From ee3ebf8d17a600746d5e51ba531565d5bb035b2b Mon Sep 17 00:00:00 2001 From: Niko Sams Date: Tue, 19 Nov 2024 11:09:28 +0100 Subject: [PATCH] Watch dev-pm.config.js and update in running daemon (#98) This allows modifications without having to shutdown the deamon. - processes are not restarted if the script command changes - processes are stopped if the script is removed - processes are not started if a new script is added - identifier for updates is the name of a script --- .changeset/spotty-mirrors-care.md | 11 ++++++++ src/commands/start-daemon.command.ts | 40 +++++++++++++++++++++++----- src/daemon-command/script.ts | 4 +++ 3 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 .changeset/spotty-mirrors-care.md diff --git a/.changeset/spotty-mirrors-care.md b/.changeset/spotty-mirrors-care.md new file mode 100644 index 0000000..6d47d39 --- /dev/null +++ b/.changeset/spotty-mirrors-care.md @@ -0,0 +1,11 @@ +--- +"@comet/dev-process-manager": minor +--- + +Watch dev-pm.config.js and update in running daemon + +This allows modifications without having to shutdown the deamon. +- processes are not restarted if the script command changes +- processes are stopped if the script is removed +- processes are not started if a new script is added +- identifier for updates is the name of a script diff --git a/src/commands/start-daemon.command.ts b/src/commands/start-daemon.command.ts index 43f97ce..e8f93fb 100644 --- a/src/commands/start-daemon.command.ts +++ b/src/commands/start-daemon.command.ts @@ -1,5 +1,5 @@ import colors from "colors"; -import { existsSync } from "fs"; +import { existsSync, watchFile } from "fs"; import { createServer, Server } from "net"; import { Config } from "../config.type"; @@ -21,15 +21,43 @@ export interface Daemon { export const startDaemon = async (): Promise => { process.chdir(findConfigDir()); const pmConfigFileName = "dev-pm.config.js"; - const { scripts: scriptDefinitions }: Config = await import(`${process.cwd()}/${pmConfigFileName}`); - const scripts = scriptDefinitions.map((scriptDefinition, id) => { - return new Script({ ...scriptDefinition, id }); - }); + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { scripts: scriptDefinitions }: Config = require(`${process.cwd()}/${pmConfigFileName}`); const daemon: Daemon = { - scripts, + scripts: scriptDefinitions.map((scriptDefinition, id) => { + return new Script({ ...scriptDefinition, id }); + }), server: undefined, }; + watchFile(`${process.cwd()}/${pmConfigFileName}`, async () => { + console.log(`${pmConfigFileName} file changed, reloading scripts`); + delete require.cache[require.resolve(`${process.cwd()}/${pmConfigFileName}`)]; + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { scripts: scriptDefinitions }: Config = require(`${process.cwd()}/${pmConfigFileName}`); + + daemon.scripts = daemon.scripts.filter((script) => { + if (!scriptDefinitions.find((s) => s.name === script.name)) { + console.log("Removing script", script.name); + script.killProcess(); + return false; + } else { + return true; + } + }); + + scriptDefinitions.forEach((scriptDefinition, id) => { + const script = daemon.scripts.find((s) => s.name === scriptDefinition.name); + if (script) { + console.log("Updating script definition", script.name); + script.updateScriptDefinition({ ...scriptDefinition, id }); + } else { + console.log("Adding new script", scriptDefinition.name); + daemon.scripts.push(new Script({ ...scriptDefinition, id })); + } + }); + }); + if (existsSync(`.pm.sock`)) { console.log( "Could not start dev-pm server. A '.pm.sock' file already exists. \nThere are 2 possible reasons for this:\nA: Another dev-pm instance is already running. \nB: dev-pm crashed and left the file behind. In this case please remove the file manually.", diff --git a/src/daemon-command/script.ts b/src/daemon-command/script.ts index 5c69e3e..3b75485 100644 --- a/src/daemon-command/script.ts +++ b/src/daemon-command/script.ts @@ -30,6 +30,10 @@ export class Script { this.logPrefix = color(`${this.name}: `); } + updateScriptDefinition(scriptDefinition: ScriptDefinition) { + this.scriptDefinition = scriptDefinition; + } + get id(): number { return this.scriptDefinition.id; }