diff options
Diffstat (limited to 'packages/tool-shell/src/spawn.ts')
| -rw-r--r-- | packages/tool-shell/src/spawn.ts | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/packages/tool-shell/src/spawn.ts b/packages/tool-shell/src/spawn.ts new file mode 100644 index 0000000..9025c26 --- /dev/null +++ b/packages/tool-shell/src/spawn.ts @@ -0,0 +1,46 @@ +import { spawn as nodeSpawn } from "node:child_process"; +import type { SpawnResult, SpawnShell } from "./shell.js"; + +export const realSpawn: SpawnShell = (params): Promise<SpawnResult> => { + return new Promise<SpawnResult>((resolve) => { + const child = nodeSpawn("sh", ["-c", params.command], { + cwd: params.cwd, + stdio: ["ignore", "pipe", "pipe"], + }); + + let timedOut = false; + let killed = false; + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGKILL"); + }, params.timeout); + + const onAbort = () => { + killed = true; + child.kill("SIGKILL"); + }; + params.signal.addEventListener("abort", onAbort, { once: true }); + + child.stdout.on("data", (chunk: Buffer) => { + params.onOutput(chunk.toString(), "stdout"); + }); + + child.stderr.on("data", (chunk: Buffer) => { + params.onOutput(chunk.toString(), "stderr"); + }); + + child.on("close", (code) => { + clearTimeout(timer); + params.signal.removeEventListener("abort", onAbort); + resolve({ exitCode: code, timedOut }); + }); + + child.on("error", () => { + clearTimeout(timer); + params.signal.removeEventListener("abort", onAbort); + if (!killed && !timedOut) { + resolve({ exitCode: 1, timedOut: false }); + } + }); + }); +}; |
