| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- import { execa } from 'execa'
- import { execSync_DEPRECATED } from './execSyncWrapper.js'
- async function whichNodeAsync(command: string): Promise<string | null> {
- if (process.platform === 'win32') {
- // On Windows, use where.exe and return the first result
- const result = await execa(`where.exe ${command}`, {
- shell: true,
- stderr: 'ignore',
- reject: false,
- })
- if (result.exitCode !== 0 || !result.stdout) {
- return null
- }
- // where.exe returns multiple paths separated by newlines, return the first
- return result.stdout.trim().split(/\r?\n/)[0] || null
- }
- // On POSIX systems (macOS, Linux, WSL), use which
- // Cross-platform safe: Windows is handled above
- // eslint-disable-next-line custom-rules/no-cross-platform-process-issues
- const result = await execa(`which ${command}`, {
- shell: true,
- stderr: 'ignore',
- reject: false,
- })
- if (result.exitCode !== 0 || !result.stdout) {
- return null
- }
- return result.stdout.trim()
- }
- function whichNodeSync(command: string): string | null {
- if (process.platform === 'win32') {
- try {
- const result = execSync_DEPRECATED(`where.exe ${command}`, {
- encoding: 'utf-8',
- stdio: ['ignore', 'pipe', 'ignore'],
- })
- const output = result.toString().trim()
- return output.split(/\r?\n/)[0] || null
- } catch {
- return null
- }
- }
- try {
- const result = execSync_DEPRECATED(`which ${command}`, {
- encoding: 'utf-8',
- stdio: ['ignore', 'pipe', 'ignore'],
- })
- return result.toString().trim() || null
- } catch {
- return null
- }
- }
- const bunWhich =
- typeof Bun !== 'undefined' && typeof Bun.which === 'function'
- ? Bun.which
- : null
- /**
- * Finds the full path to a command executable.
- * Uses Bun.which when running in Bun (fast, no process spawn),
- * otherwise spawns the platform-appropriate command.
- *
- * @param command - The command name to look up
- * @returns The full path to the command, or null if not found
- */
- export const which: (command: string) => Promise<string | null> = bunWhich
- ? async command => bunWhich(command)
- : whichNodeAsync
- /**
- * Synchronous version of `which`.
- *
- * @param command - The command name to look up
- * @returns The full path to the command, or null if not found
- */
- export const whichSync: (command: string) => string | null =
- bunWhich ?? whichNodeSync
|