@@ -9,7 +9,6 @@ import { getXdgDataHome } from '#env/xdg'
99
1010import { WIN32 } from '#constants/platform'
1111import { readJsonSync } from './fs'
12- import { getOwn } from './objects'
1312import { isPath , normalizePath } from './path'
1413import { spawn } from './spawn'
1514
@@ -86,24 +85,61 @@ export async function execBin(
8685 } )
8786}
8887
88+ /**
89+ * Options for the which function.
90+ */
91+ export interface WhichOptions {
92+ /** If true, return all matches instead of just the first one. */
93+ all ?: boolean | undefined
94+ /** If true, return null instead of throwing when no match is found. */
95+ nothrow ?: boolean | undefined
96+ /** Path to search in. */
97+ path ?: string | undefined
98+ /** Path separator character. */
99+ pathExt ?: string | undefined
100+ /** Environment variables to use. */
101+ env ?: Record < string , string | undefined > | undefined
102+ }
103+
104+ /**
105+ * Find an executable in the system PATH asynchronously.
106+ * Wrapper around the which package for lazy loading.
107+ */
108+ export async function which (
109+ binName : string ,
110+ options ?: WhichOptions ,
111+ ) : Promise < string | string [ ] | undefined > {
112+ return await getWhich ( ) ( binName , options )
113+ }
114+
115+ /**
116+ * Find an executable in the system PATH synchronously.
117+ * Wrapper around the which package for lazy loading.
118+ */
119+ export function whichSync (
120+ binName : string ,
121+ options ?: WhichOptions ,
122+ ) : string | string [ ] | undefined {
123+ return getWhich ( ) . sync ( binName , options )
124+ }
125+
89126/**
90127 * Find and resolve a binary in the system PATH asynchronously.
91- * @template {import('which').Options} T
92128 * @throws {Error } If the binary is not found and nothrow is false.
93129 */
94130export async function whichBin (
95131 binName : string ,
96- options ?: import ( 'which' ) . Options ,
132+ options ?: WhichOptions ,
97133) : Promise < string | string [ ] | undefined > {
98134 const which = getWhich ( )
99135 // Default to nothrow: true if not specified to return undefined instead of throwing
100136 const opts = { nothrow : true , ...options }
101137 // Depending on options `which` may throw if `binName` is not found.
102138 // With nothrow: true, it returns null when `binName` is not found.
103- const result = await which ?. ( binName , opts )
139+ const result = await which ( binName , opts )
104140
105141 // When 'all: true' is specified, ensure we always return an array.
106- if ( options ?. all ) {
142+ if ( opts ?. all ) {
107143 const paths = Array . isArray ( result )
108144 ? result
109145 : typeof result === 'string'
@@ -123,21 +159,20 @@ export async function whichBin(
123159
124160/**
125161 * Find and resolve a binary in the system PATH synchronously.
126- * @template {import('which').Options} T
127162 * @throws {Error } If the binary is not found and nothrow is false.
128163 */
129164export function whichBinSync (
130165 binName : string ,
131- options ?: import ( 'which' ) . Options ,
166+ options ?: WhichOptions ,
132167) : string | string [ ] | undefined {
133168 // Default to nothrow: true if not specified to return undefined instead of throwing
134169 const opts = { nothrow : true , ...options }
135170 // Depending on options `which` may throw if `binName` is not found.
136171 // With nothrow: true, it returns null when `binName` is not found.
137- const result = getWhich ( ) ?. sync ( binName , opts )
172+ const result = whichSync ( binName , opts )
138173
139174 // When 'all: true' is specified, ensure we always return an array.
140- if ( getOwn ( options , ' all' ) ) {
175+ if ( opts . all ) {
141176 const paths = Array . isArray ( result )
142177 ? result
143178 : typeof result === 'string'
@@ -152,7 +187,7 @@ export function whichBinSync(
152187 return undefined
153188 }
154189
155- return resolveBinPathSync ( result )
190+ return resolveBinPathSync ( result as string )
156191}
157192
158193/**
0 commit comments