# seniority

> Every export of seniority, with its signature and doc comment: explain, ConfigError, envBoolean, envName, ORDER, RANK and 34 more, plus 31 types.

Source: https://seniority.interlace.tools/docs/api

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

seniority — which source outranks the others.

One resolution for flags, environment, config files, a `package.json` field and declared
defaults, in a fixed order, with **provenance**: every value can say where it came from.
That last part is the whole reason this is a package rather than a function — `--explain`
is only trustworthy if the thing that picked the value is the thing that reports it.

    flag  >  env  >  config file  >  package.json field  >  default

The order is not configurable. A precedence a program can rearrange is a precedence
nobody can reason about from the outside.

`resolve` is pure — layers in, values and provenance out — so it can be tested without a
filesystem, an environment, or a process. `discover` is the half that does touch the
disk, and it is a separate import for exactly that reason.

Zero dependencies; Node builtins only.

```ts
import { explain, ConfigError, envBoolean, … } from 'seniority';
```

## Functions

### check

The throwing form: the resolved values, or one `CONFIG`-class error listing every
violation. `validate` is the record; this is the rendering a program that just wants to
exit reaches for (E1, E3 — a message and a hint, never a stack).

```ts
function check(shape: Record<string, Shape>, resolution: Resolution): Record<string, unknown>;
```

| Parameter | Type |
| :-- | :-- |
| `shape` | `Record<string, Shape>` |
| `resolution` | `Resolution` |

**Returns** `Record<string, unknown>`

### decodeFileContent

A config file saved as UTF-16 — PowerShell's `Out-File` default on Windows — is not valid
UTF-8, and reading it as UTF-8 produces text no parser can use. A UTF-8 BOM is deliberately
left where it is: that is what 10.0.1 does, and one of its four cases asserts it.

```ts
function decodeFileContent(buffer: Buffer): string;
```

| Parameter | Type |
| :-- | :-- |
| `buffer` | `Buffer` |

**Returns** `string`

### explanationEvent

The agent rendering: the family's `{ event, data }` envelope over the same projection.

```ts
function explanationEvent(e: Explanation): ExplanationEvent;
```

| Parameter | Type |
| :-- | :-- |
| `e` | `Explanation` |

**Returns** `ExplanationEvent`

### explanationJson

The `--json` rendering: the same record, with `set` spelled out rather than inferred from a missing key.

```ts
function explanationJson(e: Explanation): ExplanationJson;
```

| Parameter | Type |
| :-- | :-- |
| `e` | `Explanation` |

**Returns** `ExplanationJson`

### getDefaultSearchPlaces

`.foorc`, `.foorc.json`, `foo.config.js`, … — the async explorer's twenty-one places, in order.

```ts
function getDefaultSearchPlaces(moduleName: string): string[];
```

| Parameter | Type |
| :-- | :-- |
| `moduleName` | `string` |

**Returns** `string[]`

### getDefaultSearchPlacesSync

The same list minus every `.mjs`: a synchronous load cannot import an ES module.

```ts
function getDefaultSearchPlacesSync(moduleName: string): string[];
```

| Parameter | Type |
| :-- | :-- |
| `moduleName` | `string` |

**Returns** `string[]`

### getPropertyByPath

A property name, or a period-delimited path, or an array of names.

The literal key wins: `getPropertyByPath(source, 'ant.beetle.cootie')` returns
`source['ant.beetle.cootie']` when that key exists, and only otherwise splits on periods.
A name with a period *inside* a path can therefore only be expressed as an array, which is
what the array form is for.

**The walk guards `undefined` and nothing else**, as 10.0.1's does. A path through a string
reads the string's own properties (`packageProp: 'name.length'` is a number), and a path
through a `null` — `"foo": null` under `packageProp: 'foo.bar'` — throws the `TypeError`
upstream throws, which the loader then annotates with the file. `lilconfig.ts` reproduces
the same throw on purpose; a guard here would make the two façades disagree about one file.

```ts
function getPropertyByPath(source: unknown, path: string | readonly string[]): unknown;
```

| Parameter | Type |
| :-- | :-- |
| `source` | `unknown` |
| `path` | `string \| readonly string[]` |

**Returns** `unknown`

### loaderFor

The loader for a path, or the `USAGE` refusal that names what is missing.

```ts
function loaderFor(filepath: string, loaders?: Readonly<Record<string, Loader>>): Loader;
```

| Parameter | Type |
| :-- | :-- |
| `filepath` | `string` |
| `loaders` (optional) | `Readonly<Record<string, Loader>>` |

**Returns** `Loader`

### loadPath

Read one file and parse it. The object check is here rather than in each loader so a
caller's loader cannot be the reason a non-object reaches the resolver.

```ts
function loadPath(filepath: string, options?: LoadOptions): Promise<Record<string, unknown>>;
```

| Parameter | Type |
| :-- | :-- |
| `filepath` | `string` |
| `options` (optional) | `LoadOptions` |

