seniority
API reference

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;
ParameterType
pluginunknown

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[];
ParameterType
runtimeSourceRuntime

Returns SourceLayer[]

validate

Refuse a plugin that cannot contribute a source, at the door.

function validate(plugin: unknown): asserts plugin is Plugin;
ParameterType
pluginunknown

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';

On this page