/** * Versioning for anything this SDK writes to disk and reads back. * * Every persisted read was `JSON.parse(raw) as T` — an unchecked cast with * no idea which version of the shape it was looking at. Three things * followed, all of them silent: * * - A file written by an OLDER build was read as the current shape. * Fields added since simply arrived as `undefined` and flowed into the * runtime as though they had been there. * - A file written by a NEWER build was read by an older one, which * understood some of the fields and dropped the rest. Write it back and * the rest are gone — the only one of these that destroys data. * - Neither case produced an error, a warning, or a log line, so a * resumed session that quietly lost half its state looked exactly like * a session that never had it. * * The version is stamped as a field on the record rather than wrapping it * in an envelope, so every file already on disk stays readable: a record * with no version IS version 1, which is exactly what those files are. */ /** Records written without a stamp predate this and are that version. */ export declare const INITIAL_SCHEMA_VERSION = 1; /** Reserved key. Domain records must not use it. */ export declare const SCHEMA_VERSION_KEY = "schemaVersion"; /** A step from one version to the next. Pure; runs on the parsed record. */ export type Migration = (record: Record) => Record; export interface SchemaDefinition { /** What this record is, for error messages. */ readonly kind: string; /** The version this build writes. */ readonly current: number; /** * `migrations[n]` upgrades a version-`n` record to version `n+1`. * Every step from {@link INITIAL_SCHEMA_VERSION} to `current` must be * present, and that is checked when the schema is declared rather than * when a stale file finally shows up — a gap discovered at read time is * discovered in production, by a user whose session will not open. */ readonly migrations: Readonly>; } export declare class SchemaVersionError extends Error { readonly kind: string; readonly found: number; readonly supported: number; constructor(init: { kind: string; found: number; supported: number; message: string; }); } export declare function defineSchema(definition: SchemaDefinition): SchemaDefinition; /** * Stamp a record with the version this build writes. * * An array is returned untouched: there is nowhere on it to put a field * that survives `JSON.stringify`, and wrapping it would change the shape * of every file already written. A file whose top level is an array is * therefore unversioned, which is a real limitation — a store that needs * to migrate one has to move it under an object first. */ export declare function stamp(schema: SchemaDefinition, record: T): T; /** * Bring a parsed record up to the current version, or refuse. * * A record from the FUTURE is refused rather than read. Reading it with * today's parser means silently dropping the fields this build does not * know about — and if the caller writes it back, they are gone. A refusal * is recoverable by upgrading; a partial read that overwrites is not. */ export declare function migrate(schema: SchemaDefinition, parsed: unknown): T; //# sourceMappingURL=schema.d.ts.map