# paratext/plugin

> Every export of paratext/plugin, with its signature and doc comment: validate, register, reset, registered, contributions, attach and 2 more, plus 4 types.

Source: https://paratext.interlace.tools/docs/api/plugin

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

The plugin host for paratext'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 paratext
understands — **`capabilities`** (R5a), OSC records by name — 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 `tokens`, `spinners` and `components` are not paratext's business and are not
an error.

**Why paratext needed this file more than the other hosts did.** Until it existed, paratext
was the one published package with no `src/plugin.ts` — and that file is the *marker*
`scripts/plugin-schema-lock.test.ts` and `scripts/schema-sync.mjs` both look for. So
paratext's copy of the family schema was outside the lock that keeps the copies
byte-identical: it happened to match flagstaff's, and nothing in the repository would have
said so if it stopped.

**Nothing here imports another layer, and the plugin shape is declared rather than
imported** (R3). It imports `./capability.js` because that is this package's own module:
the capability shape, the registry and `check()` have to have exactly one home, or
"fallback is required" means one thing to a plugin and another to a built-in.

**R7, and why this host is the easy case.** R7 asks that no key require a function. Here
none does: a capability is `{ name, osc, when, encode, fallback }`, five fields of plain
data with two template strings, so a plugin can arrive as JSON, be diffed, and be printed
by a `plugin check` without anybody running its author's code. closeout's `handlers` owes
R7 an exemption; `capabilities` owes it nothing, which is the argument the design makes
for holding capabilities as data in the first place.

```ts
import { validate, register, reset, … } from 'paratext/plugin';
```

## Functions

### attach

Hand every contributed capability to a registry.

Defaults to paratext's own, which is what a program wants: `attach()` after importing the
plugins, and `emit()` can then reach them by name exactly as it reaches the built-ins.
Passing a host is for a caller keeping its own registry, and for a test that wants to see
the order without touching the global one.

```ts
function attach(host?: CapabilityHost): void;
```

| Parameter | Type |
| :-- | :-- |
| `host` (optional) | `CapabilityHost` |

**Returns** `void`

### contributions

Every capability every registered plugin contributed, with who won each name.

This is the static projection of the plugin set (R7): a caller — or `burgee plugin check`
— reads what *would* be registered, and who lost, without registering anything and without
a terminal being involved.

```ts
function contributions(): Contribution[];
```

**Returns** `Contribution[]`

### register

Register a plugin. Later wins, like ESLint flat config: the array is ordered, a caller
reads it top to bottom, and the last word on a capability name is the one nearest the
program — which is also the registry's own rule, since `register()` in `capability.ts`
replaces by name so a caller can correct a guess we got wrong.

**Registering does not emit, and does not even reach the capability registry.** It records
the contribution; {@link attach} is what hands it over. That separation is what makes
{@link contributions} a static projection rather than a side effect.

```ts
function register(plugin: unknown): void;
```

| Parameter | Type |
| :-- | :-- |
| `plugin` | `unknown` |

**Returns** `void`

### registered

The plugins registered, in registration order.

```ts
function registered(): readonly Plugin[];
```

**Returns** `readonly Plugin[]`

### reset

Forget every registered plugin. For tests, and for a program that re-plugs at runtime.

```ts
function reset(): void;
```

**Returns** `void`

### validate

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

Every refusal is a refusal rather than a silent drop. A capability quietly ignored looks
like it worked right up until the day somebody runs the program on the terminal it was
written for, and then the thing they debug is the terminal.

```ts
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.

```ts
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, caique
and closeout declare, written out rather than imported for the reason in the file comment.

```ts
const CONTRACT = 1;
```

## Interfaces

### CapabilityHost

The half of the capability registry this needs — declared structurally so a caller can
attach to something it built itself, and so a host can watch what arrives.

```ts
interface CapabilityHost {
    register(capability: Capability): void;
}
```

### Contribution

One contributed capability, with the plugin it came from and the plugins it displaced.

```ts
interface Contribution {
    name: string;
    from: string;
    /** Plugins that contributed this name earlier and were overridden, in order. */
    shadowed: string[];
    capability: Capability;
}
```

### Plugin

The keys paratext reads. Declared structurally: any object with these fields is a plugin
here, whatever else it carries.

```ts
interface Plugin {
    name: string;
    contract?: number;
    /** Capabilities by name. The key and the record's own `name` must agree; see {@link validate}. */
    capabilities?: Record<string, Capability>;
}
```

## Types

### PluginErrorCode

Three codes, all of them already in flagstaff's `PluginErrorCode` — the vocabulary home
(`scripts/plugin-error-vocabulary-lock.test.ts`). `E_NO_STATIC_PROJECTION` is the one
worth noticing: flagstaff raises it for a component with no static form and caique for a
widget with no `static`, and a capability with no `fallback` is the same defect wearing
OSC. One code, one fix shape, three layers.

```ts
type PluginErrorCode = 'E_PLUGIN_SCHEMA' | 'E_PLUGIN_CONTRACT' | 'E_NO_STATIC_PROJECTION' | 'E_NO_CONTRIBUTION';
```
