/** * Blue/green manifest swap with health gating + auto-rollback. * * Pattern: the registry serves a single manifest, and operators stage a new * one ("green") next to the live one ("blue"). `BlueGreenRegistry` exposes: * - `current()` — the live manifest * - `stage(next)` — load a candidate, return its slot id * - `promote(id)` — atomic swap; runs health gate; rolls back on failure * - `rollback()` — manual revert to previous blue * * The swap is "atomic" from a reader's perspective because `current()` * dereferences a single ref. Concurrent in-flight reads see either pre-swap * or post-swap — never a half-blended manifest. * * Health gating is pluggable so callers can run shape-validation, * /jorvel/health probes, smoke tests, etc. */ export interface BlueGreenRemote { name: string; entryUrl: string; version?: string; integrity?: string; weight?: number; } export interface BlueGreenManifest { version?: string; remotes: BlueGreenRemote[]; } export type HealthCheck = (manifest: BlueGreenManifest) => boolean | Promise; export interface BlueGreenOptions { initial: BlueGreenManifest; /** Required gate run before a promote; reject promotion if it returns false / throws. */ healthCheck?: HealthCheck; /** Max ms the health check may take. Default: 5_000. */ healthTimeoutMs?: number; /** Listener for every transition — useful for telemetry. */ onTransition?: (event: BlueGreenTransition) => void; } export type BlueGreenTransition = { type: 'staged'; slotId: string; manifest: BlueGreenManifest; } | { type: 'promote-start'; slotId: string; } | { type: 'promote-success'; slotId: string; from: BlueGreenManifest; to: BlueGreenManifest; } | { type: 'promote-failed'; slotId: string; reason: string; } | { type: 'rollback'; from: BlueGreenManifest; to: BlueGreenManifest; }; export declare class BlueGreenRegistry { private blue; private previousBlue; private staged; private nextSlotId; private readonly opts; private subscribers; constructor(opts: BlueGreenOptions); current(): BlueGreenManifest; previous(): BlueGreenManifest | null; stage(next: BlueGreenManifest): string; listStaged(): string[]; promote(slotId: string): Promise; rollback(): BlueGreenManifest; subscribe(fn: (m: BlueGreenManifest) => void): () => void; private notify; private runWithTimeout; } /** * Build a default health check that compares the new manifest against the * old one: rejects empty remote lists, duplicate names, and shrinks past * `maxShrinkRatio` (default: 0.5 = ≥50% drop is suspicious). */ export interface ShapeHealthOptions { previous: BlueGreenManifest; maxShrinkRatio?: number; } export declare function shapeHealthCheck(opts: ShapeHealthOptions): HealthCheck; //# sourceMappingURL=blue-green.d.ts.map