2023-10-29 07:35:26 +00:00
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
const path = require("path");
|
|
|
|
const fs = require("fs");
|
|
|
|
const {
|
|
|
|
execSync,
|
|
|
|
spawnSync,
|
|
|
|
spawn,
|
|
|
|
execFile,
|
|
|
|
execFileSync,
|
|
|
|
ChildProcess,
|
|
|
|
} = require("child_process");
|
|
|
|
const colors = require("../utils/console-colors");
|
2023-11-01 05:01:17 +00:00
|
|
|
const kill = require("kill-port");
|
2023-10-29 07:35:26 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
let redeployments = 0;
|
|
|
|
|
|
|
|
/** @type {NodeJS.Signals | number} */
|
|
|
|
const KILL_SIGNAL = "SIGTERM";
|
2023-11-01 05:01:17 +00:00
|
|
|
// const KILL_SIGNAL = "SIGINT";
|
2023-10-29 10:49:04 +00:00
|
|
|
|
|
|
|
/** @type {ChildProcess | null} */
|
|
|
|
let childProcess = null;
|
|
|
|
|
2023-11-01 05:01:17 +00:00
|
|
|
const pTitle = "nodecid";
|
|
|
|
process.title = pTitle;
|
|
|
|
|
2023-10-29 07:35:26 +00:00
|
|
|
/**
|
|
|
|
* # Start the process
|
|
|
|
* @param {object} param0
|
|
|
|
* @param {string} param0.command
|
|
|
|
* @param {string[] | string} param0.preflight
|
|
|
|
* @param {string} param0.redeploy_file
|
2023-11-01 05:01:17 +00:00
|
|
|
* @param {string | number} [param0.port] - The port to kill on rebuild
|
2023-10-29 12:04:21 +00:00
|
|
|
* @param {boolean} [param0.first_run] - Whether to run the preflight on first run. Default `false`
|
2023-10-29 07:35:26 +00:00
|
|
|
*/
|
2023-10-29 12:04:21 +00:00
|
|
|
function startProcess({ command, preflight, redeploy_file, port, first_run }) {
|
2023-10-29 07:35:26 +00:00
|
|
|
try {
|
2023-10-29 12:04:21 +00:00
|
|
|
if (first_run) {
|
|
|
|
console.log("First Run ...");
|
|
|
|
const runPreflight = preflightFn(preflight);
|
|
|
|
}
|
2023-10-29 07:35:26 +00:00
|
|
|
|
|
|
|
if (!preflight) {
|
2023-10-29 10:49:04 +00:00
|
|
|
console.log(
|
|
|
|
`${colors.FgRed}Error:${colors.Reset} No preflight included in config file. If you don't want to run any preflight command simply add an empty array.`
|
|
|
|
);
|
2023-10-29 07:35:26 +00:00
|
|
|
process.exit();
|
|
|
|
}
|
|
|
|
|
|
|
|
childProcess = run(command);
|
|
|
|
|
|
|
|
if (!childProcess) {
|
|
|
|
console.log(
|
|
|
|
`${colors.FgRed}Error:${colors.Reset} Process couldn't start. Exiting...`
|
|
|
|
);
|
|
|
|
process.exit();
|
|
|
|
}
|
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
console.log("Watching", redeploy_file);
|
2023-10-29 07:35:26 +00:00
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
fs.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => {
|
|
|
|
console.log(`${colors.BgBlue}File Changed${colors.Reset}`);
|
2023-10-29 07:35:26 +00:00
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
if (redeployments == 0) return;
|
|
|
|
|
|
|
|
if (childProcess) {
|
|
|
|
console.log("******************************");
|
2023-10-29 07:35:26 +00:00
|
|
|
console.log(
|
2023-10-29 10:49:04 +00:00
|
|
|
`******** ${colors.FgBlue}Rebuilding ${colors.FgMagenta}${redeployments}${colors.Reset} ********`
|
2023-10-29 07:35:26 +00:00
|
|
|
);
|
2023-10-29 10:49:04 +00:00
|
|
|
console.log("******************************");
|
2023-10-29 07:35:26 +00:00
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
try {
|
|
|
|
const runPreflight = preflightFn(preflight);
|
|
|
|
|
2023-10-29 12:26:29 +00:00
|
|
|
if (!runPreflight) {
|
|
|
|
// TODO: Action to take if preflight fails
|
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
console.log(
|
2023-10-29 14:54:24 +00:00
|
|
|
`${colors.FgRed}Error:${colors.Reset} Preflight Failed.`
|
2023-10-29 10:49:04 +00:00
|
|
|
);
|
2023-10-29 12:27:53 +00:00
|
|
|
} else {
|
|
|
|
killChild(port).then((kill) => {
|
|
|
|
if (kill) {
|
|
|
|
childProcess = run(command);
|
|
|
|
} else {
|
|
|
|
process.exit();
|
|
|
|
}
|
|
|
|
});
|
2023-10-29 10:49:04 +00:00
|
|
|
}
|
|
|
|
} catch (/** @type {*} */ error) {
|
|
|
|
console.log(
|
|
|
|
`${colors.FgRed}Error:${colors.Reset} killing child processes => ${error.message}`
|
|
|
|
);
|
|
|
|
process.exit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (/** @type {*} */ error) {
|
|
|
|
console.log(
|
|
|
|
`${colors.FgRed}Error:${colors.Reset} First run failed! => ${error.message}`
|
|
|
|
);
|
|
|
|
}
|
2023-10-29 07:35:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ## Preflight Function
|
|
|
|
* @param {string} command
|
|
|
|
* @returns {ChildProcess | null}
|
|
|
|
*/
|
|
|
|
function run(command) {
|
2023-10-29 10:49:04 +00:00
|
|
|
console.log("\n******************************");
|
|
|
|
console.log(
|
|
|
|
`****** ${colors.FgGreen}Starting App ...${colors.Reset} ******`
|
|
|
|
);
|
|
|
|
console.log("******************************\n");
|
|
|
|
|
2023-10-29 07:35:26 +00:00
|
|
|
const startCommandArray = command.split(" ").filter((str) => str.trim());
|
|
|
|
|
|
|
|
try {
|
2023-10-29 10:49:04 +00:00
|
|
|
const firstCommand = startCommandArray.shift();
|
2023-10-29 07:35:26 +00:00
|
|
|
|
|
|
|
if (!firstCommand) {
|
|
|
|
throw new Error("No Starting Command Found in command string!");
|
|
|
|
}
|
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
let childProcess = spawn(firstCommand, startCommandArray, {
|
2023-10-29 07:35:26 +00:00
|
|
|
stdio: "inherit",
|
2023-11-01 05:01:17 +00:00
|
|
|
killSignal: KILL_SIGNAL,
|
2023-10-29 07:35:26 +00:00
|
|
|
});
|
|
|
|
|
2023-11-01 05:01:17 +00:00
|
|
|
// let childProcess = execSync(command, {
|
|
|
|
// stdio: "inherit",
|
|
|
|
// });
|
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
redeployments++;
|
|
|
|
|
2023-10-29 07:35:26 +00:00
|
|
|
return childProcess;
|
|
|
|
} catch (/** @type {*} */ error) {
|
|
|
|
console.log(
|
|
|
|
`${colors.FgRed}Error:${colors.Reset} running start command => ${error.message}`
|
|
|
|
);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ## Preflight Function
|
|
|
|
* @param {string[] | string} preflight
|
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
function preflightFn(preflight) {
|
|
|
|
console.log("Preflight Running ...");
|
|
|
|
|
|
|
|
/** @type {import("child_process").ExecSyncOptions} */
|
|
|
|
const options = {
|
|
|
|
cwd: process.cwd(),
|
|
|
|
stdio: "inherit",
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (typeof preflight == "string") {
|
|
|
|
execFileSync(preflight, options);
|
|
|
|
} else if (typeof preflight == "object" && preflight?.[0]) {
|
2023-10-29 12:26:29 +00:00
|
|
|
for (let i = 0; i < preflight.length; i++) {
|
|
|
|
const cmd = preflight[i];
|
2023-10-29 11:36:35 +00:00
|
|
|
try {
|
2023-10-29 12:04:21 +00:00
|
|
|
const execCmd = execSync(cmd, options);
|
2023-10-29 11:36:35 +00:00
|
|
|
} catch (error) {
|
|
|
|
console.log(
|
|
|
|
`${colors.FgRed}Error:${colors.Reset} Preflight command ${cmd} Failed! => ${error.message}`
|
|
|
|
);
|
2023-10-29 12:26:29 +00:00
|
|
|
return false;
|
|
|
|
break;
|
2023-10-29 11:36:35 +00:00
|
|
|
}
|
2023-10-29 12:26:29 +00:00
|
|
|
}
|
2023-10-29 07:35:26 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} catch (error) {
|
|
|
|
console.log(
|
|
|
|
`${colors.FgRed}Error:${colors.Reset} Preflight Failed! => ${error.message}`
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
|
2023-10-29 10:49:04 +00:00
|
|
|
/**
|
2023-11-01 05:01:17 +00:00
|
|
|
* ## Kill Child Process Function
|
2023-10-29 10:49:04 +00:00
|
|
|
* @param {string | number} [port]
|
|
|
|
* @returns {Promise<boolean>}
|
|
|
|
*/
|
|
|
|
async function killChild(port) {
|
|
|
|
if (!childProcess) return false;
|
|
|
|
|
|
|
|
try {
|
|
|
|
const childProcessPID = childProcess.pid;
|
2023-11-01 05:01:17 +00:00
|
|
|
childProcess.kill();
|
2023-10-29 10:49:04 +00:00
|
|
|
|
2023-11-01 05:01:17 +00:00
|
|
|
if (port) {
|
|
|
|
await kill(Number(port));
|
|
|
|
}
|
2023-10-29 10:49:04 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
} catch (error) {
|
|
|
|
console.log(
|
|
|
|
`${colors.FgRed}Error:${colors.Reset} Child Process couldn't be killed! ${error.message}`
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////
|
|
|
|
|
2023-10-29 07:35:26 +00:00
|
|
|
module.exports = startProcess;
|