**Returns** `Promise<Record<string, unknown>>`

### search

The nearest match, or `undefined`.

**Proximity outranks the name.** Every name is checked in one directory before the walk
steps up, so a `.apprc` beside you wins over an `app.config.json` two directories above
even when the caller listed the latter first. That is the question an upward walk is
being asked; ordering by name instead would answer a different one silently.

```ts
function search(names: string | readonly string[], options: SearchOptions): Found | undefined;
```

| Parameter | Type |
| :-- | :-- |
| `names` | `string \| readonly string[]` |
| `options` | `SearchOptions` |

**Returns** `Found \| undefined`

### searchAll

Every match on the way up, nearest directory first and, within a directory, in the order given.

```ts
function searchAll(names: string | readonly string[], options: SearchOptions): Found[];
```

| Parameter | Type |
| :-- | :-- |
| `names` | `string \| readonly string[]` |
| `options` | `SearchOptions` |

**Returns** `Found[]`

### validate

Every violation, in the order the shape declares its options — never the first one alone.
A config file with three mistakes should be fixable in one pass, not three runs.

```ts
function validate(shape: Record<string, Shape>, resolution: Resolution): Violation[];
```

| Parameter | Type |
| :-- | :-- |
| `shape` | `Record<string, Shape>` |
| `resolution` | `Resolution` |

**Returns** `Violation[]`

## Classes

### LoaderError

A format nobody declared a loader for.

`USAGE` and not `CONFIG` on purpose. `CONFIG` (3) tells the user their configuration file
is wrong, and sends them to read a file that may be perfectly good; the mistake is the
program's, one line up, where it did not declare the loader it needs. Carrying the code on
the error rather than choosing it at the exit is what lets a façade report it correctly
without this package owning a process.

```ts
class LoaderError extends Error {
    readonly extension: string;
    readonly hint: string;
    readonly exitCode = 2;
    constructor(message: string, extension: string, hint: string);
}
```

## Constants

### builtinLoaders

The four Node can read unaided. Frozen: one caller's `loaders['.json'] = …` must not reach another's.

```ts
const defaultLoaders: Readonly<Record<string, Loader>>;
```

### defaultLoaders

The async loader table. Frozen: `index.test.ts` asserts that deleting a key throws.

```ts
const defaultLoaders: Readonly<Record<string, Loader>>;
```

### defaultLoadersSync

The sync table: no `.mjs`, no `.mts`, and `loadJsSync` in place of `loadJs`.

```ts
const defaultLoadersSync: Readonly<Record<string, Loader>>;
```

### globalConfigSearchPlaces

Tried in the user's global config directory, which is always the last directory a `global` search visits.

```ts
const globalConfigSearchPlaces: string[];
```

### globalConfigSearchPlacesSync

The same, minus `.mjs`.

```ts
const globalConfigSearchPlacesSync: string[];
```

### metaSearchPlaces

Where cosmiconfig looks for its *own* configuration — the `cosmiconfig` key of a
`.config/config.*` or a `package.json`. Internal to 10.0.1 and exported here because the
meta explorer is the one part of the option pipeline a caller can observe.

```ts
const metaSearchPlaces: string[];
```

### NOT_BUNDLED

The formats a caller may supply and this package will not bundle, listed so the refusal can
name them and so a reader can see the 747 M/wk that is being declined rather than missed.

```ts
const NOT_BUNDLED: readonly string[];
```

### WALK_LIMIT

How many directories one walk may visit.

A number rather than "until the root" alone, because the root is not the only way a walk
ends badly: a bind mount, a container overlay or a deliberately deep fixture tree all
present as an ancestor chain that is long rather than infinite. Sixty-four is far past any
real repository — a monorepo package sits six or seven directories down — and small enough
that the worst case is imperceptible.

```ts
const WALK_LIMIT = 64;
```

## Interfaces

### ExplanationEvent

```ts
interface ExplanationEvent {
    event: 'config.explain';
    data: ExplanationJson;
}
```

### ExplanationJson

```ts
interface ExplanationJson {
    option: string;
    value?: unknown;
    source?: string;
    location?: string;
    line?: number;
    candidates: ExplanationCandidateJson[];
}
```

### Found

```ts
interface Found {
    /** The file, absolute. */
    path: string;
    /** The directory it was found in, absolute. */
    dir: string;
    /** How many steps up from `cwd` — `0` is `cwd` itself. What `--explain` prints as "found N levels up". */
    depth: number;
}
```

### LoadOptions

```ts
interface LoadOptions {
    /** Merged over `defaultLoaders`; a caller may add a format or replace a builtin. */
    loaders?: Readonly<Record<string, Loader>>;
}
```

### SearchOptions

