Something went wrong. Try again.
more up to date at codeberg https://codeberg.org/cowie/tau.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120import { type ChildProcess, type ChildProcessByStdio, spawn as nodeSpawn, spawnSync as nodeSpawnSync, type SpawnOptions, type SpawnOptionsWithStdioTuple, type SpawnSyncOptionsWithStringEncoding, type SpawnSyncReturns, type StdioNull, type StdioPipe,} from "node:child_process";import type { Readable } from "node:stream";import crossSpawn from "cross-spawn";
const EXIT_STDIO_GRACE_MS = 100;
export function spawnProcess( command: string, args: string[], options: SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioPipe>,): ChildProcessByStdio<null, Readable, Readable>;export function spawnProcess(command: string, args: string[], options: SpawnOptions): ChildProcess;export function spawnProcess(command: string, args: string[], options: SpawnOptions): ChildProcess { return process.platform === "win32" ? crossSpawn(command, args, options) : nodeSpawn(command, args, options);}
export function spawnProcessSync( command: string, args: string[], options: SpawnSyncOptionsWithStringEncoding,): SpawnSyncReturns<string> { return process.platform === "win32" ? crossSpawn.sync(command, args, options) : nodeSpawnSync(command, args, options);}
/** * Wait for a child process to terminate without hanging on inherited stdio handles. * * On Windows, daemonized descendants can inherit the child's stdout/stderr pipe * handles. In that case the child emits `exit`, but `close` can hang forever even * though the original process is already gone. We wait briefly for stdio to end, * then forcibly stop tracking the inherited handles. */export function waitForChildProcess(child: ChildProcess): Promise<number | null> { return new Promise((resolve, reject) => { let settled = false; let exited = false; let exitCode: number | null = null; let postExitTimer: NodeJS.Timeout | undefined; let stdoutEnded = child.stdout === null; let stderrEnded = child.stderr === null;
const cleanup = () => { if (postExitTimer) { clearTimeout(postExitTimer); postExitTimer = undefined; } child.removeListener("error", onError); child.removeListener("exit", onExit); child.removeListener("close", onClose); child.stdout?.removeListener("end", onStdoutEnd); child.stderr?.removeListener("end", onStderrEnd); };
const finalize = (code: number | null) => { if (settled) return; settled = true; cleanup(); child.stdout?.destroy(); child.stderr?.destroy(); resolve(code); };
const maybeFinalizeAfterExit = () => { if (!exited || settled) return; if (stdoutEnded && stderrEnded) { finalize(exitCode); } };
const onStdoutEnd = () => { stdoutEnded = true; maybeFinalizeAfterExit(); };
const onStderrEnd = () => { stderrEnded = true; maybeFinalizeAfterExit(); };
const onError = (err: Error) => { if (settled) return; settled = true; cleanup(); reject(err); };
const onExit = (code: number | null) => { exited = true; exitCode = code; maybeFinalizeAfterExit(); if (!settled) { postExitTimer = setTimeout(() => finalize(code), EXIT_STDIO_GRACE_MS); } };
const onClose = (code: number | null) => { finalize(code); };
child.stdout?.once("end", onStdoutEnd); child.stderr?.once("end", onStderrEnd); child.once("error", onError); child.once("exit", onExit); child.once("close", onClose); });}