Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
4.3 kB · 150 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151// This file represents useful wrappers over node:child_process// These wrappers ease error handling and cross-platform compatbility// By using execa, Windows automatically gets shell escaping + BAT / CMD handling
import { type ExecaError, execa } from 'execa'import { getCwd } from '../utils/cwd.js'import { logError } from './log.js'
export { execSyncWithDefaults_DEPRECATED } from './execFileNoThrowPortable.js'
const MS_IN_SECOND = 1000const SECONDS_IN_MINUTE = 60
type ExecFileOptions = { abortSignal?: AbortSignal timeout?: number preserveOutputOnError?: boolean // Setting useCwd=false avoids circular dependencies during initialization // getCwd() -> PersistentShell -> logEvent() -> execFileNoThrow useCwd?: boolean env?: NodeJS.ProcessEnv stdin?: 'ignore' | 'inherit' | 'pipe' input?: string}
export function execFileNoThrow( file: string, args: string[], options: ExecFileOptions = { timeout: 10 * SECONDS_IN_MINUTE * MS_IN_SECOND, preserveOutputOnError: true, useCwd: true, },): Promise<{ stdout: string; stderr: string; code: number; error?: string }> { return execFileNoThrowWithCwd(file, args, { abortSignal: options.abortSignal, timeout: options.timeout, preserveOutputOnError: options.preserveOutputOnError, cwd: options.useCwd ? getCwd() : undefined, env: options.env, stdin: options.stdin, input: options.input, })}
type ExecFileWithCwdOptions = { abortSignal?: AbortSignal timeout?: number preserveOutputOnError?: boolean maxBuffer?: number cwd?: string env?: NodeJS.ProcessEnv shell?: boolean | string | undefined stdin?: 'ignore' | 'inherit' | 'pipe' input?: string}
type ExecaResultWithError = { shortMessage?: string signal?: string}
/** * Extracts a human-readable error message from an execa result. * * Priority order: * 1. shortMessage - execa's human-readable error (e.g., "Command failed with exit code 1: ...") * This is preferred because it already includes signal info when a process is killed, * making it more informative than just the signal name. * 2. signal - the signal that killed the process (e.g., "SIGTERM") * 3. errorCode - fallback to just the numeric exit code */function getErrorMessage( result: ExecaResultWithError, errorCode: number,): string { if (result.shortMessage) { return result.shortMessage } if (typeof result.signal === 'string') { return result.signal } return String(errorCode)}
/** * execFile, but always resolves (never throws) */export function execFileNoThrowWithCwd( file: string, args: string[], { abortSignal, timeout: finalTimeout = 10 * SECONDS_IN_MINUTE * MS_IN_SECOND, preserveOutputOnError: finalPreserveOutput = true, cwd: finalCwd, env: finalEnv, maxBuffer, shell, stdin: finalStdin, input: finalInput, }: ExecFileWithCwdOptions = { timeout: 10 * SECONDS_IN_MINUTE * MS_IN_SECOND, preserveOutputOnError: true, maxBuffer: 1_000_000, },): Promise<{ stdout: string; stderr: string; code: number; error?: string }> { return new Promise(resolve => { // Use execa for cross-platform .bat/.cmd compatibility on Windows execa(file, args, { maxBuffer, signal: abortSignal, timeout: finalTimeout, cwd: finalCwd, env: finalEnv, shell, stdin: finalStdin, input: finalInput, reject: false, // Don't throw on non-zero exit codes }) .then(result => { if (result.failed) { if (finalPreserveOutput) { const errorCode = result.exitCode ?? 1 void resolve({ stdout: result.stdout || '', stderr: result.stderr || '', code: errorCode, error: getErrorMessage( result as unknown as ExecaResultWithError, errorCode, ), }) } else { void resolve({ stdout: '', stderr: '', code: result.exitCode ?? 1 }) } } else { void resolve({ stdout: result.stdout, stderr: result.stderr, code: 0, }) } }) .catch((error: ExecaError) => { logError(error) void resolve({ stdout: '', stderr: '', code: 1 }) }) })}