(spec: SpawnSpec)
| 200 | } |
| 201 | |
| 202 | export function spawnChild(spec: SpawnSpec): ChildProcess { |
| 203 | const child = spawn(resolveWindowsBin(spec.command), spec.args, { |
| 204 | env: spec.env, |
| 205 | stdio: spec.prefixLogs ? ['inherit', 'pipe', 'pipe'] : 'inherit', |
| 206 | // On Windows the dev commands (`tsx`, `pnpm`) are `.cmd` shims in |
| 207 | // node_modules/.bin. Node's spawn won't apply PATHEXT resolution to find |
| 208 | // them without a shell, so a bare `spawn('tsx', …)` throws ENOENT — and a |
| 209 | // Git-Bash PATH may not even carry .bin, so the command is resolved to its |
| 210 | // absolute shim above. POSIX resolves the bin dir directly, so keep shell |
| 211 | // off there. Args here have no spaces, so shell quoting isn't a concern. |
| 212 | shell: process.platform === 'win32', |
| 213 | } satisfies SpawnOptions) |
| 214 | |
| 215 | if (spec.prefixLogs) { |
| 216 | const tag = `[${spec.name}] ` |
| 217 | child.stdout?.on('data', (buf: Buffer) => writePrefixed(process.stdout, buf, tag)) |
| 218 | child.stderr?.on('data', (buf: Buffer) => writePrefixed(process.stderr, buf, tag)) |
| 219 | } |
| 220 | return child |
| 221 | } |
| 222 | |
| 223 | /** |
| 224 | * Kill a child *and its descendants*, cross-platform. |
no test coverage detected