Refactor to typescript
This commit is contained in:
		
							parent
							
								
									5f589f89d8
								
							
						
					
					
						commit
						09e8b1f6d7
					
				
							
								
								
									
										2
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| @moduletrace:registry=https://git.tben.me/api/packages/moduletrace/npm/ | ||||
| //git.tben.me/api/packages/moduletrace/npm/:_authToken=${GITBEN_NPM_TOKEN} | ||||
							
								
								
									
										
											BIN
										
									
								
								bin/nodecid
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/nodecid
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										263
									
								
								deploy/start.js
									
									
									
									
									
								
							
							
						
						
									
										263
									
								
								deploy/start.js
									
									
									
									
									
								
							| @ -1,263 +0,0 @@ | ||||
| // @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"); | ||||
| const kill = require("kill-port"); | ||||
| 
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| 
 | ||||
| let redeployments = 0; | ||||
| 
 | ||||
| /** @type {NodeJS.Signals | number} */ | ||||
| const KILL_SIGNAL = "SIGTERM"; | ||||
| // const KILL_SIGNAL = "SIGINT";
 | ||||
| 
 | ||||
| /** @type {ChildProcess | null} */ | ||||
| let childProcess = null; | ||||
| 
 | ||||
| const pTitle = "nodecid"; | ||||
| process.title = pTitle; | ||||
| 
 | ||||
