(
cmd: string,
args: string[],
options: ExecStreamOptions = {},
)
| 110 | } |
| 111 | |
| 112 | function runSpawnedCommand( |
| 113 | cmd: string, |
| 114 | args: string[], |
| 115 | options: ExecStreamOptions = {}, |
| 116 | ): Promise<ExecResult> { |
| 117 | const executable = normalizeExecutableCommand(cmd); |
| 118 | const execTrace = createExecTraceContext(); |
| 119 | return new Promise((resolve, reject) => { |
| 120 | const child = spawn(executable, args, { |
| 121 | cwd: options.cwd, |
| 122 | env: options.env, |
| 123 | stdio: ['pipe', 'pipe', 'pipe'], |
| 124 | detached: options.detached, |
| 125 | windowsHide: true, |
| 126 | shell: false, |
| 127 | }); |
| 128 | options.onSpawn?.(child); |
| 129 | |
| 130 | let stdout = ''; |
| 131 | const stdoutChunks: Buffer[] | undefined = options.binaryStdout ? [] : undefined; |
| 132 | let stderr = ''; |
| 133 | let didTimeout = false; |
| 134 | const timeoutMs = normalizeTimeoutMs(options.timeoutMs); |
| 135 | const timeoutHandle = timeoutMs |
| 136 | ? setTimeout(() => { |
| 137 | didTimeout = true; |
| 138 | killProcessTree(child, options.detached); |
| 139 | }, timeoutMs) |
| 140 | : null; |
| 141 | const abort = watchCommandAbort(child, options); |
| 142 | |
| 143 | if (!options.binaryStdout) child.stdout.setEncoding('utf8'); |
| 144 | child.stderr.setEncoding('utf8'); |
| 145 | |
| 146 | void writeChildStdin(child, options.stdin).catch((err: unknown) => { |
| 147 | if (abort.didAbort || didTimeout) return; |
| 148 | if (isEpipeError(err)) return; |
| 149 | reject(createStdinError(executable, cmd, args, err)); |
| 150 | killProcessTree(child, options.detached); |
| 151 | }); |
| 152 | |
| 153 | child.stdout.on('data', (chunk) => { |
| 154 | if (options.binaryStdout) { |
| 155 | stdoutChunks?.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); |
| 156 | return; |
| 157 | } |
| 158 | const text = String(chunk); |
| 159 | stdout += text; |
| 160 | options.onStdoutChunk?.(text); |
| 161 | }); |
| 162 | |
| 163 | child.stderr.on('data', (chunk) => { |
| 164 | const text = String(chunk); |
| 165 | stderr += text; |
| 166 | options.onStderrChunk?.(text); |
| 167 | }); |
| 168 | |
| 169 | child.on('error', (err) => { |
no test coverage detected