You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@vltpkg/which

Package Overview
Dependencies
Maintainers
6
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vltpkg/which - npm Package Compare versions

Comparing version
1.0.0-rc.10
to
1.0.0-rc.11
+42
dist/index.d.ts
export type WhichOptions = {
all?: boolean;
path?: string;
pathExt?: string;
nothrow?: boolean;
delimiter?: string;
};
export type WhichOptionsFindAll = WhichOptions & {
all: true;
};
export type WhichOptionsFindOne = WhichOptions & {
all?: false;
};
export type WhichOptionsNoThrow = WhichOptions & {
nothrow: true;
};
export type WhichOptionsThrow = WhichOptions & {
nothrow?: false;
};
export type WhichOptionsFindOneThrow = WhichOptionsFindOne & WhichOptionsThrow;
export type WhichOptionsFindOneNoThrow = WhichOptionsFindOne & WhichOptionsNoThrow;
export type WhichOptionsFindAllNoThrow = WhichOptionsFindAll & WhichOptionsNoThrow;
export type WhichOptionsFindAllThrow = WhichOptionsFindAll & WhichOptionsThrow;
export declare function which(cmd: string): Promise<string>;
export declare function which(cmd: string, opt: WhichOptionsFindAllNoThrow): Promise<string[] | null>;
export declare function which(cmd: string, opt: WhichOptionsFindOneNoThrow): Promise<string | null>;
export declare function which(cmd: string, opt: WhichOptionsFindAllThrow): Promise<string[]>;
export declare function which(cmd: string, opt: WhichOptionsFindOneThrow): Promise<string>;
export declare function which(cmd: string, opt: WhichOptionsFindOne): Promise<string | null>;
export declare function which(cmd: string, opt: WhichOptionsNoThrow): Promise<string[] | string | null>;
export declare function which(cmd: string, opt: WhichOptionsFindAll): Promise<string[] | null>;
export declare function which(cmd: string, opt: WhichOptions): Promise<string[] | string | null>;
export declare function whichSync(cmd: string): string;
export declare function whichSync(cmd: string, opt: WhichOptionsFindAllNoThrow): string[] | null;
export declare function whichSync(cmd: string, opt: WhichOptionsFindOneNoThrow): string | null;
export declare function whichSync(cmd: string, opt: WhichOptionsFindAllThrow): string[];
export declare function whichSync(cmd: string, opt: WhichOptionsFindOneThrow): string;
export declare function whichSync(cmd: string, opt: WhichOptionsFindOne): string | null;
export declare function whichSync(cmd: string, opt: WhichOptionsNoThrow): string[] | string | null;
export declare function whichSync(cmd: string, opt: WhichOptionsFindAll): string[] | null;
export declare function whichSync(cmd: string, opt?: WhichOptions): string[] | string | null;
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
import { isexe, sync as isexeSync } from 'isexe';
import { delimiter, join, sep } from 'node:path';
const isWindows = process.platform === 'win32';
// used to check for slashed in commands passed in. always checks for the posix
// separator on all platforms, and checks for the current separator when not on
// a posix platform. don't use the isWindows check for this since that is
// mocked in tests but we still need the code to actually work when called.
// that is also why it is ignored from coverage.
/* c8 ignore next */
const rSlash = sep === '/' ? /\// : /[\\/]/;
const rRel = new RegExp(`^\\.${rSlash.source}`);
// Simulate a NodeJS.ErrnoException
const getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' });
const getPathInfo = (cmd, { path: optPath = process.env.PATH, pathExt: optPathExt = process.env.PATHEXT, delimiter: optDelimiter = delimiter, }) => {
// If it has a slash, then we don't bother searching the pathenv.
// just check the file itself, and that's it.
const pathEnv = cmd.match(rSlash) ?
['']
: [
// windows always checks the cwd first
/* c8 ignore next - platform-specific */
...(isWindows ? [process.cwd()] : []),
...(optPath ?? /* c8 ignore next - very unusual */ '').split(optDelimiter),
];
if (isWindows) {
const pathExtExe = optPathExt ||
['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter);
const pathExt = pathExtExe
.split(optDelimiter)
.flatMap(item => [item, item.toLowerCase()]);
if (cmd.includes('.') && pathExt[0] !== '') {
pathExt.unshift('');
}
return { pathEnv, pathExt, pathExtExe };
/* c8 ignore start - not reachable on windows */
}
return { pathEnv, pathExt: [''] };
};
/* c8 ignore stop */
const getPathPart = (raw, cmd) => {
const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : '';
return prefix + join(pathPart, cmd);
};
export async function which(cmd, opt = {}) {
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
const found = [];
for (const envPart of pathEnv) {
const p = getPathPart(envPart, cmd);
for (const ext of pathExt) {
const withExt = p + ext;
const is = await isexe(withExt, {
pathExt: pathExtExe,
ignoreErrors: true,
});
if (is) {
if (!opt.all) {
return withExt;
}
found.push(withExt);
}
}
}
if (opt.all && found.length) {
return found;
}
if (opt.nothrow) {
return null;
}
throw getNotFoundError(cmd);
}
export function whichSync(cmd, opt = {}) {
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
const found = [];
for (const pathEnvPart of pathEnv) {
const p = getPathPart(pathEnvPart, cmd);
for (const ext of pathExt) {
const withExt = p + ext;
const is = isexeSync(withExt, {
pathExt: pathExtExe,
ignoreErrors: true,
});
if (is) {
if (!opt.all) {
return withExt;
}
found.push(withExt);
}
}
}
if (opt.all && found.length) {
return found;
}
if (opt.nothrow) {
return null;
}
throw getNotFoundError(cmd);
}
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { isexe, sync as isexeSync } from 'isexe'\nimport { delimiter, join, sep } from 'node:path'\n\nconst isWindows = process.platform === 'win32'\n\n// used to check for slashed in commands passed in. always checks for the posix\n// separator on all platforms, and checks for the current separator when not on\n// a posix platform. don't use the isWindows check for this since that is\n// mocked in tests but we still need the code to actually work when called.\n// that is also why it is ignored from coverage.\n/* c8 ignore next */\nconst rSlash = sep === '/' ? /\\// : /[\\\\/]/\nconst rRel = new RegExp(`^\\\\.${rSlash.source}`)\n\n// Simulate a NodeJS.ErrnoException\nconst getNotFoundError = (cmd: string) =>\n Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' })\n\nconst getPathInfo = (\n cmd: string,\n {\n path: optPath = process.env.PATH,\n pathExt: optPathExt = process.env.PATHEXT,\n delimiter: optDelimiter = delimiter,\n }: WhichOptions,\n) => {\n // If it has a slash, then we don't bother searching the pathenv.\n // just check the file itself, and that's it.\n const pathEnv =\n cmd.match(rSlash) ?\n ['']\n : [\n // windows always checks the cwd first\n /* c8 ignore next - platform-specific */\n ...(isWindows ? [process.cwd()] : []),\n ...(optPath ?? /* c8 ignore next - very unusual */ '').split(\n optDelimiter,\n ),\n ]\n\n if (isWindows) {\n const pathExtExe =\n optPathExt ||\n ['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter)\n const pathExt = pathExtExe\n .split(optDelimiter)\n .flatMap(item => [item, item.toLowerCase()])\n if (cmd.includes('.') && pathExt[0] !== '') {\n pathExt.unshift('')\n }\n return { pathEnv, pathExt, pathExtExe }\n /* c8 ignore start - not reachable on windows */\n }\n\n return { pathEnv, pathExt: [''] }\n}\n/* c8 ignore stop */\n\nconst getPathPart = (raw: string, cmd: string) => {\n const pathPart = /^\".*\"$/.test(raw) ? raw.slice(1, -1) : raw\n const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : ''\n return prefix + join(pathPart, cmd)\n}\n\nexport type WhichOptions = {\n all?: boolean\n path?: string\n pathExt?: string\n nothrow?: boolean\n delimiter?: string\n}\n\nexport type WhichOptionsFindAll = WhichOptions & { all: true }\nexport type WhichOptionsFindOne = WhichOptions & { all?: false }\n\nexport type WhichOptionsNoThrow = WhichOptions & { nothrow: true }\nexport type WhichOptionsThrow = WhichOptions & { nothrow?: false }\n\nexport type WhichOptionsFindOneThrow = WhichOptionsFindOne &\n WhichOptionsThrow\nexport type WhichOptionsFindOneNoThrow = WhichOptionsFindOne &\n WhichOptionsNoThrow\n\nexport type WhichOptionsFindAllNoThrow = WhichOptionsFindAll &\n WhichOptionsNoThrow\nexport type WhichOptionsFindAllThrow = WhichOptionsFindAll &\n WhichOptionsThrow\n\nexport async function which(cmd: string): Promise<string>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindAllNoThrow,\n): Promise<string[] | null>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindOneNoThrow,\n): Promise<string | null>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindAllThrow,\n): Promise<string[]>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindOneThrow,\n): Promise<string>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindOne,\n): Promise<string | null>\nexport async function which(\n cmd: string,\n opt: WhichOptionsNoThrow,\n): Promise<string[] | string | null>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindAll,\n): Promise<string[] | null>\nexport async function which(\n cmd: string,\n opt: WhichOptions,\n): Promise<string[] | string | null>\nexport async function which(cmd: string, opt: WhichOptions = {}) {\n const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt)\n const found = []\n\n for (const envPart of pathEnv) {\n const p = getPathPart(envPart, cmd)\n\n for (const ext of pathExt) {\n const withExt = p + ext\n const is = await isexe(withExt, {\n pathExt: pathExtExe,\n ignoreErrors: true,\n })\n if (is) {\n if (!opt.all) {\n return withExt\n }\n found.push(withExt)\n }\n }\n }\n\n if (opt.all && found.length) {\n return found\n }\n\n if (opt.nothrow) {\n return null\n }\n\n throw getNotFoundError(cmd)\n}\n\nexport function whichSync(cmd: string): string\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindAllNoThrow,\n): string[] | null\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindOneNoThrow,\n): string | null\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindAllThrow,\n): string[]\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindOneThrow,\n): string\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindOne,\n): string | null\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsNoThrow,\n): string[] | string | null\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindAll,\n): string[] | null\nexport function whichSync(\n cmd: string,\n opt?: WhichOptions,\n): string[] | string | null\nexport function whichSync(cmd: string, opt: WhichOptions = {}) {\n const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt)\n const found = []\n\n for (const pathEnvPart of pathEnv) {\n const p = getPathPart(pathEnvPart, cmd)\n\n for (const ext of pathExt) {\n const withExt = p + ext\n const is = isexeSync(withExt, {\n pathExt: pathExtExe,\n ignoreErrors: true,\n })\n if (is) {\n if (!opt.all) {\n return withExt\n }\n found.push(withExt)\n }\n }\n }\n\n if (opt.all && found.length) {\n return found\n }\n\n if (opt.nothrow) {\n return null\n }\n\n throw getNotFoundError(cmd)\n}\n"]}
+3
-17
{
"name": "@vltpkg/which",
"description": "Find the first executable in the path (TS port of 'which')",
"version": "1.0.0-rc.10",
"version": "1.0.0-rc.11",
"repository": {

@@ -11,13 +11,2 @@ "type": "git",

"author": "vlt technology inc. <support@vlt.sh> (http://vlt.sh)",
"tshy": {
"selfLink": false,
"liveDev": true,
"dialects": [
"esm"
],
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
}
},
"dependencies": {

@@ -32,3 +21,2 @@ "isexe": "^3.1.1"

"tap": "^21.5.0",
"tshy": "^3.1.0",
"typedoc": "~0.27.9",

@@ -46,3 +34,3 @@ "typescript": "5.7.3",

"prettier": "../../.prettierrc.js",
"module": "./dist/esm/index.js",
"module": "./dist/index.js",
"type": "module",

@@ -53,4 +41,3 @@ "exports": {

"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
"default": "./dist/index.js"
}

@@ -70,5 +57,4 @@ }

"posttest": "tsc --noEmit",
"tshy": "tshy",
"typecheck": "tsc --noEmit"
}
}
export type WhichOptions = {
all?: boolean;
path?: string;
pathExt?: string;
nothrow?: boolean;
delimiter?: string;
};
export type WhichOptionsFindAll = WhichOptions & {
all: true;
};
export type WhichOptionsFindOne = WhichOptions & {
all?: false;
};
export type WhichOptionsNoThrow = WhichOptions & {
nothrow: true;
};
export type WhichOptionsThrow = WhichOptions & {
nothrow?: false;
};
export type WhichOptionsFindOneThrow = WhichOptionsFindOne & WhichOptionsThrow;
export type WhichOptionsFindOneNoThrow = WhichOptionsFindOne & WhichOptionsNoThrow;
export type WhichOptionsFindAllNoThrow = WhichOptionsFindAll & WhichOptionsNoThrow;
export type WhichOptionsFindAllThrow = WhichOptionsFindAll & WhichOptionsThrow;
export declare function which(cmd: string): Promise<string>;
export declare function which(cmd: string, opt: WhichOptionsFindAllNoThrow): Promise<string[] | null>;
export declare function which(cmd: string, opt: WhichOptionsFindOneNoThrow): Promise<string | null>;
export declare function which(cmd: string, opt: WhichOptionsFindAllThrow): Promise<string[]>;
export declare function which(cmd: string, opt: WhichOptionsFindOneThrow): Promise<string>;
export declare function which(cmd: string, opt: WhichOptionsFindOne): Promise<string | null>;
export declare function which(cmd: string, opt: WhichOptionsNoThrow): Promise<string[] | string | null>;
export declare function which(cmd: string, opt: WhichOptionsFindAll): Promise<string[] | null>;
export declare function which(cmd: string, opt: WhichOptions): Promise<string[] | string | null>;
export declare function whichSync(cmd: string): string;
export declare function whichSync(cmd: string, opt: WhichOptionsFindAllNoThrow): string[] | null;
export declare function whichSync(cmd: string, opt: WhichOptionsFindOneNoThrow): string | null;
export declare function whichSync(cmd: string, opt: WhichOptionsFindAllThrow): string[];
export declare function whichSync(cmd: string, opt: WhichOptionsFindOneThrow): string;
export declare function whichSync(cmd: string, opt: WhichOptionsFindOne): string | null;
export declare function whichSync(cmd: string, opt: WhichOptionsNoThrow): string[] | string | null;
export declare function whichSync(cmd: string, opt: WhichOptionsFindAll): string[] | null;
export declare function whichSync(cmd: string, opt?: WhichOptions): string[] | string | null;
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
import { isexe, sync as isexeSync } from 'isexe';
import { delimiter, join, sep } from 'node:path';
const isWindows = process.platform === 'win32';
// used to check for slashed in commands passed in. always checks for the posix
// separator on all platforms, and checks for the current separator when not on
// a posix platform. don't use the isWindows check for this since that is
// mocked in tests but we still need the code to actually work when called.
// that is also why it is ignored from coverage.
/* c8 ignore next */
const rSlash = sep === '/' ? /\// : /[\\/]/;
const rRel = new RegExp(`^\\.${rSlash.source}`);
// Simulate a NodeJS.ErrnoException
const getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' });
const getPathInfo = (cmd, { path: optPath = process.env.PATH, pathExt: optPathExt = process.env.PATHEXT, delimiter: optDelimiter = delimiter, }) => {
// If it has a slash, then we don't bother searching the pathenv.
// just check the file itself, and that's it.
const pathEnv = cmd.match(rSlash) ?
['']
: [
// windows always checks the cwd first
/* c8 ignore next - platform-specific */
...(isWindows ? [process.cwd()] : []),
...(optPath ?? /* c8 ignore next - very unusual */ '').split(optDelimiter),
];
if (isWindows) {
const pathExtExe = optPathExt ||
['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter);
const pathExt = pathExtExe
.split(optDelimiter)
.flatMap(item => [item, item.toLowerCase()]);
if (cmd.includes('.') && pathExt[0] !== '') {
pathExt.unshift('');
}
return { pathEnv, pathExt, pathExtExe };
/* c8 ignore start - not reachable on windows */
}
return { pathEnv, pathExt: [''] };
};
/* c8 ignore stop */
const getPathPart = (raw, cmd) => {
const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : '';
return prefix + join(pathPart, cmd);
};
export async function which(cmd, opt = {}) {
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
const found = [];
for (const envPart of pathEnv) {
const p = getPathPart(envPart, cmd);
for (const ext of pathExt) {
const withExt = p + ext;
const is = await isexe(withExt, {
pathExt: pathExtExe,
ignoreErrors: true,
});
if (is) {
if (!opt.all) {
return withExt;
}
found.push(withExt);
}
}
}
if (opt.all && found.length) {
return found;
}
if (opt.nothrow) {
return null;
}
throw getNotFoundError(cmd);
}
export function whichSync(cmd, opt = {}) {
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
const found = [];
for (const pathEnvPart of pathEnv) {
const p = getPathPart(pathEnvPart, cmd);
for (const ext of pathExt) {
const withExt = p + ext;
const is = isexeSync(withExt, {
pathExt: pathExtExe,
ignoreErrors: true,
});
if (is) {
if (!opt.all) {
return withExt;
}
found.push(withExt);
}
}
}
if (opt.all && found.length) {
return found;
}
if (opt.nothrow) {
return null;
}
throw getNotFoundError(cmd);
}
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { isexe, sync as isexeSync } from 'isexe'\nimport { delimiter, join, sep } from 'node:path'\n\nconst isWindows = process.platform === 'win32'\n\n// used to check for slashed in commands passed in. always checks for the posix\n// separator on all platforms, and checks for the current separator when not on\n// a posix platform. don't use the isWindows check for this since that is\n// mocked in tests but we still need the code to actually work when called.\n// that is also why it is ignored from coverage.\n/* c8 ignore next */\nconst rSlash = sep === '/' ? /\\// : /[\\\\/]/\nconst rRel = new RegExp(`^\\\\.${rSlash.source}`)\n\n// Simulate a NodeJS.ErrnoException\nconst getNotFoundError = (cmd: string) =>\n Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' })\n\nconst getPathInfo = (\n cmd: string,\n {\n path: optPath = process.env.PATH,\n pathExt: optPathExt = process.env.PATHEXT,\n delimiter: optDelimiter = delimiter,\n }: WhichOptions,\n) => {\n // If it has a slash, then we don't bother searching the pathenv.\n // just check the file itself, and that's it.\n const pathEnv =\n cmd.match(rSlash) ?\n ['']\n : [\n // windows always checks the cwd first\n /* c8 ignore next - platform-specific */\n ...(isWindows ? [process.cwd()] : []),\n ...(optPath ?? /* c8 ignore next - very unusual */ '').split(\n optDelimiter,\n ),\n ]\n\n if (isWindows) {\n const pathExtExe =\n optPathExt ||\n ['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter)\n const pathExt = pathExtExe\n .split(optDelimiter)\n .flatMap(item => [item, item.toLowerCase()])\n if (cmd.includes('.') && pathExt[0] !== '') {\n pathExt.unshift('')\n }\n return { pathEnv, pathExt, pathExtExe }\n /* c8 ignore start - not reachable on windows */\n }\n\n return { pathEnv, pathExt: [''] }\n}\n/* c8 ignore stop */\n\nconst getPathPart = (raw: string, cmd: string) => {\n const pathPart = /^\".*\"$/.test(raw) ? raw.slice(1, -1) : raw\n const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : ''\n return prefix + join(pathPart, cmd)\n}\n\nexport type WhichOptions = {\n all?: boolean\n path?: string\n pathExt?: string\n nothrow?: boolean\n delimiter?: string\n}\n\nexport type WhichOptionsFindAll = WhichOptions & { all: true }\nexport type WhichOptionsFindOne = WhichOptions & { all?: false }\n\nexport type WhichOptionsNoThrow = WhichOptions & { nothrow: true }\nexport type WhichOptionsThrow = WhichOptions & { nothrow?: false }\n\nexport type WhichOptionsFindOneThrow = WhichOptionsFindOne &\n WhichOptionsThrow\nexport type WhichOptionsFindOneNoThrow = WhichOptionsFindOne &\n WhichOptionsNoThrow\n\nexport type WhichOptionsFindAllNoThrow = WhichOptionsFindAll &\n WhichOptionsNoThrow\nexport type WhichOptionsFindAllThrow = WhichOptionsFindAll &\n WhichOptionsThrow\n\nexport async function which(cmd: string): Promise<string>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindAllNoThrow,\n): Promise<string[] | null>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindOneNoThrow,\n): Promise<string | null>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindAllThrow,\n): Promise<string[]>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindOneThrow,\n): Promise<string>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindOne,\n): Promise<string | null>\nexport async function which(\n cmd: string,\n opt: WhichOptionsNoThrow,\n): Promise<string[] | string | null>\nexport async function which(\n cmd: string,\n opt: WhichOptionsFindAll,\n): Promise<string[] | null>\nexport async function which(\n cmd: string,\n opt: WhichOptions,\n): Promise<string[] | string | null>\nexport async function which(cmd: string, opt: WhichOptions = {}) {\n const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt)\n const found = []\n\n for (const envPart of pathEnv) {\n const p = getPathPart(envPart, cmd)\n\n for (const ext of pathExt) {\n const withExt = p + ext\n const is = await isexe(withExt, {\n pathExt: pathExtExe,\n ignoreErrors: true,\n })\n if (is) {\n if (!opt.all) {\n return withExt\n }\n found.push(withExt)\n }\n }\n }\n\n if (opt.all && found.length) {\n return found\n }\n\n if (opt.nothrow) {\n return null\n }\n\n throw getNotFoundError(cmd)\n}\n\nexport function whichSync(cmd: string): string\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindAllNoThrow,\n): string[] | null\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindOneNoThrow,\n): string | null\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindAllThrow,\n): string[]\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindOneThrow,\n): string\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindOne,\n): string | null\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsNoThrow,\n): string[] | string | null\nexport function whichSync(\n cmd: string,\n opt: WhichOptionsFindAll,\n): string[] | null\nexport function whichSync(\n cmd: string,\n opt?: WhichOptions,\n): string[] | string | null\nexport function whichSync(cmd: string, opt: WhichOptions = {}) {\n const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt)\n const found = []\n\n for (const pathEnvPart of pathEnv) {\n const p = getPathPart(pathEnvPart, cmd)\n\n for (const ext of pathExt) {\n const withExt = p + ext\n const is = isexeSync(withExt, {\n pathExt: pathExtExe,\n ignoreErrors: true,\n })\n if (is) {\n if (!opt.all) {\n return withExt\n }\n found.push(withExt)\n }\n }\n }\n\n if (opt.all && found.length) {\n return found\n }\n\n if (opt.nothrow) {\n return null\n }\n\n throw getNotFoundError(cmd)\n}\n"]}
{
"type": "module"
}