(local: LocalProcessState, params: {
command: string
args: string[]
cwd: string
env?: Record<string, string>
timeoutMs?: number
label: string
tempScriptPath?: string
})
| 61 | } |
| 62 | |
| 63 | async function startChild(local: LocalProcessState, params: { |
| 64 | command: string |
| 65 | args: string[] |
| 66 | cwd: string |
| 67 | env?: Record<string, string> |
| 68 | timeoutMs?: number |
| 69 | label: string |
| 70 | tempScriptPath?: string |
| 71 | }): Promise<RuntimeNodeProcessStartResult> { |
| 72 | await assertDirectory(params.cwd) |
| 73 | const id = processId() |
| 74 | const child = spawn(params.command, params.args, { |
| 75 | cwd: params.cwd, |
| 76 | env: { ...process.env, ...params.env }, |
| 77 | detached: process.platform !== "win32", |
| 78 | windowsHide: true, |
| 79 | }) |
| 80 | const state: ActiveProcess = { |
| 81 | process: child, |
| 82 | output: [], |
| 83 | completed: false, |
| 84 | exitCode: null, |
| 85 | signal: null, |
| 86 | tempScriptPath: params.tempScriptPath, |
| 87 | } |
| 88 | local.active.set(id, state) |
| 89 | |
| 90 | child.stdout?.on("data", (data: Buffer) => { |
| 91 | const chunk = { type: "stdout" as const, data: data.toString("utf8"), timestamp: Date.now() } |
| 92 | bufferOutput(state, chunk) |
| 93 | emit(local, { type: "output", processId: id, chunk }) |
| 94 | }) |
| 95 | child.stderr?.on("data", (data: Buffer) => { |
| 96 | const chunk = { type: "stderr" as const, data: data.toString("utf8"), timestamp: Date.now() } |
| 97 | bufferOutput(state, chunk) |
| 98 | emit(local, { type: "output", processId: id, chunk }) |
| 99 | }) |
| 100 | child.once("error", (error) => { |
| 101 | if (state.completed) return |
| 102 | state.completed = true |
| 103 | state.error = error.message |
| 104 | if (state.timeout) clearTimeout(state.timeout) |
| 105 | emit(local, { type: "error", processId: id, error: error.message }) |
| 106 | scheduleCleanup(local, id, state) |
| 107 | }) |
| 108 | child.once("exit", (exitCode, signal) => { |
| 109 | if (state.completed) return |
| 110 | state.completed = true |
| 111 | state.exitCode = exitCode |
| 112 | state.signal = signal |
| 113 | if (state.timeout) clearTimeout(state.timeout) |
| 114 | emit(local, { type: "exit", processId: id, exitCode, signal }) |
| 115 | scheduleCleanup(local, id, state) |
| 116 | }) |
| 117 | |
| 118 | if (params.timeoutMs && params.timeoutMs > 0) { |
| 119 | state.timeout = setTimeout(() => { |
| 120 | child.kill("SIGTERM") |
no test coverage detected