first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
# Schema Migration
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`migration.ts` ports the bit-packer schema migration toolkit from
upstream. A migration describes how to transform data shaped by an old
`BitPackerSchema` into data shaped by a newer one — adding fields,
removing fields, renaming, changing types, splitting, merging, or
running a fully custom transform. The toolkit is designed to be
composable: a single migration step is a `MigrationFunction`, a strategy
is one of `MigrationStrategy`, and a chain of strategies forms a path
between two schema versions tracked by `bitpacker-schema/versioning/`.
This module is the data-shape side of schema evolution. The companion
`versioning.ts` module owns version registration, lookup, and
chain-execution; this file owns the per-step transform vocabulary,
operation descriptors, and the helper builders that turn a strategy
into a runnable function.
## Features
- `MigrationStrategy` enum covering the eight common transforms
(`ADD_FIELD`, `REMOVE_FIELD`, `RENAME_FIELD`, `CHANGE_FIELD_TYPE`,
`MOVE_FIELD`, `SPLIT_FIELD`, `MERGE_FIELDS`, `CUSTOM`).
- `MigrationOperation` descriptor — a serialisable record of one step.
- `MigrationFunction<T, U>` — a pure data transform, no side effects.
- `SchemaTypeToDataType<T>` helper — propagates inferred runtime types.
- Pure functions; no state, no I/O.
## Usage: Basic Example
```ts
import {
MigrationStrategy,
type MigrationFunction,
} from "@suaveplan/bitpacker-schema";
// A v1 record is a plain `{ id }`; v2 adds `createdAt`.
const addCreatedAt: MigrationFunction = (data) => ({
...(data as Record<string, unknown>),
createdAt: new Date().toISOString(),
});
```
## Usage: Advanced Example
Compose multiple migrations through the versioning store. The
`migration.ts` module supplies the building blocks; `versioning.ts`
chains them.
```ts
import {
MigrationStrategy,
type MigrationFunction,
type MigrationOperation,
} from "@suaveplan/bitpacker-schema";
const renameUserId: MigrationFunction = (raw) => {
const r = raw as Record<string, unknown>;
const { user_id, ...rest } = r;
return { ...rest, userId: user_id };
};
const renameOp: MigrationOperation = {
strategy: MigrationStrategy.RENAME_FIELD,
fromField: "user_id",
toField: "userId",
};
// Combined with versioning's `addMigration(fromVersion, toVersion, fn)`,
// the v2 -> v3 hop becomes a deterministic, replayable transform.
```
## API Reference
- `enum MigrationStrategy` — eight strategy tags.
- `interface MigrationOperation` — `strategy`, plus optional
`fromField` / `toField` / `fromType` / `toType` / `metadata`.
- `type MigrationFunction<T, U>` — `(data: T) => U`.
- `type SchemaTypeToDataType<T>` — placeholder for runtime data type
inference; ported as `unknown` (upstream uses ad-hoc inference).
## Implementation Notes
- This file deliberately avoids any reference to actual
`BitPackerSchema` evaluation; it is shape-only metadata. Execution
lives in `versioning.ts` where chains are walked.
- Strategies map 1:1 with the upstream enum so that migrations
authored against the old API port without modification.
- The `CUSTOM` strategy is the escape hatch for transforms that don't
fit the other seven; the consumer supplies an arbitrary
`MigrationFunction` and a description.