rebootify
Version:
A Faster and lightweight alertnative to nodemon to monitor your Node Application
103 lines (86 loc) • 3.39 kB
JavaScript
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();