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,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.