# bellpull/which

> Every export of bellpull/which, with its signature and doc comment: pathExtensions, extensionCandidates, searchPath, whichAllSync, whichSync, resolveExecutable and 5 more, plus 3 types.

Source: https://bellpull.interlace.tools/docs/api/which

<!-- Generated by scripts/api-reference.ts from the built dist/*.d.ts. Do not edit; run `npx tsx scripts/api-reference.ts`. -->

```ts
import { pathExtensions, extensionCandidates, searchPath, … } from 'bellpull/which';
```

## Functions

### extensionCandidates

The extensions tried for this command, in order.

On Windows a command that already carries a dot may be complete as written, so the empty
extension goes first — `which` does the same, and `whoami.cmd` on `PATH` depends on it.

```ts
function extensionCandidates(command: string, options: WhichOptions): string[];
```

| Parameter | Type |
| :-- | :-- |
| `command` | `string` |
| `options` | `WhichOptions` |

**Returns** `string[]`

### pathExtensions

The `PATHEXT` list for this runtime, as an array. `['']` off Windows: no expansion.

Exported because it is the one half of Windows resolution that can be *checked* from
another platform: which extensions are tried, and in what order, is policy, whereas
whether `C:\\tools\\npm.cmd` exists is a fact about a filesystem that is not here.

```ts
function pathExtensions(options: WhichOptions): string[];
```

| Parameter | Type |
| :-- | :-- |
| `options` | `WhichOptions` |

**Returns** `string[]`

### resolveExecutable

Where `command` resolves to for the purpose of **spawning it** — two `PATHEXT` attempts,
not one, as `cross-spawn` does.

`PATHEXT` answers "what would the shell run if I typed this", which is right for `which`
and wrong for a spawner: an extensionless file with a `#!` line is still runnable here,
because `spawn-args.ts` puts the interpreter in front of it. So the walk is repeated with
expansion disabled.

**One function, because two callers asking this differently is a bug and was one.**
`spawn-args.ts` made both attempts and `run.ts` only the first, so on Windows a shebang
script resolved for the parse and was then refused by `run()` with `NotFoundError`. Off
Windows `pathExtensions` is always `['']` and the second attempt is the first, so the
divergence was invisible to a 68 / 68 grading.

```ts
function resolveExecutable(command: string, options: WhichOptions): Resolution | undefined;
```

| Parameter | Type |
| :-- | :-- |
| `command` | `string` |
| `options` | `WhichOptions` |

**Returns** `Resolution \| undefined`

### runPath

`PATH` with every `node_modules/.bin` from `cwd` upward in front of it — `npm-run-path`'s
contract (104 M/wk, 2 dependencies, last published 2024-08-26).

Twelve lines rather than a sibling dependency (design R4): the walk stops at the
filesystem root, which `resolve` of `'..'` reports by returning its own argument.

```ts
function runPath(options: WhichOptions): string;
```

| Parameter | Type |
| :-- | :-- |
| `options` | `WhichOptions` |

**Returns** `string`

### searchPath

The directories this runtime would search, in order — the static projection of resolution
(PRINCIPLES rule 6).

A caller, or an agent, reads what *would* happen without running anything. It is also
where the two refusals above become visible: an entry dropped for being empty or relative
is listed with the reason, so a `PATH` that silently does less than its author expected
says so.

```ts
function searchPath(options: WhichOptions): SearchEntry[];
```

| Parameter | Type |
| :-- | :-- |
| `options` | `WhichOptions` |

**Returns** `SearchEntry[]`

### whichAllSync

Every place `command` resolves to, best first. Empty when it resolves nowhere.

`all` in `which`'s API; here it is the primitive and the single answer is the first of it,
because "there are two `node`s on this `PATH`" is the finding an investigation wants and
throwing away everything after the first is what stops it being available.

```ts
function whichAllSync(command: string, options: WhichOptions): Resolution[];
```

| Parameter | Type |
| :-- | :-- |
| `command` | `string` |
| `options` | `WhichOptions` |

**Returns** `Resolution[]`

### whichOrThrowSync

Where `command` resolves to, throwing {@link NotFoundError} when it resolves nowhere.

`which`'s own shape, for the callers that want it — and the one place in this package
where not finding something is an exception, because the caller asked a question that has
no other answer.

```ts
function whichOrThrowSync(command: string, options: WhichOptions): Resolution;
```

| Parameter | Type |
| :-- | :-- |
| `command` | `string` |
| `options` | `WhichOptions` |

**Returns** `Resolution`

### whichSync

Where `command` resolves to, or `undefined`.

The non-throwing form, because "it is not installed" is an ordinary answer that a caller
branches on — the same argument the `Result` in `run.ts` makes about a non-zero exit.

```ts
function whichSync(command: string, options: WhichOptions): Resolution | undefined;
```

| Parameter | Type |
| :-- | :-- |
| `command` | `string` |
| `options` | `WhichOptions` |

**Returns** `Resolution \| undefined`

## Classes

### NotFoundError

`Error` with the `code` a caller switches on, and the command it could not find.

```ts
class NotFoundError extends Error {
    readonly command: string;
    readonly code = "ENOENT";
    constructor(command: string);
}
```

## Constants

### delimiter

The platform-specific file delimiter. ';' or ':'.

```ts
const delimiter: ";" | ":";
```

### sep

The platform-specific file separator. '\\' or '/'.

```ts
const sep: "\\" | "/";
```

## Interfaces

### Resolution

Where an executable was found, and what found it.

```ts
interface Resolution {
    /** The absolute path of the file that would be executed. */
    path: string;
    /**
     * The `PATH` entry it was found under, or `''` when the command carried its own path and
     * `PATH` was never consulted. This is the field no incumbent returns.
     */
    from: string;
    /**
     * The extension appended from `PATHEXT` to find it — `.CMD`, `.EXE`. Always `''` off
     * Windows, where the file is executable or it is not.
     */
    ext: string;
}
```

### SearchEntry

One directory to search, and whether it was skipped and why.

```ts
interface SearchEntry {
    /** The entry as it appeared on `PATH`, before quotes were stripped or it was resolved. */
    raw: string;
    /** The absolute directory that will be searched, when it will be. */
    dir?: string;
    /** Why it will not be, when it will not: a reader can see the hole rather than infer it. */
    skipped?: 'empty' | 'relative';
}
```

### WhichOptions

```ts
interface WhichOptions {
    /** The ambient state. Required in spirit; defaulted only by the façades. */
    runtime: Runtime;
    /** Override the `PATH` string. Overrides `runtime.env`'s, as `which`'s `path` does. */
    path?: string | undefined;
    /** Override `PATHEXT`. `''` disables extension expansion entirely. */
    pathExt?: string | undefined;
    /** Resolve relative entries and relative commands against this instead of `runtime.cwd`. */
    cwd?: string | undefined;
}
```
