UNPKG

rebootify

Version:

A Faster and lightweight alertnative to nodemon to monitor your Node Application

103 lines (86 loc) 3.39 kB
const spawn = require('child_process').spawn; const chokidar = require('chokidar'); const path = require('path'); const Utility = require('../util/utility'); const logger = require('./logger'); class Rebootify { constructor() { this.__init__(); } __init__ = () => { this.args = process.argv; this.fileName = this.args[2]; this.cwd = process.cwd(); // Watch only the server.js file for changes, update to match your use case this.watchPaths = [path.join(this.cwd, 'server.js')]; // Watch the specific file `server.js` this.ignoredPaths = "**/node_modules/*"; this.logInit(); this.reload(); // Start initial process this.startWatching(); // Start file watching this.listeningEvents(); // Listen for CLI input } reload = () => { logger('debug', `Starting ${this.fileName}`); if (this.nodeServer) this.killNodeProcess(); // Kill previous process before spawning a new one const nodeArgs = this.args.slice(3); // Capture any additional arguments logger('debug', `Spawning new process for ${this.fileName}`); this.nodeServer = spawn('node', [this.fileName, ...nodeArgs], { stdio: 'inherit' }); this.nodeServer.on('close', (code) => { if (code !== 0) { logger('error', `${this.fileName} crashed. Restarting on changes...`); } }); this.nodeServer.on('spawn', () => { logger('debug', `${this.fileName} spawned successfully`); }); }; startWatching = () => { const watcher = chokidar.watch(this.watchPaths, { ignored: this.ignoredPaths, ignoreInitial: true, }); watcher.on('ready', () => { logger('info', 'Watcher is ready. Monitoring changes...'); }).on('change', (filePath) => { logger('debug', `File changed: ${filePath}`); Utility.debounce(() => { logger('debug', 'Debounced reload triggered.'); this.reload(); // Restart the process when file changes }, 500)(); }); }; listeningEvents = () => { // Listening for CLI input (e.g., 'rs' to restart) process.stdin.on("data", (chunk) => { let cliInput = chunk.toString().trim(); // Trim extra spaces/newlines if (cliInput === 'rs') { this.reload(); } }); }; logInit = () => { logger('info', 'Rebootify v1.0.0'); logger('info', 'To restart at any time, enter `rs`'); }; killNodeProcess = () => { if (this.nodeServer) { logger('info', 'Killing the previous Node.js process...'); this.nodeServer.kill('SIGTERM'); // Send the signal to gracefully stop the process this.nodeServer = null; } else { logger('warn', 'No process to kill.'); } }; } // Graceful shutdown: Ensure subprocess is killed when exiting process.on('SIGINT', () => { logger('info', 'Shutting down gracefully...'); if (this.nodeServer) this.killNodeProcess(); process.exit(); }); process.on('SIGTERM', () => { logger('info', 'Received SIGTERM. Shutting down...'); if (this.nodeServer) this.killNodeProcess(); process.exit(); }); module.exports = new Rebootify();