MCPcopy
hub / github.com/coder/mux / execAsync

Function execAsync

src/node/utils/disposableExec.ts:205–258  ·  view source on GitHub ↗
(command: string, options?: ExecAsyncOptions)

Source from the content-addressed store, hash-verified

203 * using proc = execAsync("nohup bash -c ...", { shell: getBashPath() });
204 */
205export function execAsync(command: string, options?: ExecAsyncOptions): DisposableExec {
206 // Child processes inherit process.env automatically, which includes
207 // the enriched PATH set by initShellEnv() at startup
208 const child = exec(command, { shell: options?.shell });
209 const promise = new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {
210 let stdout = "";
211 let stderr = "";
212 let exitCode: number | null = null;
213 let exitSignal: string | null = null;
214
215 child.stdout?.on("data", (data) => {
216 stdout += data;
217 });
218 child.stderr?.on("data", (data) => {
219 stderr += data;
220 });
221
222 // Use 'close' event instead of 'exit' - close fires after all stdio streams are closed
223 // This ensures we've received all buffered output before resolving/rejecting
224 child.on("exit", (code, signal) => {
225 exitCode = code;
226 exitSignal = signal;
227 });
228
229 child.on("close", () => {
230 // Only resolve if process exited cleanly (code 0, no signal)
231 if (exitCode === 0 && exitSignal === null) {
232 resolve({ stdout, stderr });
233 } else {
234 // Include stderr in error message for better debugging
235 const errorMsg =
236 stderr.trim() ||
237 (exitSignal
238 ? `Command killed by signal ${exitSignal}`
239 : `Command failed with exit code ${exitCode ?? "unknown"}`);
240 const error = new Error(errorMsg) as Error & {
241 code: number | null;
242 signal: string | null;
243 stdout: string;
244 stderr: string;
245 };
246 error.code = exitCode;
247 error.signal = exitSignal;
248 error.stdout = stdout;
249 error.stderr = stderr;
250 reject(error);
251 }
252 });
253
254 child.on("error", reject);
255 });
256
257 return new DisposableExec(promise, child);
258}
259
260/**
261 * Options for execFileAsync.

Callers 15

executeSSHFunction · 0.90
remove.test.tsFile · 0.90
git.test.tsFile · 0.85
createTempGitRepoFunction · 0.85
addFakeOriginFunction · 0.85
addSubmoduleFunction · 0.85
createLocalSubmoduleRepoFunction · 0.85

Calls 4

rejectFunction · 0.85
onMethod · 0.80
execFunction · 0.50
resolveFunction · 0.50

Tested by 6

executeSSHFunction · 0.72
commitChangesFunction · 0.68
addInitHookFunction · 0.68