/** * The engine registry: one path for ours and anybody else's. * * WHY THIS EXISTS. The router was a `switch` over five engines, so a user with * a proprietary log format, a domain payload or simply a better compressor than * ours had nowhere to put it. HeadRoom's engine set is fixed too -- the same * closed door; an extension point is the cheapest way to be beaten less often, * because the next content type is always one nobody anticipated. * * NO COUNT IS CLAIMED HERE, deliberately. This comment said "six fixed engines" * and that number could not be supported: their README names three * (SmartCrusher for JSON, CodeCompressor for code, Kompress-v2-base for prose) * and `compression/handlers/` holds `base.py`, `code_handler.py` and * `json_handler.py`. The argument was never about how many they have; it is * about whether a user can add one. Counting a competitor's internals in a * source comment invites being wrong about them in public, and we were. * * NO PRIVILEGED TIER. The built-ins register through this exactly as a third * party does, so there is one code path to test and no "works for us, breaks * for you" class of bug. A custom engine can also claim content ahead of a * built-in, because a user who knows their own format knows better than our * heuristics do. * * THE BOUNDARY IS THE SAME GUARANTEE WE HOLD OURSELVES TO, not a sandbox: * * - output larger than input is discarded; * - a throw is caught and the input passes through untouched; * - a lossy elision with nowhere to recover from is refused outright; * - signed content never reaches any engine, which the strategy enforces * before dispatch. * * That last rule is the one that catches honest mistakes rather than hostile * ones, and it caught one of ours the day it was written. * * NOT A SANDBOX, and the docs should say so plainly: a registered engine runs * in this process and sees the content it is given. Registering one is the same * trust decision as installing any dependency. */ import type { CompressionResult, Engine, EngineContext } from './types.js'; export interface EngineRegistration { /** Stable identifier, used in diagnostics and to replace a registration. */ readonly name: string; /** * Higher runs first. Built-ins register at 0, so a custom engine claiming * content ahead of them uses any positive number, and a fallback uses a * negative one. */ readonly priority?: number; /** Does this engine want the block? Must be pure and cheap. */ readonly claims: (text: string, ctx: EngineContext) => boolean; /** The transform itself. */ readonly compress: Engine; } /** Registers an engine, replacing any earlier one with the same name. */ export declare function registerEngine(engine: EngineRegistration): void; /** Removes one engine by name. Returns whether anything was removed. */ export declare function unregisterEngine(name: string): boolean; /** Every registration, highest priority first. For diagnostics and tests. */ export declare function registeredEngines(): readonly EngineRegistration[]; /** * The first engine that claims this block, or null. * * A `claims` predicate that throws is treated as "does not claim" rather than * being allowed to take down the request -- fail open applies to the decision * as well as to the transform. */ export declare function engineFor(text: string, ctx: EngineContext): EngineRegistration | null; /** * Runs one engine behind the boundary. * * Exported so the rules are testable directly rather than only through the * router, and so a caller composing engines gets the same guarantees. */ export declare function runEngine(engine: EngineRegistration, text: string, ctx: EngineContext): CompressionResult; //# sourceMappingURL=registry.d.ts.map