source dump of claude code
at main 82 lines 2.4 kB view raw
1import { execa } from 'execa' 2import { execSync_DEPRECATED } from './execSyncWrapper.js' 3 4async function whichNodeAsync(command: string): Promise<string | null> { 5 if (process.platform === 'win32') { 6 // On Windows, use where.exe and return the first result 7 const result = await execa(`where.exe ${command}`, { 8 shell: true, 9 stderr: 'ignore', 10 reject: false, 11 }) 12 if (result.exitCode !== 0 || !result.stdout) { 13 return null 14 } 15 // where.exe returns multiple paths separated by newlines, return the first 16 return result.stdout.trim().split(/\r?\n/)[0] || null 17 } 18 19 // On POSIX systems (macOS, Linux, WSL), use which 20 // Cross-platform safe: Windows is handled above 21 // eslint-disable-next-line custom-rules/no-cross-platform-process-issues 22 const result = await execa(`which ${command}`, { 23 shell: true, 24 stderr: 'ignore', 25 reject: false, 26 }) 27 if (result.exitCode !== 0 || !result.stdout) { 28 return null 29 } 30 return result.stdout.trim() 31} 32 33function whichNodeSync(command: string): string | null { 34 if (process.platform === 'win32') { 35 try { 36 const result = execSync_DEPRECATED(`where.exe ${command}`, { 37 encoding: 'utf-8', 38 stdio: ['ignore', 'pipe', 'ignore'], 39 }) 40 const output = result.toString().trim() 41 return output.split(/\r?\n/)[0] || null 42 } catch { 43 return null 44 } 45 } 46 47 try { 48 const result = execSync_DEPRECATED(`which ${command}`, { 49 encoding: 'utf-8', 50 stdio: ['ignore', 'pipe', 'ignore'], 51 }) 52 return result.toString().trim() || null 53 } catch { 54 return null 55 } 56} 57 58const bunWhich = 59 typeof Bun !== 'undefined' && typeof Bun.which === 'function' 60 ? Bun.which 61 : null 62 63/** 64 * Finds the full path to a command executable. 65 * Uses Bun.which when running in Bun (fast, no process spawn), 66 * otherwise spawns the platform-appropriate command. 67 * 68 * @param command - The command name to look up 69 * @returns The full path to the command, or null if not found 70 */ 71export const which: (command: string) => Promise<string | null> = bunWhich 72 ? async command => bunWhich(command) 73 : whichNodeAsync 74 75/** 76 * Synchronous version of `which`. 77 * 78 * @param command - The command name to look up 79 * @returns The full path to the command, or null if not found 80 */ 81export const whichSync: (command: string) => string | null = 82 bunWhich ?? whichNodeSync