first commit
This commit is contained in:
69
docs/foundation/data/pwa/src/sync-queue/version-migration.md
Normal file
69
docs/foundation/data/pwa/src/sync-queue/version-migration.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# `sync-queue/version-migration.ts`
|
||||
|
||||
## Purpose
|
||||
|
||||
Forward-migrates raw `SyncQueueEntry` records loaded from persistent storage
|
||||
(IndexedDB / localStorage) to the current schema version. Entries created by
|
||||
older versions of `@suaveplan/pwa` linger in browser storage indefinitely, so
|
||||
the queue must upgrade them on every load before they cross the
|
||||
`SyncQueueEntrySchema` validator. The migration registry is deterministic and
|
||||
idempotent: an entry already at the current version passes through unchanged.
|
||||
|
||||
## Features
|
||||
|
||||
- `DEFAULT_MIGRATORS` — ordered list of `VersionMigrator` records shipped with
|
||||
the package, currently covering `v1 → v2` (the leap that added an explicit
|
||||
`schemaVersion` field).
|
||||
- `migrateEntry(raw, migrators?)` — single-entry upgrade.
|
||||
- `migrateBatch(raws, migrators?)` — convenience for bulk loads.
|
||||
- `asSyncQueueEntry(record)` — type narrowing for callers that have just
|
||||
validated a record against `SyncQueueEntrySchema`.
|
||||
- Throws when no migrator is registered for a `fromVersion`, so corrupt
|
||||
versions surface as errors rather than silently propagating.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { migrateEntry } from "@suaveplan/pwa";
|
||||
|
||||
const upgraded = migrateEntry({
|
||||
id: "old",
|
||||
url: "/api/x",
|
||||
method: "POST",
|
||||
createdAt: 0,
|
||||
});
|
||||
// upgraded.schemaVersion === 2
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Supply an extra migrator for a custom future schema bump:
|
||||
|
||||
```ts
|
||||
import { DEFAULT_MIGRATORS, migrateBatch, type VersionMigrator } from "@suaveplan/pwa";
|
||||
|
||||
const v2ToV3: VersionMigrator = {
|
||||
fromVersion: 2,
|
||||
upgrade: (e) => ({ ...e, schemaVersion: 3, tenant: e.tenant ?? "default" }),
|
||||
};
|
||||
const upgraded = migrateBatch(rawRows, [...DEFAULT_MIGRATORS, v2ToV3]);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `VersionMigrator` — `{ fromVersion, upgrade(entry) }`.
|
||||
- `DEFAULT_MIGRATORS` — frozen array shipped with the package.
|
||||
- `migrateEntry(raw, migrators?): Record<string, unknown>`.
|
||||
- `migrateBatch(raws, migrators?): Record<string, unknown>[]`.
|
||||
- `asSyncQueueEntry(record): SyncQueueEntry` — narrowing cast helper.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The function operates on `Record<string, unknown>` rather than `SyncQueueEntry`
|
||||
because pre-current-version records do not satisfy the current type. The caller
|
||||
is expected to feed the output through `SyncQueueEntrySchema.parse(...)` before
|
||||
trusting field types. The loop terminates because every migrator must increment
|
||||
`schemaVersion` by at least one (enforced via the throw on missing migrator
|
||||
when a record's version is `>= SYNC_QUEUE_SCHEMA_VERSION` we don't enter the
|
||||
loop at all). Idempotency derives from the same property: a record already at
|
||||
the current version skips the loop body entirely.
|
||||
Reference in New Issue
Block a user