first commit
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# VersionedSchema
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`VersionedSchema` is the working unit for evolving a `BitPackerSchema` over time without breaking previously-packed data. A single `VersionedSchema` instance keeps an ordered list of `SchemaVersion` rows (each pairing a version number with a `BitPackerSchema` and an optional description), plus a list of `SchemaMigration` rows that describe how to transform data between adjacent versions. Production code constructs versioned schemas in two ways: directly via the constructor when authoring a new schema lineage, or via `SchemaRegistry.getVersionedSchema(namespace, name)` when reconstructing one from storage. It is the contract the migration engine, the registry, and the runtime pack/unpack path all consult.
|
||||
|
||||
## Features
|
||||
|
||||
- Ordered version list with `addVersion` for new entries and `latestSchema` / `latestVersion` accessors.
|
||||
- Per-version migration registration via `addMigration<U extends BitPackerSchema>` with a `MigrationFunction<T, U>`.
|
||||
- Bit-packer-aware: pack/unpack methods that select the schema by version number and route through an injectable `BitPacker`.
|
||||
- Bulk reconstruction from `SchemaRegistry` storage rows.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { VersionedSchema } from "@suaveplan/bitpacker-schema";
|
||||
|
||||
const player = new VersionedSchema({ name: "-16", health: 255 }, { name: "player" });
|
||||
player.addVersion({ name: "-16", health: 255, mana: 255 }, "added mana");
|
||||
const latest = player.latestSchema;
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { VersionedSchema } from "@suaveplan/bitpacker-schema";
|
||||
|
||||
const player = new VersionedSchema(
|
||||
{ name: "-16", health: 255 },
|
||||
{ name: "player", namespace: "game" }
|
||||
);
|
||||
player.addVersion({ name: "-16", health: 255, mana: 255 });
|
||||
player.addMigration(1, 2, (data) => ({ ...data, mana: 100 }));
|
||||
|
||||
// Pack v1 data, then transparently migrate up.
|
||||
const packed = player.pack({ name: "Hero", health: 200 }, 1);
|
||||
const v2Data = player.unpackAndMigrate(packed, 1, 2);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `class VersionedSchema<T extends BitPackerSchema = BitPackerSchema>`
|
||||
|
||||
- `constructor(schema: T, options: VersionedSchemaOptions)`
|
||||
- `addVersion(schema: BitPackerSchema, description?: string): number` — appends; returns new version number.
|
||||
- `addMigration<U extends BitPackerSchema>(from: number, to: number, fn: MigrationFunction): void`
|
||||
- `getSchema(version: number): BitPackerSchema` — throws if version not found.
|
||||
- `pack(data, version): Uint8Array` / `unpack(data, version): unknown` — pack/unpack at a specific version.
|
||||
- `get versions: readonly SchemaVersion[]`
|
||||
- `get latestSchema: BitPackerSchema`
|
||||
- `get latestVersion: number`
|
||||
|
||||
### `interface SchemaVersion`
|
||||
|
||||
`{ version: number; schema: BitPackerSchema; description?: string; createdAt?: Date }`
|
||||
|
||||
### `interface VersionedSchemaOptions`
|
||||
|
||||
`{ name: string; namespace?: string; description?: string; autoMigrate?: boolean; includeVersion?: boolean; bitPacker?: BitPacker }`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The internal `_bitPacker` defaults to a fresh `BitPacker()` instance; tests inject a stub to verify pack/unpack are routed through the injectable, not module-scope state.
|
||||
- `MigrationFunction` signatures are intentionally `any → any` because migration functions transform between heterogeneous data shapes; the `T → U` generic threading is encouraged but not enforced at runtime.
|
||||
- `addVersion` appends in monotonic order. There is no insertion or rewriting — historical versions are immutable so packed data on disk stays decodable.
|
||||
Reference in New Issue
Block a user