seniority/plugin
Every export of seniority/plugin, with its signature and doc comment: validate, register, reset, registered, sources, CONTRACT and 1 more, plus 5 types.
The plugin host for seniority's half of the contract (plugin-contract R1, R5a, R6, R7, R8).
A plugin is one plain object shared by the whole family. This file keeps the key seniority
understands — sources, a resolution source — and ignores every other key without
complaining, which is what makes the same object work on any subset of the family that
is installed. A plugin written for flagstaff registers here and contributes nothing; its
spinners and components are not seniority's business and are not an error.
Nothing here imports another layer, and the shape is declared rather than imported. Types erase, so an import would cost nothing at run time — and it would still put another package in seniority's dependency story, which is the one thing the family promises it does not do.
A plugin adds a source; it cannot reorder the five. rank slots a source between two
built-ins and nothing else: below RANK.flag, so what the user typed on the command line
always wins, and above RANK.default, so a declared default stays the floor. Both bounds
are refused at the door rather than clamped, because a source silently demoted to last
looks like it worked and the author debugs the wrong thing. "The order is not
configurable" survives extension exactly this far, and no further.
Reading happens here, not in resolve. resolve is pure over the layers it is
handed (R2) and nothing in this package reads process.* (R11) — so sources(runtime)
is the seam: the caller passes its own { env, cwd }, this file calls each read, and
what resolve receives is data.
import { validate, register, reset, … } from 'seniority/plugin';Functions
register
Register a plugin. Later wins at an equal rank, like ESLint flat config: the array is ordered, a caller reads it top to bottom, and the last word on a source is the one nearest the program.
function register(plugin: unknown): void;| Parameter | Type |
|---|---|
plugin | unknown |
Returns void
registered
The plugins registered, in registration order.
function registered(): readonly Plugin[];Returns readonly Plugin[]
reset
Forget every registered plugin. For tests, and for a program that re-registers at runtime.
function reset(): void;Returns void
sources
Every registered source, read against this runtime and sorted by rank — the array
resolve takes as layers.sources.
A source whose read returns undefined had nothing for this run and contributes no
candidate at all, which is different from contributing an empty one: --explain should
not list a vault that was never reachable as a source that was consulted and lost.
function sources(runtime: SourceRuntime): SourceLayer[];| Parameter | Type |
|---|---|
runtime | SourceRuntime |
Returns SourceLayer[]
validate
Refuse a plugin that cannot contribute a source, at the door.
function validate(plugin: unknown): asserts plugin is Plugin;| Parameter | Type |
|---|---|
plugin | unknown |
Returns asserts plugin is Plugin
Classes
PluginError
A refused plugin says what is wrong and what to do about it — the family's one vocabulary.
class PluginError extends Error {
readonly code: PluginErrorCode;
readonly fix: string;
constructor(code: PluginErrorCode, message: string, fix: string);
}Constants
CONTRACT
The plugin contract version. One number for the family — the same 1 flagstaff declares,
written out rather than imported for the reason in the file comment above.
const CONTRACT = 1;Interfaces
Plugin
The keys seniority reads. Declared structurally: any object with these fields is a plugin here, whatever else it carries.
interface Plugin {
name: string;
contract?: number;
sources?: Record<string, SourceSpec>;
}SourceRead
What a read returns when it has something to say.
interface SourceRead {
values: Record<string, unknown>;
/** Where a person would look. Falls back to the source's `location`, then to its name. */
location?: string;
}SourceRuntime
What a source is handed. Declared structurally and deliberately small: env and cwd are
what a vault, a CI variable set or a remote config needs, and anything a plugin could do
with process directly it should be given instead (R11, Y9).
interface SourceRuntime {
env: Record<string, string | undefined>;
cwd: string;
}SourceSpec
One source a plugin contributes, keyed in sources by the name --explain prints.
Exactly one of values and read. values is the data-first form R7 asks for — a source
that is a constant is inspectable without being run — and read is the dynamic form R5a
names, for the vault or the remote config that has to go and look.
interface SourceSpec {
/** Against `RANK`: strictly between `RANK.flag` and `RANK.default`. */
rank: number;
values?: Record<string, unknown>;
location?: string;
read?: (runtime: SourceRuntime) => SourceRead | undefined;
}Types
PluginErrorCode
type PluginErrorCode = 'E_PLUGIN_SCHEMA' | 'E_PLUGIN_CONTRACT' | 'E_NO_CONTRIBUTION';seniority/explain
Every export of seniority/explain, with its signature and doc comment: explain, explanation, renderExplanation, plus 1 type.
seniority/cosmiconfig
Every export of seniority/cosmiconfig, with its signature and doc comment: cosmiconfig, cosmiconfigSync, Explorer, ExplorerSync, plus 10 types.