import { spawn } from 'child_process';
import { Logger } from './logger.js';
interface ExecuteOptions {
cwd?: string;
timeout?: number;
onProgress?: (output: string) => void;
}
interface ExecuteResult {
stdout: string;
stderr: string;
exitCode: number;
}
export async function executeCommand(
command: string,
args: string[],
options: ExecuteOptions = {}
): Promise<ExecuteResult> {
const { cwd, timeout = 300000, onProgress } = options;
return new Promise((resolve, reject) => {
const proc = spawn(command, args, {
cwd,
shell: true,
env: { ...process.env },
});
let stdout = '';
let stderr = '';
const timeoutId = setTimeout(() => {
proc.kill('SIGTERM');
reject(new Error(`Command timed out after ${timeout}ms`));
}, timeout);
proc.stdout.on('data', (data) => {
const chunk = data.toString();
stdout += chunk;
onProgress?.(chunk);
});
proc.stderr.on('data', (data) => {
const chunk = data.toString();
stderr += chunk;
onProgress?.(chunk);
});
proc.on('close', (code) => {
clearTimeout(timeoutId);
resolve({
stdout,
stderr,
exitCode: code ?? 1,
});
});
proc.on('error', (error) => {
clearTimeout(timeoutId);
Logger.error('Command execution error:', error);
reject(error);
});
});
}