execFileNoThrow.ts
1 import { execFile } from 'child_process' 2 import { getCwd } from './state.js' 3 import { logError } from './log.js' 4 5 const MS_IN_SECOND = 1000 6 const SECONDS_IN_MINUTE = 60 7 8 /** 9 * execFile, but always resolves (never throws) 10 */ 11 export function execFileNoThrow( 12 file: string, 13 args: string[], 14 abortSignal?: AbortSignal, 15 timeout = 10 * SECONDS_IN_MINUTE * MS_IN_SECOND, 16 preserveOutputOnError = true, 17 ): Promise<{ stdout: string; stderr: string; code: number }> { 18 return new Promise(resolve => { 19 try { 20 execFile( 21 file, 22 args, 23 { 24 maxBuffer: 1_000_000, 25 signal: abortSignal, 26 timeout, 27 cwd: getCwd(), 28 }, 29 (error, stdout, stderr) => { 30 if (error) { 31 if (preserveOutputOnError) { 32 const errorCode = typeof error.code === 'number' ? error.code : 1 33 resolve({ 34 stdout: stdout || '', 35 stderr: stderr || '', 36 code: errorCode, 37 }) 38 } else { 39 resolve({ stdout: '', stderr: '', code: 1 }) 40 } 41 } else { 42 resolve({ stdout, stderr, code: 0 }) 43 } 44 }, 45 ) 46 } catch (error) { 47 logError(error) 48 resolve({ stdout: '', stderr: '', code: 1 }) 49 } 50 }) 51 }