115 lines
4.0 KiB
JavaScript
115 lines
4.0 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.commands = commands;
|
|
exports.readPackageName = readPackageName;
|
|
const node_child_process_1 = require("node:child_process");
|
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
const json_1 = require("../../utils/json");
|
|
function commands() {
|
|
const childProcesses = [];
|
|
let isShuttingDown = false;
|
|
const registerChild = (child) => {
|
|
childProcesses.push(child);
|
|
};
|
|
const killChild = (child, signal) => {
|
|
if (!child.killed) {
|
|
child.kill(signal);
|
|
}
|
|
};
|
|
const forceKillAllChildren = () => {
|
|
childProcesses.forEach((child) => killChild(child, 'SIGKILL'));
|
|
process.exit(1);
|
|
};
|
|
const gracefulShutdown = (signal) => {
|
|
if (childProcesses.length === 0) {
|
|
process.exit();
|
|
return;
|
|
}
|
|
let exitedCount = 0;
|
|
const totalChildren = childProcesses.length;
|
|
const forceExitTimer = setTimeout(forceKillAllChildren, 5000);
|
|
const onChildExit = () => {
|
|
exitedCount++;
|
|
if (exitedCount === totalChildren) {
|
|
clearTimeout(forceExitTimer);
|
|
process.exit();
|
|
}
|
|
};
|
|
childProcesses.forEach((child) => {
|
|
if (!child.killed) {
|
|
child.once('exit', onChildExit);
|
|
killChild(child, signal);
|
|
setTimeout(() => killChild(child, 'SIGKILL'), 5000);
|
|
}
|
|
else {
|
|
onChildExit();
|
|
}
|
|
});
|
|
};
|
|
const handleSignal = (signal) => {
|
|
if (isShuttingDown) {
|
|
console.log('\nForce killing processes...');
|
|
forceKillAllChildren();
|
|
return;
|
|
}
|
|
isShuttingDown = true;
|
|
if (signal === 'SIGINT') {
|
|
console.log('\nShutting down gracefully... (press Ctrl+C again to force quit)');
|
|
}
|
|
gracefulShutdown(signal);
|
|
};
|
|
process.on('SIGINT', () => handleSignal('SIGINT'));
|
|
process.on('SIGTERM', () => handleSignal('SIGTERM'));
|
|
const stripAnsiCodes = (input) => input
|
|
.replace(/\x1Bc/g, '')
|
|
.replace(/\x1B\[2J/g, '')
|
|
.replace(/\x1B\[3J/g, '')
|
|
.replace(/\x1B\[H/g, '')
|
|
.replace(/\x1B\[0?m/g, '');
|
|
const createLogger = (name, color, allowOutput) => (text) => {
|
|
if (allowOutput && !allowOutput(text))
|
|
return;
|
|
const prefix = name ? (color ? color(`[${name}]`) : `[${name}]`) : '';
|
|
console.log(prefix ? `${prefix} ${text}` : text);
|
|
};
|
|
const processOutput = (data, logger) => {
|
|
data
|
|
.toString()
|
|
.split('\n')
|
|
.map((line) => stripAnsiCodes(line).trim())
|
|
.filter(Boolean)
|
|
.forEach(logger);
|
|
};
|
|
const runPersistentCommand = (cmd, args, opts = {}) => {
|
|
const child = (0, node_child_process_1.spawn)(cmd, args, {
|
|
cwd: opts.cwd,
|
|
env: { ...process.env, ...opts.env },
|
|
stdio: ['inherit', 'pipe', 'pipe'],
|
|
shell: process.platform === 'win32',
|
|
});
|
|
registerChild(child);
|
|
const logger = createLogger(opts.name, opts.color, opts.allowOutput);
|
|
const handleOutput = (data) => processOutput(data, logger);
|
|
child.stdout?.on('data', handleOutput);
|
|
child.stderr?.on('data', handleOutput);
|
|
child.on('close', (code) => {
|
|
if (!isShuttingDown) {
|
|
console.log(`${opts.name ?? cmd} exited with code ${code}`);
|
|
process.exit(code ?? 0);
|
|
}
|
|
});
|
|
return child;
|
|
};
|
|
return {
|
|
runPersistentCommand,
|
|
};
|
|
}
|
|
async function readPackageName() {
|
|
return await promises_1.default
|
|
.readFile('package.json', 'utf-8')
|
|
.then((packageJson) => (0, json_1.jsonParse)(packageJson)?.name ?? 'unknown');
|
|
}
|
|
//# sourceMappingURL=utils.js.map
|