@sentzunhat/zacatl
Version:
A modular, high-performance TypeScript microservice framework for Node.js, featuring layered architecture, dependency injection, and robust validation for building scalable APIs and distributed systems.
82 lines • 2.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.runCommand = void 0;
const child_process_1 = require("child_process");
const policy_1 = require("./policy");
const types_1 = require("./types");
const SIGKILL_GRACE_MS = 2_000;
const runCommand = (spec, policy) => {
return new Promise((resolve, reject) => {
const parsed = types_1.commandSpecSchema.safeParse(spec);
if (!parsed.success) {
reject(parsed.error);
return;
}
try {
(0, policy_1.validateCommandSpec)(parsed.data, policy);
}
catch (err) {
reject(err);
return;
}
const startMs = Date.now();
let stdout = '';
let stderr = '';
let timedOut = false;
let outputBytes = 0;
const env = policy.inheritEnv
? { ...process.env, ...(parsed.data.env ?? {}) }
: { ...(parsed.data.env ?? {}) };
const child = (0, child_process_1.spawn)(parsed.data.cmd, parsed.data.args, {
shell: false,
cwd: parsed.data.cwd,
env,
stdio: ['ignore', 'pipe', 'pipe'],
});
const killTimer = setTimeout(() => {
timedOut = true;
child.kill('SIGTERM');
const forceKill = setTimeout(() => child.kill('SIGKILL'), SIGKILL_GRACE_MS);
if (typeof forceKill.unref === 'function')
forceKill.unref();
}, policy.timeoutMs);
child.stdout.on('data', (chunk) => {
outputBytes += chunk.byteLength;
if (outputBytes <= policy.maxOutputBytes) {
stdout += chunk.toString('utf-8');
}
});
child.stderr.on('data', (chunk) => {
outputBytes += chunk.byteLength;
if (outputBytes <= policy.maxOutputBytes) {
stderr += chunk.toString('utf-8');
}
});
child.on('close', (code) => {
clearTimeout(killTimer);
resolve({
cmd: parsed.data.cmd,
args: parsed.data.args,
exitCode: code,
stdout,
stderr,
timedOut,
durationMs: Date.now() - startMs,
});
});
child.on('error', (err) => {
clearTimeout(killTimer);
resolve({
cmd: parsed.data.cmd,
args: parsed.data.args,
exitCode: null,
stdout,
stderr: stderr ? `${stderr}\n${err.message}` : err.message,
timedOut,
durationMs: Date.now() - startMs,
});
});
});
};
exports.runCommand = runCommand;
//# sourceMappingURL=runner.js.map