```ts
interface SearchOptions {
    /** Where the walk starts. The first directory checked, not the first one above it. */
    cwd: string;
    /** The highest directory the walk may look in, inclusive. Defaults to the filesystem root. */
    stopAt?: string;
    /** Directories to visit at most. Defaults to `WALK_LIMIT`; a smaller number wins. */
    limit?: number;
    /** Injected for tests and for a caller with its own filesystem. Defaults to `existsSync`. */
    exists?: (path: string) => boolean;
    /** Injected the same way. Defaults to `realpathSync`, and a path that cannot be resolved is used as written. */
    realpath?: (path: string) => string;
}
```

### Shape

What validation reads from a manifest, and no more.

`type` is checked when it is one of the four JavaScript kinds and ignored otherwise: a
shape that says nothing asserts nothing, which is what lets a richer spec pass through a
field this package has never heard of.

```ts
interface Shape {
    type?: string;
    choices?: readonly unknown[];
    required?: boolean;
    default?: unknown;
}
```

### Violation

```ts
interface Violation {
    key: string;
    /** The whole sentence, ready to print: the rule, then where the value came from. */
    message: string;
    /** What the value should have been — `'a string'`, `'one of fast, safe'`. */
    expected: string;
    value: unknown;
    /** Absent only for a required option that no source set: there is no origin to name. */
    provenance?: Provenance;
}
```

## Types

### Loader

What a loader is handed and what it gives back. The same shape `cosmiconfig` uses, so a caller's loader ports unchanged.

```ts
type Loader = (filepath: string, content: string) => unknown;
```

## Re-exported

Documented on the page of the entry point that declares them.

| Export | Kind | Documented in |
| :-- | :-- | :-- |
| `candidates` | function | [`seniority/config`](/docs/api/config#candidates) |
| `cosmiconfig` | function | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#cosmiconfig) |
| `cosmiconfigSync` | function | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#cosmiconfigsync) |
| `deepMerge` | function | [`seniority/config`](/docs/api/config#deepmerge) |
| `discover` | function | [`seniority/config`](/docs/api/config#discover) |
| `envBoolean` | function | [`seniority/precedence`](/docs/api/precedence#envboolean) |
| `envName` | function | [`seniority/precedence`](/docs/api/precedence#envname) |
| `explain` | function | [`seniority/explain`](/docs/api/explain#explain) |
| `explanation` | function | [`seniority/explain`](/docs/api/explain#explanation) |
| `lineOf` | function | [`seniority/config`](/docs/api/config#lineof) |
| `loadWithExtends` | function | [`seniority/config`](/docs/api/config#loadwithextends) |
| `renderExplanation` | function | [`seniority/explain`](/docs/api/explain#renderexplanation) |
| `resolve` | function | [`seniority/precedence`](/docs/api/precedence#resolve) |
| `screaming` | function | [`seniority/precedence`](/docs/api/precedence#screaming) |
| `ConfigError` | class | [`seniority/precedence`](/docs/api/precedence#configerror) |
| `Explorer` | class | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#explorer) |
| `ExplorerSync` | class | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#explorersync) |
| `ORDER` | const | [`seniority/precedence`](/docs/api/precedence#order) |
| `RANK` | const | [`seniority/precedence`](/docs/api/precedence#rank) |
| `Candidate` | interface | [`seniority/precedence`](/docs/api/precedence#candidate) |
| `CommonOptions` | interface | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#commonoptions) |
| `Discovery` | interface | [`seniority/config`](/docs/api/config#discovery) |
| `Explanation` | interface | [`seniority/explain`](/docs/api/explain#explanation) |
| `Layer` | interface | [`seniority/precedence`](/docs/api/precedence#layer) |
| `Layers` | interface | [`seniority/precedence`](/docs/api/precedence#layers) |
| `LoadConfigOptions` | interface | [`seniority/config`](/docs/api/config#loadconfigoptions) |
| `Loaded` | interface | [`seniority/config`](/docs/api/config#loaded) |
| `Options` | interface | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#options) |
| `OptionSpec` | interface | [`seniority/precedence`](/docs/api/precedence#optionspec) |
| `Provenance` | interface | [`seniority/precedence`](/docs/api/precedence#provenance) |
| `PublicExplorer` | interface | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#publicexplorer) |
| `PublicExplorerSync` | interface | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#publicexplorersync) |
| `Resolution` | interface | [`seniority/precedence`](/docs/api/precedence#resolution) |
| `SourceLayer` | interface | [`seniority/precedence`](/docs/api/precedence#sourcelayer) |
| `BuiltinSource` | type | [`seniority/precedence`](/docs/api/precedence#builtinsource) |
| `Config` | type | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#config) |
| `CosmiconfigResult` | type | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#cosmiconfigresult) |
| `Loaders` | type | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#loaders) |
| `OptionsSync` | type | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#optionssync) |
| `SearchStrategy` | type | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#searchstrategy) |
| `Source` | type | [`seniority/precedence`](/docs/api/precedence#source) |
| `Transform` | type | [`seniority/cosmiconfig`](/docs/api/cosmiconfig#transform) |