| /** | ||||
|  * # Start the process | ||||
|  * @param {object} param0 | ||||
|  * @param {string} param0.command | ||||
|  * @param {string[] | string} param0.preflight | ||||
|  * @param {string[] | string} [param0.postflight] | ||||
|  * @param {string} param0.redeploy_file | ||||
|  * @param {string | number | (string | number)[]} [param0.port] - The port to kill on rebuild | ||||
|  * @param {boolean} [param0.first_run] - Whether to run the preflight on first run. Default `false` | ||||
|  */ | ||||
| function startProcess({ | ||||
|     command, | ||||
|     preflight, | ||||
|     postflight, | ||||
|     redeploy_file, | ||||
|     port, | ||||
|     first_run, | ||||
| }) { | ||||
|     try { | ||||
|         if (first_run) { | ||||
|             console.log("First Run ..."); | ||||
|             const runPreflight = preflightFn(preflight); | ||||
|         } | ||||
| 
 | ||||
|         if (!preflight) { | ||||
|             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.` | ||||
|             ); | ||||
|             process.exit(); | ||||
|         } | ||||
| 
 | ||||
|         childProcess = run(command); | ||||
| 
 | ||||
|         if (!childProcess) { | ||||
|             console.log( | ||||
|                 `${colors.FgRed}Error:${colors.Reset} Process couldn't start. Exiting...` | ||||
|             ); | ||||
|             process.exit(); | ||||
|         } | ||||
| 
 | ||||
|         console.log("Watching", redeploy_file); | ||||
| 
 | ||||
|         fs.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => { | ||||
|             console.log(`${colors.BgBlue}File Changed${colors.Reset}`); | ||||
| 
 | ||||
|             if (redeployments == 0) return; | ||||
| 
 | ||||
|             if (childProcess) { | ||||
|                 console.log("******************************"); | ||||
|                 console.log( | ||||
|                     `******** ${colors.FgBlue}Rebuilding ${colors.FgMagenta}${redeployments}${colors.Reset} ********` | ||||
|                 ); | ||||
|                 console.log("******************************"); | ||||
| 
 | ||||
|                 try { | ||||
|                     const runPreflight = preflightFn(preflight); | ||||
| 
 | ||||
|                     if (!runPreflight) { | ||||
|                         // TODO: Action to take if preflight fails
 | ||||
| 
 | ||||
|                         console.log( | ||||
|                             `${colors.FgRed}Error:${colors.Reset} Preflight Failed.` | ||||
|                         ); | ||||
|                     } else { | ||||
|                         killChild(port).then((kill) => { | ||||
|                             if (kill) { | ||||
|                                 childProcess = run(command); | ||||
| 
 | ||||
|                                 if (postflight) { | ||||
|                                     const runPostflight = preflightFn( | ||||
|                                         postflight, | ||||
|                                         true | ||||
|                                     ); | ||||
| 
 | ||||
|                                     if (!runPostflight) { | ||||
|                                         // TODO: Action to take if postflight fails
 | ||||
| 
 | ||||
|                                         console.log( | ||||
|                                             `${colors.FgRed}Error:${colors.Reset} Postflight Failed.` | ||||
|                                         ); | ||||
|                                     } | ||||
|                                 } | ||||
|                             } else { | ||||
|                                 process.exit(); | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|                 } 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}` | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| 
 | ||||
| /** | ||||
|  * ## Preflight Function | ||||
|  * @param {string} command | ||||
|  * @returns {ChildProcess | null} | ||||
|  */ | ||||
| function run(command) { | ||||
|     console.log("\n******************************"); | ||||
|     console.log( | ||||
|         `****** ${colors.FgGreen}Starting App ...${colors.Reset} ******` | ||||
|     ); | ||||
|     console.log("******************************\n"); | ||||
| 
 | ||||
|     const startCommandArray = command.split(" ").filter((str) => str.trim()); | ||||
| 
 | ||||
|     try { | ||||
|         const firstCommand = startCommandArray.shift(); | ||||
| 
 | ||||
|         if (!firstCommand) { | ||||
|             throw new Error("No Starting Command Found in command string!"); | ||||
|         } | ||||
| 
 | ||||
|         let childProcess = spawn(firstCommand, startCommandArray, { | ||||
|             stdio: "inherit", | ||||
|             killSignal: KILL_SIGNAL, | ||||
|         }); | ||||
| 
 | ||||
|         // let childProcess = execSync(command, {
 | ||||
|         //     stdio: "inherit",
 | ||||
|         // });
 | ||||
| 
 | ||||
|         redeployments++; | ||||
| 
 | ||||
|         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 | ||||
|  * @param {boolean} [postflight] | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
| function preflightFn(preflight, postflight) { | ||||
|     const tag = postflight ? "Postflight" : "Preflight"; | ||||
|     console.log(`${tag} 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]) { | ||||
|             for (let i = 0; i < preflight.length; i++) { | ||||
|                 const cmd = preflight[i]; | ||||
|                 try { | ||||
|                     const execCmd = execSync(cmd, options); | ||||
|                 } catch (error) { | ||||
|                     console.log( | ||||
|                         `${colors.FgRed}Error:${colors.Reset} ${tag} command ${cmd} Failed! => ${error.message}` | ||||
|                     ); | ||||
|                     return false; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     } catch (error) { | ||||
|         console.log( | ||||
|             `${colors.FgRed}Error:${colors.Reset} ${tag} Failed! => ${error.message}` | ||||
|         ); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| 
 | ||||
| /** | ||||
|  * ## Kill Child Process Function | ||||
|  * @param {string | number | (string | number)[]} [port] | ||||
|  * @returns {Promise<boolean>} | ||||
|  */ | ||||
| async function killChild(port) { | ||||
|     if (!childProcess) return false; | ||||
| 
 | ||||
|     try { | ||||
|         const childProcessPID = childProcess.pid; | ||||
|         childProcess.kill(); | ||||
| 
 | ||||
|         if (typeof port == "object" && port?.[0]) { | ||||
|             for (let i = 0; i < port.length; i++) { | ||||
|                 const singlePort = port[i]; | ||||
|                 await kill(Number(singlePort)); | ||||
|             } | ||||
|         } else if (port) { | ||||
|             await kill(Number(port)); | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } catch (error) { | ||||
|         console.log( | ||||
|             `${colors.FgRed}Error:${colors.Reset} Child Process couldn't be killed! ${error.message}` | ||||
|         ); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| 
 | ||||
| module.exports = startProcess; | ||||
							
								
								
									
										1
									
								
								dist/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| export {}; | ||||
							
								
								
									
										50
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| "use strict"; | ||||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
|     return (mod && mod.__esModule) ? mod : { "default": mod }; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||||
| const fs_1 = __importDefault(require("fs")); | ||||
| const path_1 = __importDefault(require("path")); | ||||
| const console_colors_1 = __importDefault(require("./utils/console-colors")); | ||||
| const start_1 = __importDefault(require("./utils/start")); | ||||
| const WORK_DIR = process.cwd(); | ||||
| function run() { | ||||
|     try { | ||||
|         const configText = fs_1.default.readFileSync(path_1.default.join(WORK_DIR, "nodecid.config.json"), "utf-8"); | ||||
|         const config = JSON.parse(configText); | ||||
|         const { start, preflight, postflight, build, redeploy_path, first_run, port, } = config; | ||||
|         /** @type {string | undefined} */ | ||||
|         let redeployFile; | ||||
|         if (!redeploy_path) { | ||||
|             const defaultRedeployPath = path_1.default.join(WORK_DIR, "REDEPLOY"); | ||||
|             const checkExistingPath = fs_1.default.existsSync(defaultRedeployPath); | ||||
|             if (!checkExistingPath) { | ||||
|                 fs_1.default.writeFileSync(defaultRedeployPath, Date.now().toString(), "utf-8"); | ||||
|             } | ||||
|             redeployFile = path_1.default.join(WORK_DIR, "REDEPLOY"); | ||||
|         } | ||||
|         else { | ||||
|             redeployFile = path_1.default.resolve(WORK_DIR, redeploy_path); | ||||
|         } | ||||
|         if (!redeployFile) | ||||
|             throw new Error("Redeploy file not found!"); | ||||
|         (0, start_1.default)({ | ||||
|             command: start, | ||||
|             preflight, | ||||
|             redeploy_file: redeployFile, | ||||
|             first_run, | ||||
|             port, | ||||
|             postflight, | ||||
|         }); | ||||
|     } | ||||
|     catch (error) { | ||||
|         console.log(`${console_colors_1.default.FgRed}ERROR:${console_colors_1.default.Reset} CI process failed! => ${error.message}`); | ||||
|     } | ||||
| } | ||||
| run(); | ||||
| process.on("exit", () => { | ||||
|     console.log("Process exiting ..."); | ||||
| }); | ||||
| process.on("beforeExit", () => { | ||||
|     console.log("Process Before exit ..."); | ||||
| }); | ||||
							
								
								
									
										1
									
								
								dist/tsconfig.tsbuildinfo
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/tsconfig.tsbuildinfo
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										13
									
								
								dist/types.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								dist/types.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| export interface NodeCIConfig { | ||||
|     start: string; | ||||
|     preflight: string[] | string; | ||||
|     postflight?: string[] | string; | ||||
|     redeploy_path?: string; | ||||
|     first_run?: boolean; | ||||
|     port?: string | number | (string | number)[]; | ||||
|     build?: NodeCIBuild; | ||||
| } | ||||
| export interface NodeCIBuild { | ||||
|     paradigm: "Next.JS" | "Remix"; | ||||
|     out_dir?: string; | ||||
| } | ||||
							
								
								
									
										2
									
								
								dist/types.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								dist/types.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| "use strict"; | ||||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||||
							
								
								
									
										28
									
								
								dist/utils/console-colors.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								dist/utils/console-colors.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| declare const colors: { | ||||
|     Reset: string; | ||||
|     Bright: string; | ||||
|     Dim: string; | ||||
|     Underscore: string; | ||||
|     Blink: string; | ||||
|     Reverse: string; | ||||
|     Hidden: string; | ||||
|     FgBlack: string; | ||||
|     FgRed: string; | ||||
|     FgGreen: string; | ||||
|     FgYellow: string; | ||||
|     FgBlue: string; | ||||
|     FgMagenta: string; | ||||
|     FgCyan: string; | ||||
|     FgWhite: string; | ||||
|     FgGray: string; | ||||
|     BgBlack: string; | ||||
|     BgRed: string; | ||||
|     BgGreen: string; | ||||
|     BgYellow: string; | ||||
|     BgBlue: string; | ||||
|     BgMagenta: string; | ||||
|     BgCyan: string; | ||||
|     BgWhite: string; | ||||
|     BgGray: string; | ||||
| }; | ||||
| export default colors; | ||||
							
								
								
									
										61
									
								
								utils/console-colors.js → dist/utils/console-colors.js
									
									
									
									
										vendored
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										61
									
								
								utils/console-colors.js → dist/utils/console-colors.js
									
									
									
									
										vendored
									
									
										
										
										Executable file → Normal file
									
								
							| @ -1,31 +1,30 @@ | ||||
| const colors = { | ||||
|     Reset: "\x1b[0m", | ||||
|     Bright: "\x1b[1m", | ||||
|     Dim: "\x1b[2m", | ||||
|     Underscore: "\x1b[4m", | ||||
|     Blink: "\x1b[5m", | ||||
|     Reverse: "\x1b[7m", | ||||
|     Hidden: "\x1b[8m", | ||||
| 
 | ||||
|     FgBlack: "\x1b[30m", | ||||
|     FgRed: "\x1b[31m", | ||||
|     FgGreen: "\x1b[32m", | ||||
|     FgYellow: "\x1b[33m", | ||||
|     FgBlue: "\x1b[34m", | ||||
|     FgMagenta: "\x1b[35m", | ||||
|     FgCyan: "\x1b[36m", | ||||
|     FgWhite: "\x1b[37m", | ||||
|     FgGray: "\x1b[90m", | ||||
| 
 | ||||
|     BgBlack: "\x1b[40m", | ||||
|     BgRed: "\x1b[41m", | ||||
|     BgGreen: "\x1b[42m", | ||||
|     BgYellow: "\x1b[43m", | ||||
|     BgBlue: "\x1b[44m", | ||||
|     BgMagenta: "\x1b[45m", | ||||
|     BgCyan: "\x1b[46m", | ||||
|     BgWhite: "\x1b[47m", | ||||
|     BgGray: "\x1b[100m", | ||||
| }; | ||||
| 
 | ||||
| module.exports = colors; | ||||
| "use strict"; | ||||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||||
| const colors = { | ||||
|     Reset: "\x1b[0m", | ||||
|     Bright: "\x1b[1m", | ||||
|     Dim: "\x1b[2m", | ||||
|     Underscore: "\x1b[4m", | ||||
|     Blink: "\x1b[5m", | ||||
|     Reverse: "\x1b[7m", | ||||
|     Hidden: "\x1b[8m", | ||||
|     FgBlack: "\x1b[30m", | ||||
|     FgRed: "\x1b[31m", | ||||
|     FgGreen: "\x1b[32m", | ||||
|     FgYellow: "\x1b[33m", | ||||
|     FgBlue: "\x1b[34m", | ||||
|     FgMagenta: "\x1b[35m", | ||||
|     FgCyan: "\x1b[36m", | ||||
|     FgWhite: "\x1b[37m", | ||||
|     FgGray: "\x1b[90m", | ||||
|     BgBlack: "\x1b[40m", | ||||
|     BgRed: "\x1b[41m", | ||||
|     BgGreen: "\x1b[42m", | ||||
|     BgYellow: "\x1b[43m", | ||||
|     BgBlue: "\x1b[44m", | ||||
|     BgMagenta: "\x1b[45m", | ||||
|     BgCyan: "\x1b[46m", | ||||
|     BgWhite: "\x1b[47m", | ||||
|     BgGray: "\x1b[100m", | ||||
| }; | ||||
| exports.default = colors; | ||||
							
								
								
									
										6
									
								
								dist/utils/kill-child.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								dist/utils/kill-child.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| /** | ||||
|  * ## Kill Child Process Function | ||||
|  * @param {string | number | (string | number)[]} [port] | ||||
|  * @returns {Promise<boolean>} | ||||
|  */ | ||||
| export default function killChild(port?: string | number | (string | number)[]): Promise<boolean>; | ||||
							
								
								
									
										49
									
								
								dist/utils/kill-child.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								dist/utils/kill-child.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| "use strict"; | ||||
| var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||||
|     function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||||
|     return new (P || (P = Promise))(function (resolve, reject) { | ||||
|         function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||||
|         function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||||
|         function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||||
|         step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||||
|     }); | ||||
| }; | ||||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
|     return (mod && mod.__esModule) ? mod : { "default": mod }; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||||
| exports.default = killChild; | ||||
| const console_colors_1 = __importDefault(require("./console-colors")); | ||||
| const kill_port_1 = __importDefault(require("kill-port")); | ||||
| let childProcess = null; | ||||
| const pTitle = "nodecid"; | ||||
| process.title = pTitle; | ||||
| /** | ||||
|  * ## Kill Child Process Function | ||||
|  * @param {string | number | (string | number)[]} [port] | ||||
|  * @returns {Promise<boolean>} | ||||
|  */ | ||||
| function killChild(port) { | ||||
|     return __awaiter(this, void 0, void 0, function* () { | ||||
|         if (!childProcess) | ||||
|             return false; | ||||
|         try { | ||||
|             const childProcessPID = childProcess.pid; | ||||
|             childProcess.kill(); | ||||
|             if (typeof port == "object" && (port === null || port === void 0 ? void 0 : port[0])) { | ||||
|                 for (let i = 0; i < port.length; i++) { | ||||
|                     const singlePort = port[i]; | ||||
|                     yield (0, kill_port_1.default)(Number(singlePort)); | ||||
|                 } | ||||
|             } | ||||
|             else if (port) { | ||||
|                 yield (0, kill_port_1.default)(Number(port)); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         catch (error) { | ||||
|             console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Child Process couldn't be killed! ${error.message}`); | ||||
|             return false; | ||||
|         } | ||||
|     }); | ||||
| } | ||||
							
								
								
									
										7
									
								
								dist/utils/preflight.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								dist/utils/preflight.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| /** | ||||
|  * ## Preflight Function | ||||
|  * @param {string[] | string} preflight | ||||
|  * @param {boolean} [postflight] | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
| export default function preflightFn(preflight?: string[] | string, postflight?: boolean): boolean; | ||||
							
								
								
									
										45
									
								
								dist/utils/preflight.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								dist/utils/preflight.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| "use strict"; | ||||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
|     return (mod && mod.__esModule) ? mod : { "default": mod }; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||||
| exports.default = preflightFn; | ||||
| const child_process_1 = require("child_process"); | ||||
| const console_colors_1 = __importDefault(require("../utils/console-colors")); | ||||
| /** | ||||
|  * ## Preflight Function | ||||
|  * @param {string[] | string} preflight | ||||
|  * @param {boolean} [postflight] | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
| function preflightFn(preflight, postflight) { | ||||
|     const tag = postflight ? "Postflight" : "Preflight"; | ||||
|     console.log(`${tag} Running ...`); | ||||
|     const options = { | ||||
|         cwd: process.cwd(), | ||||
|         stdio: "inherit", | ||||
|     }; | ||||
|     try { | ||||
|         if (typeof preflight == "string") { | ||||
|             (0, child_process_1.execFileSync)(preflight, options); | ||||
|         } | ||||
|         else if (typeof preflight == "object" && (preflight === null || preflight === void 0 ? void 0 : preflight[0])) { | ||||
|             for (let i = 0; i < preflight.length; i++) { | ||||
|                 const cmd = preflight[i]; | ||||
|                 try { | ||||
|                     const execCmd = (0, child_process_1.execSync)(cmd, options); | ||||
|                 } | ||||
|                 catch (error) { | ||||
|                     console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} ${tag} command ${cmd} Failed! => ${error.message}`); | ||||
|                     return false; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|     catch (error) { | ||||
|         console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} ${tag} Failed! => ${error.message}`); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										7
									
								
								dist/utils/run.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								dist/utils/run.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| import { ChildProcess } from "child_process"; | ||||
| /** | ||||
|  * ## Preflight Function | ||||
|  * @param {string} command | ||||
|  * @returns {ChildProcess | null} | ||||
|  */ | ||||
| export default function run(command: string): ChildProcess | null; | ||||
							
								
								
									
										39
									
								
								dist/utils/run.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								dist/utils/run.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| "use strict"; | ||||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
|     return (mod && mod.__esModule) ? mod : { "default": mod }; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||||
| exports.default = run; | ||||
| const child_process_1 = require("child_process"); | ||||
| const console_colors_1 = __importDefault(require("./console-colors")); | ||||
| let redeployments = 0; | ||||
| const KILL_SIGNAL = "SIGTERM"; | ||||
| const pTitle = "nodecid"; | ||||
| process.title = pTitle; | ||||
| /** | ||||
|  * ## Preflight Function | ||||
|  * @param {string} command | ||||
|  * @returns {ChildProcess | null} | ||||
|  */ | ||||
| function run(command) { | ||||
|     console.log("\n******************************"); | ||||
|     console.log(`****** ${console_colors_1.default.FgGreen}Starting App ...${console_colors_1.default.Reset} ******`); | ||||
|     console.log("******************************\n"); | ||||
|     const startCommandArray = command.split(" ").filter((str) => str.trim()); | ||||
|     try { | ||||
|         const firstCommand = startCommandArray.shift(); | ||||
|         if (!firstCommand) { | ||||
|             throw new Error("No Starting Command Found in command string!"); | ||||
|         } | ||||
|         let childProcess = (0, child_process_1.spawn)(firstCommand, startCommandArray, { | ||||
|             stdio: "inherit", | ||||
|             killSignal: KILL_SIGNAL, | ||||
|         }); | ||||
|         redeployments++; | ||||
|         return childProcess; | ||||
|     } | ||||
|     catch (error) { | ||||
|         console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} running start command => ${error.message}`); | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										18
									
								
								dist/utils/start.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								dist/utils/start.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| /** | ||||
|  * # Start the process | ||||
|  * @param {object} param0 | ||||
|  * @param {string} param0.command | ||||
|  * @param {string[] | string} param0.preflight | ||||
|  * @param {string[] | string} [param0.postflight] | ||||
|  * @param {string} param0.redeploy_file | ||||
|  * @param {string | number | (string | number)[]} [param0.port] - The port to kill on rebuild | ||||
|  * @param {boolean} [param0.first_run] - Whether to run the preflight on first run. Default `false` | ||||
|  */ | ||||
| export default function startProcess({ command, preflight, postflight, redeploy_file, port, first_run, }: { | ||||
|     command: string; | ||||
|     preflight: string[] | string; | ||||
|     postflight?: string[] | string; | ||||
|     redeploy_file: string; | ||||
|     port?: string | number | (string | number)[]; | ||||
|     first_run?: boolean; | ||||
| }): void; | ||||
							
								
								
									
										84
									
								
								dist/utils/start.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								dist/utils/start.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | ||||
| "use strict"; | ||||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
|     return (mod && mod.__esModule) ? mod : { "default": mod }; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||||
| exports.default = startProcess; | ||||
| const fs_1 = __importDefault(require("fs")); | ||||
| const console_colors_1 = __importDefault(require("./console-colors")); | ||||
| const preflight_1 = __importDefault(require("./preflight")); | ||||
| const run_1 = __importDefault(require("./run")); | ||||
| const kill_child_1 = __importDefault(require("./kill-child")); | ||||
| let redeployments = 0; | ||||
| let childProcess = null; | ||||
| const pTitle = "nodecid"; | ||||
| process.title = pTitle; | ||||
| /** | ||||
|  * # Start the process | ||||
|  * @param {object} param0 | ||||
|  * @param {string} param0.command | ||||
|  * @param {string[] | string} param0.preflight | ||||
|  * @param {string[] | string} [param0.postflight] | ||||
|  * @param {string} param0.redeploy_file | ||||
|  * @param {string | number | (string | number)[]} [param0.port] - The port to kill on rebuild | ||||
|  * @param {boolean} [param0.first_run] - Whether to run the preflight on first run. Default `false` | ||||
|  */ | ||||
| function startProcess({ command, preflight, postflight, redeploy_file, port, first_run, }) { | ||||
|     try { | ||||
|         if (first_run) { | ||||
|             console.log("First Run ..."); | ||||
|             const runPreflight = (0, preflight_1.default)(preflight); | ||||
|         } | ||||
|         if (!preflight) { | ||||
|             console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} No preflight included in config file. If you don't want to run any preflight command simply add an empty array.`); | ||||
|             process.exit(); | ||||
|         } | ||||
|         childProcess = (0, run_1.default)(command); | ||||
|         if (!childProcess) { | ||||
|             console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Process couldn't start. Exiting...`); | ||||
|             process.exit(); | ||||
|         } | ||||
|         console.log("Watching", redeploy_file); | ||||
|         fs_1.default.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => { | ||||
|             console.log(`${console_colors_1.default.BgBlue}File Changed${console_colors_1.default.Reset}`); | ||||
|             if (redeployments == 0) | ||||
|                 return; | ||||
|             if (childProcess) { | ||||
|                 console.log("******************************"); | ||||
|                 console.log(`******** ${console_colors_1.default.FgBlue}Rebuilding ${console_colors_1.default.FgMagenta}${redeployments}${console_colors_1.default.Reset} ********`); | ||||
|                 console.log("******************************"); | ||||
|                 try { | ||||
|                     const runPreflight = (0, preflight_1.default)(preflight); | ||||
|                     if (!runPreflight) { | ||||
|                         // TODO: Action to take if preflight fails
 | ||||
|                         console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Preflight Failed.`); | ||||
|                     } | ||||
|                     else { | ||||
|                         (0, kill_child_1.default)(port).then((kill) => { | ||||
|                             if (kill) { | ||||
|                                 childProcess = (0, run_1.default)(command); | ||||
|                                 if (postflight) { | ||||
|                                     const runPostflight = (0, preflight_1.default)(postflight, true); | ||||
|                                     if (!runPostflight) { | ||||
|                                         // TODO: Action to take if postflight fails
 | ||||
|                                         console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Postflight Failed.`); | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             else { | ||||
|                                 process.exit(); | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (error) { | ||||
|                     console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} killing child processes => ${error.message}`); | ||||
|                     process.exit(); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     catch (error) { | ||||
|         console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} First run failed! => ${error.message}`); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										1
									
								
								dist/utils/triggers/github.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/utils/triggers/github.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| declare function githubWebhook(): boolean; | ||||
							
								
								
									
										4
									
								
								dist/utils/triggers/github.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								dist/utils/triggers/github.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| "use strict"; | ||||
| function githubWebhook() { | ||||
|     return true; | ||||
| } | ||||
| @ -1,21 +1,11 @@ | ||||
| #! /usr/bin/env node | ||||
| // @ts-check
 | ||||
| 
 | ||||
| const fs = require("fs"); | ||||
| const path = require("path"); | ||||
| const colors = require("./utils/console-colors"); | ||||
| const startProcess = require("./deploy/start"); | ||||
| 
 | ||||
| ///////////////////////////////////////////////
 | ||||
| ///////////////////////////////////////////////
 | ||||
| ///////////////////////////////////////////////
 | ||||
| import fs from "fs"; | ||||
| import path from "path"; | ||||
| import colors from "./utils/console-colors"; | ||||
| import startProcess from "./utils/start"; | ||||
| import type { NodeCIConfig } from "./types"; | ||||
| 
 | ||||
| const WORK_DIR = process.cwd(); | ||||
| 
 | ||||
| ///////////////////////////////////////////////
 | ||||
| ///////////////////////////////////////////////
 | ||||
| ///////////////////////////////////////////////
 | ||||
| 
 | ||||
| function run() { | ||||
|     try { | ||||
|         const configText = fs.readFileSync( | ||||
| @ -23,8 +13,7 @@ function run() { | ||||
|             "utf-8" | ||||
|         ); | ||||
| 
 | ||||
|         /** @type {NodeCIConfig} */ | ||||
|         const config = JSON.parse(configText); | ||||
|         const config: NodeCIConfig = JSON.parse(configText); | ||||
| 
 | ||||
|         const { | ||||
|             start, | ||||
| @ -66,7 +55,7 @@ function run() { | ||||
|             port, | ||||
|             postflight, | ||||
|         }); | ||||
|     } catch (error) { | ||||
|     } catch (error: any) { | ||||
|         console.log( | ||||
|             `${colors.FgRed}ERROR:${colors.Reset} CI process failed! => ${error.message}` | ||||
|         ); | ||||
| @ -75,10 +64,6 @@ function run() { | ||||
| 
 | ||||
| run(); | ||||
| 
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| ////////////////////////////////////////////
 | ||||
| 
 | ||||
| process.on("exit", () => { | ||||
|     console.log("Process exiting ..."); | ||||
| }); | ||||
							
								
								
									
										27
									
								
								jsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								jsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| { | ||||
|   "compilerOptions": { | ||||
|     // Enable latest features | ||||
|     "lib": ["ESNext", "DOM"], | ||||
|     "target": "ESNext", | ||||
|     "module": "ESNext", | ||||
|     "moduleDetection": "force", | ||||
|     "jsx": "react-jsx", | ||||
|     "allowJs": true, | ||||
| 
 | ||||
|     // Bundler mode | ||||
|     "moduleResolution": "bundler", | ||||
|     "allowImportingTsExtensions": true, | ||||
|     "verbatimModuleSyntax": true, | ||||
|     "noEmit": true, | ||||
| 
 | ||||
|     // Best practices | ||||
|     "strict": true, | ||||
|     "skipLibCheck": true, | ||||
|     "noFallthroughCasesInSwitch": true, | ||||
| 
 | ||||
|     // Some stricter flags (disabled by default) | ||||
|     "noUnusedLocals": false, | ||||
|     "noUnusedParameters": false, | ||||
|     "noPropertyAccessFromIndexSignature": false | ||||
|   } | ||||
| } | ||||
							
								
								
									
										42
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										42
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,42 +0,0 @@ | ||||
| { | ||||
|     "name": "nodecid", | ||||
|     "version": "1.0.5", | ||||
|     "lockfileVersion": 3, | ||||
|     "requires": true, | ||||
|     "packages": { | ||||
|         "": { | ||||
|             "name": "nodecid", | ||||
|             "version": "1.0.5", | ||||
|             "license": "MIT", | ||||
|             "dependencies": { | ||||
|                 "kill-port": "^2.0.1" | ||||
|             }, | ||||
|             "bin": { | ||||
|                 "node-ci-cd": "index.js", | ||||
|                 "nodecid": "index.js" | ||||
|             } | ||||
|         }, | ||||
|         "node_modules/get-them-args": { | ||||
|             "version": "1.3.2", | ||||
|             "resolved": "https://registry.npmjs.org/get-them-args/-/get-them-args-1.3.2.tgz", | ||||
|             "integrity": "sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==" | ||||
|         }, | ||||
|         "node_modules/kill-port": { | ||||
|             "version": "2.0.1", | ||||
|             "resolved": "https://registry.npmjs.org/kill-port/-/kill-port-2.0.1.tgz", | ||||
|             "integrity": "sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ==", | ||||
|             "dependencies": { | ||||
|                 "get-them-args": "1.3.2", | ||||
|                 "shell-exec": "1.0.2" | ||||
|             }, | ||||
|             "bin": { | ||||
|                 "kill-port": "cli.js" | ||||
|             } | ||||
|         }, | ||||
|         "node_modules/shell-exec": { | ||||
|             "version": "1.0.2", | ||||
|             "resolved": "https://registry.npmjs.org/shell-exec/-/shell-exec-1.0.2.tgz", | ||||
|             "integrity": "sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==" | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										18
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								package.json
									
									
									
									
									
								
							| @ -1,11 +1,14 @@ | ||||
| { | ||||
|     "name": "nodecid", | ||||
|     "name": "@moduletrace/nodecid", | ||||
|     "version": "1.0.7", | ||||
|     "description": "Simple CI/CD process", | ||||
|     "main": "index.js", | ||||
|     "main": "dist/index.js", | ||||
|     "bin": { | ||||
|         "nodecid": "./index.js", | ||||
|         "node-ci-cd": "./index.js" | ||||
|         "nodecid": "./dist/index.js", | ||||
|         "node-ci-cd": "./dist/index.js" | ||||
|     }, | ||||
|     "scripts": { | ||||
|         "compile": "bun build --compile --minify --sourcemap --bytecode index.ts --outfile bin/nodecid" | ||||
|     }, | ||||
|     "keywords": [ | ||||
|         "CI/CD", | ||||
| @ -16,5 +19,12 @@ | ||||
|     "license": "MIT", | ||||
|     "dependencies": { | ||||
|         "kill-port": "^2.0.1" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@types/bun": "latest", | ||||
|         "@types/node": "^22.10.7" | ||||
|     }, | ||||
|     "peerDependencies": { | ||||
|         "typescript": "^5.0.0" | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										21
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| { | ||||
|     "compilerOptions": { | ||||
|         "target": "ES2015", | ||||
|         "module": "commonjs", | ||||
|         "maxNodeModuleJsDepth": 10, | ||||
|         "esModuleInterop": true, | ||||
|         "forceConsistentCasingInFileNames": true, | ||||
|         "strict": true, | ||||
|         "skipLibCheck": true, | ||||
|         "lib": ["dom", "dom.iterable", "esnext"], | ||||
|         "allowJs": true, | ||||
|         "incremental": true, | ||||
|         "resolveJsonModule": true, | ||||
|         "jsx": "preserve", | ||||
|         "moduleResolution": "node", | ||||
|         "declaration": true, | ||||
|         "outDir": "dist" | ||||
|     }, | ||||
|     "include": ["**/*.ts"], | ||||
|     "exclude": ["node_modules", "dist"] | ||||
| } | ||||
							
								
								
									
										19
									
								
								types.d.js
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								types.d.js
									
									
									
									
									
								
							| @ -1,19 +0,0 @@ | ||||
| /** | ||||
|  * @typedef {object} NodeCIConfig | ||||
|  * @property {string} start - Start command. Eg `node index.js` | ||||
|  * @property {string[] | string} preflight - And array of commands to run before | ||||
|  * the application starts, or a single `.sh` file path. | ||||
|  * @property {string[] | string} [postflight] - And array of commands to run after | ||||
|  * the application starts. | ||||
|  * @property {string} [redeploy_path] - The path to the file that will trigger a | ||||
|  * redeployment if content is changed. Default file path is `./REDEPLOY` | ||||
|  * @property {boolean} [first_run] - Whether to run the preflight on first run. Default `false` | ||||
|  * @property {string | number | (string | number)[]} [port] - The port to kill on reload | ||||
|  * @property {NodeCIBuild} [build] - Build configurations | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {object} NodeCIBuild | ||||
|  * @property {"Next.JS" | "Remix"} paradigm - The paradigm to build on | ||||
|  * @property {string} [out_dir] - The output Directory. Default `.dist`. | ||||
|  */ | ||||
							
								
								
									
										14
									
								
								types.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								types.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| export interface NodeCIConfig { | ||||
|     start: string; | ||||
|     preflight: string[] | string; | ||||
|     postflight?: string[] | string; | ||||
|     redeploy_path?: string; | ||||
|     first_run?: boolean; | ||||
|     port?: string | number | (string | number)[]; | ||||
|     build?: NodeCIBuild; | ||||
| } | ||||
| 
 | ||||
| export interface NodeCIBuild { | ||||
|     paradigm: "Next.JS" | "Remix"; | ||||
|     out_dir?: string; | ||||
| } | ||||
							
								
								
									
										31
									
								
								utils/console-colors.ts
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								utils/console-colors.ts
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,31 @@ | ||||
| const colors = { | ||||
|     Reset: "\x1b[0m", | ||||
|     Bright: "\x1b[1m", | ||||
|     Dim: "\x1b[2m", | ||||
|     Underscore: "\x1b[4m", | ||||
|     Blink: "\x1b[5m", | ||||
|     Reverse: "\x1b[7m", | ||||
|     Hidden: "\x1b[8m", | ||||
| 
 | ||||
|     FgBlack: "\x1b[30m", | ||||
|     FgRed: "\x1b[31m", | ||||
|     FgGreen: "\x1b[32m", | ||||
|     FgYellow: "\x1b[33m", | ||||
|     FgBlue: "\x1b[34m", | ||||
|     FgMagenta: "\x1b[35m", | ||||
|     FgCyan: "\x1b[36m", | ||||
|     FgWhite: "\x1b[37m", | ||||
|     FgGray: "\x1b[90m", | ||||
| 
 | ||||
|     BgBlack: "\x1b[40m", | ||||
|     BgRed: "\x1b[41m", | ||||
|     BgGreen: "\x1b[42m", | ||||
|     BgYellow: "\x1b[43m", | ||||
|     BgBlue: "\x1b[44m", | ||||
|     BgMagenta: "\x1b[45m", | ||||
|     BgCyan: "\x1b[46m", | ||||
|     BgWhite: "\x1b[47m", | ||||
|     BgGray: "\x1b[100m", | ||||
| }; | ||||
| 
 | ||||
| export default colors; | ||||
							
								
								
									
										40
									
								
								utils/kill-child.ts
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										40
									
								
								utils/kill-child.ts
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,40 @@ | ||||
| import { ChildProcess } from "child_process"; | ||||
| import colors from "./console-colors"; | ||||
| import kill from "kill-port"; | ||||
| 
 | ||||
| let childProcess: ChildProcess | null = null; | ||||
| 
 | ||||
| const pTitle = "nodecid"; | ||||
| process.title = pTitle; | ||||
| 
 | ||||
| /** | ||||
|  * ## Kill Child Process Function | ||||
|  * @param {string | number | (string | number)[]} [port] | ||||
|  * @returns {Promise<boolean>} | ||||
|  */ | ||||
| export default async function killChild( | ||||
|     port?: string | number | (string | number)[] | ||||
| ): Promise<boolean> { | ||||
|     if (!childProcess) return false; | ||||
| 
 | ||||
|     try { | ||||
|         const childProcessPID = childProcess.pid; | ||||
|         childProcess.kill(); | ||||
| 
 | ||||
|         if (typeof port == "object" && port?.[0]) { | ||||
|             for (let i = 0; i < port.length; i++) { | ||||
|                 const singlePort = port[i]; | ||||
|                 await kill(Number(singlePort)); | ||||
|             } | ||||
|         } else if (port) { | ||||
|             await kill(Number(port)); | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } catch (error: any) { | ||||
|         console.log( | ||||
|             `${colors.FgRed}Error:${colors.Reset} Child Process couldn't be killed! ${error.message}` | ||||
|         ); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										46
									
								
								utils/preflight.ts
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										46
									
								
								utils/preflight.ts
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,46 @@ | ||||
| import { execSync, execFileSync, type ExecSyncOptions } from "child_process"; | ||||
| import colors from "../utils/console-colors"; | ||||
| 
 | ||||
| /** | ||||
|  * ## Preflight Function | ||||
|  * @param {string[] | string} preflight | ||||
|  * @param {boolean} [postflight] | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
| export default function preflightFn( | ||||
|     preflight?: string[] | string, | ||||
|     postflight?: boolean | ||||
| ): boolean { | ||||
|     const tag = postflight ? "Postflight" : "Preflight"; | ||||
|     console.log(`${tag} Running ...`); | ||||
| 
 | ||||
|     const options: ExecSyncOptions = { | ||||
|         cwd: process.cwd(), | ||||
|         stdio: "inherit", | ||||
|     }; | ||||
| 
 | ||||
|     try { | ||||
|         if (typeof preflight == "string") { | ||||
|             execFileSync(preflight, options); | ||||
|         } else if (typeof preflight == "object" && preflight?.[0]) { | ||||
|             for (let i = 0; i < preflight.length; i++) { | ||||
|                 const cmd = preflight[i]; | ||||
|                 try { | ||||
|                     const execCmd = execSync(cmd, options); | ||||
|                 } catch (error: any) { | ||||
|                     console.log( | ||||
|                         `${colors.FgRed}Error:${colors.Reset} ${tag} command ${cmd} Failed! => ${error.message}` | ||||
|                     ); | ||||
|                     return false; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     } catch (error: any) { | ||||
|         console.log( | ||||
|             `${colors.FgRed}Error:${colors.Reset} ${tag} Failed! => ${error.message}` | ||||
|         ); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										46
									
								
								utils/run.ts
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										46
									
								
								utils/run.ts
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,46 @@ | ||||
| import { spawn, ChildProcess } from "child_process"; | ||||
| import colors from "./console-colors"; | ||||
| 
 | ||||
| let redeployments = 0; | ||||
| 
 | ||||
| const KILL_SIGNAL: NodeJS.Signals | number = "SIGTERM"; | ||||
| 
 | ||||
| const pTitle = "nodecid"; | ||||
| process.title = pTitle; | ||||
| 
 | ||||
| /** | ||||
|  * ## Preflight Function | ||||
|  * @param {string} command | ||||
|  * @returns {ChildProcess | null} | ||||
|  */ | ||||
| export default function run(command: string): ChildProcess | null { | ||||
|     console.log("\n******************************"); | ||||
|     console.log( | ||||
|         `****** ${colors.FgGreen}Starting App ...${colors.Reset} ******` | ||||
|     ); | ||||
|     console.log("******************************\n"); | ||||
| 
 | ||||
|     const startCommandArray = command.split(" ").filter((str) => str.trim()); | ||||
| 
 | ||||
|     try { | ||||
|         const firstCommand = startCommandArray.shift(); | ||||
| 
 | ||||
|         if (!firstCommand) { | ||||
|             throw new Error("No Starting Command Found in command string!"); | ||||
|         } | ||||
| 
 | ||||
|         let childProcess = spawn(firstCommand, startCommandArray, { | ||||
|             stdio: "inherit", | ||||
|             killSignal: KILL_SIGNAL, | ||||
|         }); | ||||
| 
 | ||||
|         redeployments++; | ||||
| 
 | ||||
|         return childProcess; | ||||
|     } catch (error: any) { | ||||
|         console.log( | ||||
|             `${colors.FgRed}Error:${colors.Reset} running start command => ${error.message}` | ||||
|         ); | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										123
									
								
								utils/start.ts
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										123
									
								
								utils/start.ts
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,123 @@ | ||||
| import fs from "fs"; | ||||
| import { ChildProcess } from "child_process"; | ||||
| import colors from "./console-colors"; | ||||
| import kill from "kill-port"; | ||||
| import preflightFn from "./preflight"; | ||||
| import run from "./run"; | ||||
| import killChild from "./kill-child"; | ||||
| 
 | ||||
| let redeployments = 0; | ||||
| 
 | ||||
| let childProcess: ChildProcess | null = null; | ||||
| 
 | ||||
| const pTitle = "nodecid"; | ||||
| process.title = pTitle; | ||||
| 
 | ||||
| /** | ||||
|  * # Start the process | ||||
|  * @param {object} param0 | ||||
|  * @param {string} param0.command | ||||
|  * @param {string[] | string} param0.preflight | ||||
|  * @param {string[] | string} [param0.postflight] | ||||
|  * @param {string} param0.redeploy_file | ||||
|  * @param {string | number | (string | number)[]} [param0.port] - The port to kill on rebuild | ||||
|  * @param {boolean} [param0.first_run] - Whether to run the preflight on first run. Default `false` | ||||
|  */ | ||||
| export default function startProcess({ | ||||
|     command, | ||||
|     preflight, | ||||
|     postflight, | ||||
|     redeploy_file, | ||||
|     port, | ||||
|     first_run, | ||||
| }: { | ||||
|     command: string; | ||||
|     preflight: string[] | string; | ||||
|     postflight?: string[] | string; | ||||
|     redeploy_file: string; | ||||
|     port?: string | number | (string | number)[]; | ||||
|     first_run?: boolean; | ||||
| }) { | ||||
|     try { | ||||
|         if (first_run) { | ||||
|             console.log("First Run ..."); | ||||
|             const runPreflight = preflightFn(preflight); | ||||
|         } | ||||
| 
 | ||||
|         if (!preflight) { | ||||
|             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.` | ||||
|             ); | ||||
|             process.exit(); | ||||
|         } | ||||
| 
 | ||||
|         childProcess = run(command); | ||||
| 
 | ||||
|         if (!childProcess) { | ||||
|             console.log( | ||||
|                 `${colors.FgRed}Error:${colors.Reset} Process couldn't start. Exiting...` | ||||
|             ); | ||||
|             process.exit(); | ||||
|         } | ||||
| 
 | ||||
|         console.log("Watching", redeploy_file); | ||||
| 
 | ||||
|         fs.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => { | ||||
|             console.log(`${colors.BgBlue}File Changed${colors.Reset}`); | ||||
| 
 | ||||
|             if (redeployments == 0) return; | ||||
| 
 | ||||
|             if (childProcess) { | ||||
|                 console.log("******************************"); | ||||
|                 console.log( | ||||
|                     `******** ${colors.FgBlue}Rebuilding ${colors.FgMagenta}${redeployments}${colors.Reset} ********` | ||||
|                 ); | ||||
|                 console.log("******************************"); | ||||
| 
 | ||||
|                 try { | ||||
|                     const runPreflight = preflightFn(preflight); | ||||
| 
 | ||||
|                     if (!runPreflight) { | ||||
|                         // TODO: Action to take if preflight fails
 | ||||
| 
 | ||||
|                         console.log( | ||||
|                             `${colors.FgRed}Error:${colors.Reset} Preflight Failed.` | ||||
|                         ); | ||||
|                     } else { | ||||
|                         killChild(port).then((kill) => { | ||||
|                             if (kill) { | ||||
|                                 childProcess = run(command); | ||||
| 
 | ||||
|                                 if (postflight) { | ||||
|                                     const runPostflight = preflightFn( | ||||
|                                         postflight, | ||||
|                                         true | ||||
|                                     ); | ||||
| 
 | ||||
|                                     if (!runPostflight) { | ||||
|                                         // TODO: Action to take if postflight fails
 | ||||
| 
 | ||||
|                                         console.log( | ||||
|                                             `${colors.FgRed}Error:${colors.Reset} Postflight Failed.` | ||||
|                                         ); | ||||
|                                     } | ||||
|                                 } | ||||
|                             } else { | ||||
|                                 process.exit(); | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|                 } catch (error: any) { | ||||
|                     console.log( | ||||
|                         `${colors.FgRed}Error:${colors.Reset} killing child processes => ${error.message}` | ||||
|                     ); | ||||
|                     process.exit(); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } catch (error: any) { | ||||
|         console.log( | ||||
|             `${colors.FgRed}Error:${colors.Reset} First run failed! => ${error.message}` | ||||
|         ); | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Benjamin Toby
						Benjamin Toby