seniority/precedence
Every export of seniority/precedence, with its signature and doc comment: screaming, envName, envBoolean, resolve, ORDER, RANK and 1 more, plus 9 types.
One precedence order, fixed and not configurable (commander-env V1–V3, V5):
flag > env > config file > package.json field > defaultresolve is pure — it takes the layers and returns the values with their provenance —
which is what makes --explain trustworthy and meta.provenance cheap. Env applies
only to the options the running command declares (yargs #873), never to a sibling's.
import { screaming, envName, envBoolean, … } from 'seniority/precedence';Functions
envBoolean
Booleans from env accept one spelling each way (R7).
function envBoolean(raw: string): boolean | undefined;| Parameter | Type |
|---|---|
raw | string |
Returns boolean \| undefined
envName
function envName(name: string, spec: OptionSpec, prefix: string | undefined): string | undefined;| Parameter | Type |
|---|---|
name | string |
spec | OptionSpec |
prefix | string | undefined |
Returns string \| undefined
resolve
Every declared option, resolved through the layers; a missing required one is left undefined for the caller to report.
function resolve(specs: Record<string, OptionSpec>, layers: Layers): Resolution;| Parameter | Type |
|---|---|
specs | Record<string, OptionSpec> |
layers | Layers |
Returns Resolution
screaming
region → REGION, dryRun → DRY_RUN, log-level → LOG_LEVEL (yargs #2005: never camel-cased back).
function screaming(name: string): string;| Parameter | Type |
|---|---|
name | string |
Returns string
Classes
ConfigError
A value that cannot be used as configured: exit CONFIG (3), never a stack (E1, E3).
class ConfigError extends Error {
readonly hint?: string | undefined;
constructor(message: string, hint?: string | undefined);
}Constants
ORDER
The precedence, highest first — the one declaration (R1, R14).
The design's R1 wrote this array as ['flag','env','project','home','pkg','default'] and
the shipped union said 'flag'|'env'|'config'|'package'|'default'. Those are two
spellings of one fact, and a plugin cannot register against two. The shipped five win:
they are what provenance.source already prints for every user of 0.1.0, and the
project/home split the design wanted is carried more precisely by location — which
names the actual file — than a second source kind ever could.
Source is generated from this array rather than written beside it, so the drift cannot
come back: adding a kind means adding it here.
const ORDER: readonly ["flag", "env", "config", "package", "default"];RANK
const RANK: Readonly<Record<BuiltinSource, number>>;Interfaces
Candidate
interface Candidate {
source: Source;
location: string;
/** `undefined` when the layer had nothing for this option. */
value: unknown;
/** The line in `location` that set it, when the layer knows (R3). */
line?: number;
}Layer
interface Layer {
path: string;
data: Record<string, unknown>;
/**
* Key → the line in `path` that sets it, when the loader could tell (R3, R12). Optional
* everywhere: a `.js` config has no line a parser can hand back without a parser, and a
* missing line is reported as a missing line rather than as line zero.
*/
lines?: Record<string, number>;
}Layers
interface Layers {
/** What the user typed: only options present on the command line. */
flags: Record<string, unknown>;
env: Record<string, string | undefined>;
/** With a prefix, an option without `env:` reads `PREFIX_OPTION_NAME` (R2). */
envPrefix?: string;
config?: Layer;
/** The `package.json` field named after the program, when present. */
pkg?: Layer;
/** Plugin-contributed sources, already read — see `seniority/plugin`'s `sources()`. */
sources?: readonly SourceLayer[];
}OptionSpec
What resolution needs to know about an option, and no more.
burgee's OptionSpec carries eighteen fields — choices, schema, placeholder,
deprecation, the lot. Resolving a value reads three of them. Declaring those
three here is what lets any program use seniority with its OWN option type:
TypeScript's structural typing accepts a richer spec with no adapter, no
import, and no dependency pointing back up the stack.
interface OptionSpec {
/** Only `'boolean'` changes how the environment is read; everything else stays text. */
type?: string;
/** Environment variable consulted when the flag is absent (V2). */
env?: string;
default?: unknown;
}Provenance
interface Provenance {
source: Source;
/** The env name, the config file, or `package.json` — where a person would look. */
location?: string;
/** The line within `location`, when the layer recorded one (R3). A file source may; an env name cannot. */
line?: number;
}Resolution
interface Resolution {
values: Record<string, unknown>;
provenance: Record<string, Provenance>;
candidates: Record<string, Candidate[]>;
}SourceLayer
A layer contributed by something other than the five — the sources plugin host, already
read, so resolve stays pure over what it is handed (R2, R11).
interface SourceLayer {
/** The kind `--explain` prints and `provenance.source` carries: the plugin's own name for it. */
source: string;
/** Where a person would look — a path, a URL, a variable set. */
location: string;
/** Against `RANK`; strictly between `RANK.flag` and `RANK.default`. */
rank: number;
data: Record<string, unknown>;
}Types
BuiltinSource
The five seniority resolves itself.
type BuiltinSource = (typeof ORDER)[number];Source
An open union (R13, PLAN D5). A plugin's source is a Source seniority has never
heard of; (string & {}) keeps the five as completions while admitting the rest, so the
sources host of PLAN 1.3 is the additive change it reads as rather than a type break.
type Source = BuiltinSource | (string & {});