"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const child_process_1 = require("child_process"); const readline_1 = __importDefault(require("readline")); const console_colors_1 = __importDefault(require("./console-colors")); setInterval(() => { console.log(`Batchrun Running for ${process.uptime().toLocaleString()}s ...`); }, 60000); if ((_a = process.argv[process.argv.length - 1]) === null || _a === void 0 ? void 0 : _a.match(/^--version$|^-v$/)) { console.log(`Batchrun v${require("./package.json").version}`); process.exit(); } const processesStrings = []; let processes = []; const isWindows = process.platform.match(/win/i); const isMac = process.platform.match(/darwin/i); const isLinux = process.platform.match(/linux/i); //////////////////////////////////////////// //////////////////////////////////////////// //////////////////////////////////////////// const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout, }); rl.on("line", (input) => { readCommands(input); }); /** * Read Lines and execute commands * @param {string} input * @returns */ function readCommands(input) { if (input === null || input === void 0 ? void 0 : input.match(/^(reload|restart|reboot|r)$/i)) { console.log(` - ${console_colors_1.default.FgBlue}Reloading processes ...${console_colors_1.default.Reset}`); restartAll(); } else if (input === null || input === void 0 ? void 0 : input.match(/^(reload|restart|reboot|r) \d/i)) { const processedIndexesString = input.split(" ")[1]; const processedIndexes = processedIndexesString ? processedIndexesString.split(",") : null; if (!(processedIndexes === null || processedIndexes === void 0 ? void 0 : processedIndexes.length)) { console.log(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} No processes to reload`); return; } else { console.log(` - ${console_colors_1.default.FgBlue}Reloading processes ${processedIndexesString} ...${console_colors_1.default.Reset}`); processedIndexes.forEach((index) => { restartOne(parseInt(index)); }); console.log(` - ${console_colors_1.default.FgGreen}Processes Restarted Successfully ${processedIndexesString} ...${console_colors_1.default.Reset}`); } } if (input === null || input === void 0 ? void 0 : input.match(/^kill$/i)) { console.log(` - ${console_colors_1.default.FgYellow}Killing processes ...${console_colors_1.default.Reset}`); process.exit(); } else if (input === null || input === void 0 ? void 0 : input.match(/^kill \d/i)) { const processedIndexesString = input.split(" ")[1]; const processedIndexes = processedIndexesString ? processedIndexesString.split(",") : null; if (!(processedIndexes === null || processedIndexes === void 0 ? void 0 : processedIndexes.length)) { console.log(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} No processes to reload`); return; } else { console.log(` - ${console_colors_1.default.FgYellow}Killing processes ${processedIndexesString} ...${console_colors_1.default.Reset}`); processedIndexes.forEach((index) => { killOne(index); }); console.log(` - ${console_colors_1.default.FgGreen}Processes Killed ${processedIndexesString} ...${console_colors_1.default.Reset}`); } } } process.stdin.on("keypress", (character, key) => { if (key.ctrl && key.name === "r") { console.log(` - ${console_colors_1.default.FgBlue}Reloading processes ...${console_colors_1.default.Reset}`); restartAll(); } }); /** * Cleanup function to kill all child processes */ function cleanupChildProcesses() { for (const childProcess of processes) { try { if (childProcess.pid) { console.log(` - ${console_colors_1.default.FgYellow}Killing process PID: ${childProcess.pid}${console_colors_1.default.Reset}`); killProcessForce(childProcess.pid); } childProcess.kill(); } catch (error) { console.error(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Failed to kill process PID: ${childProcess.pid}`); } } processes = []; } process.on("exit", (code) => { console.log(` - ${console_colors_1.default.FgBlue}Process exited with code ${code}${console_colors_1.default.Reset}`); rl.close(); cleanupChildProcesses(); }); process.on("SIGINT", () => { console.log(` - ${console_colors_1.default.FgYellow}SIGINT received, exiting...${console_colors_1.default.Reset}`); process.exit(); }); process.on("SIGTERM", () => { console.log(` - ${console_colors_1.default.FgYellow}SIGTERM received, exiting...${console_colors_1.default.Reset}`); process.exit(); }); //////////////////////////////////////////// //////////////////////////////////////////// //////////////////////////////////////////// const argvProcessListIndex = process.argv.indexOf("batch-run") + 1; const argvProcessList = process.argv.at(-1); const processesFilePath = path_1.default.resolve(process.cwd(), "batchrun.config.json"); if ((argvProcessList === null || argvProcessList === void 0 ? void 0 : argvProcessList.match(/batchrun/i)) && !fs_1.default.existsSync(processesFilePath)) { console.error(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} No arguments to run`); process.exit(1); } if (fs_1.default.existsSync(processesFilePath)) { const processesFile = fs_1.default.readFileSync(processesFilePath, "utf8"); const processesArray = JSON.parse(processesFile); for (let i = 0; i < processesArray.length; i++) { const processString = processesArray[i]; const strippedProcessString = processString.trim(); processesStrings.push(strippedProcessString); } } else if (argvProcessList) { const processesArray = argvProcessList.split(","); for (let i = 0; i < processesArray.length; i++) { const processString = processesArray[i]; const strippedProcessString = processString.trim(); processesStrings.push(strippedProcessString); } } else { console.error(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} No arguments to run or \`batchrun.config.json\` file present`); process.exit(1); } if (!(processesStrings === null || processesStrings === void 0 ? void 0 : processesStrings[0])) { console.error(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} No processes to run`); process.exit(1); } /** @type {import("child_process").SpawnOptions} */ const spawnOptions = { cwd: process.cwd(), shell: isWindows ? "bash.exe" : undefined, stdio: ["pipe", "inherit", "inherit"], detached: false, }; /** * Start all processes */ function startProcesses() { for (let i = 0; i < processesStrings.length; i++) { const processString = processesStrings[i]; const processStringArray = processString.split(" "); const targetProcess = processStringArray.shift(); if (targetProcess) { const childProcess = (0, child_process_1.spawn)(targetProcess, processStringArray, spawnOptions); if (childProcess) { childProcess.on("exit", (code, signal) => { console.log(` - ${console_colors_1.default.FgRed}Process ${i} exited with code ${code} and signal ${signal}${console_colors_1.default.Reset}`); }); childProcess.on("error", (err) => { console.error(` - ${console_colors_1.default.FgYellow}Error:${console_colors_1.default.Reset} Failed to start process ${i}: ${err.message}`); }); childProcess.on("close", (code, signal) => { console.log(` - ${console_colors_1.default.FgRed}Process ${i} closed with code ${code} and signal ${signal}${console_colors_1.default.Reset}`); }); processes.push(childProcess); } else { console.error(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Failed to start process ${i}`); process.exit(1); } } else { console.error(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} A target process is not defined in \`${processString}\``); process.exit(1); } } } /** * Restart All Processes */ function restartAll() { for (let i = 0; i < processes.length; i++) { const childProcess = processes[i]; try { if (childProcess.pid) killProcessForce(childProcess.pid); childProcess.kill(); // processes.splice(i, 1); } catch (error) { console.log(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Failed to kill process ${childProcess.pid}`); process.exit(); } } console.log(` - ${console_colors_1.default.FgGreen}Restarted ${processes.length} processes${console_colors_1.default.Reset}`); processes = []; setTimeout(() => { startProcesses(); }, 500); } /** * Restart a single process * @param {string} index */ function restartOne(index) { const childProcess = processes[index]; try { if (childProcess.pid) killProcessForce(childProcess.pid); childProcess.kill(); } catch (error) { console.log(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Failed to kill process ${childProcess.pid}`); process.exit(); } const processString = processesStrings[index]; const processStringArray = processString.split(" "); const targetProcess = processStringArray.shift(); if (!targetProcess) return; const newChildProcess = (0, child_process_1.spawn)(targetProcess, processStringArray, spawnOptions); processes.splice(index, 1, newChildProcess); } /** * Kill a single process * @param {string} index */ function killOne(index) { const childProcess = processes[parseInt(index)]; if (childProcess.pid) killProcessForce(childProcess.pid); childProcess.kill(); try { } catch (error) { console.log(` - ${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Failed to kill process ${childProcess.pid}`); process.exit(); } } /** * Kill a process by PID * @param {number} pid */ function killProcessForce(pid) { if (typeof pid !== "number") { return; } try { if (isWindows) { (0, child_process_1.execSync)(`taskkill /F /PID ${pid} /T`); } else { (0, child_process_1.execSync)(`kill -9 ${pid}`); } } catch (error) { } } console.log(` - ${console_colors_1.default.FgGreen}Started ${processesStrings.length} processes${console_colors_1.default.Reset}`); startProcesses();