@workglow/indexeddb 0.2.31 → 0.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +34 -0
  2. package/dist/job-queue/IndexedDbQueueStorage.d.ts +16 -11
  3. package/dist/job-queue/IndexedDbQueueStorage.d.ts.map +1 -1
  4. package/dist/job-queue/IndexedDbRateLimiterStorage.d.ts +15 -4
  5. package/dist/job-queue/IndexedDbRateLimiterStorage.d.ts.map +1 -1
  6. package/dist/job-queue/browser.js +399 -351
  7. package/dist/job-queue/browser.js.map +9 -6
  8. package/dist/job-queue/common.d.ts +3 -0
  9. package/dist/job-queue/common.d.ts.map +1 -1
  10. package/dist/job-queue/node.js +399 -351
  11. package/dist/job-queue/node.js.map +9 -6
  12. package/dist/migrations/IndexedDbMigrationRunner.d.ts +93 -0
  13. package/dist/migrations/IndexedDbMigrationRunner.d.ts.map +1 -0
  14. package/dist/migrations/indexedDbQueueMigrations.d.ts +24 -0
  15. package/dist/migrations/indexedDbQueueMigrations.d.ts.map +1 -0
  16. package/dist/migrations/indexedDbRateLimiterMigrations.d.ts +37 -0
  17. package/dist/migrations/indexedDbRateLimiterMigrations.d.ts.map +1 -0
  18. package/dist/storage/IndexedDbTable.d.ts.map +1 -1
  19. package/dist/storage/IndexedDbTabularMigrationApplier.d.ts +84 -0
  20. package/dist/storage/IndexedDbTabularMigrationApplier.d.ts.map +1 -0
  21. package/dist/storage/IndexedDbTabularStorage.d.ts +21 -2
  22. package/dist/storage/IndexedDbTabularStorage.d.ts.map +1 -1
  23. package/dist/storage/browser.js +472 -30
  24. package/dist/storage/browser.js.map +8 -5
  25. package/dist/storage/common.d.ts +3 -0
  26. package/dist/storage/common.d.ts.map +1 -1
  27. package/dist/storage/node.js +472 -30
  28. package/dist/storage/node.js.map +8 -5
  29. package/dist/storage/openIdb.d.ts +19 -0
  30. package/dist/storage/openIdb.d.ts.map +1 -0
  31. package/package.json +7 -7
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type IMigration, type IMigrationRunner, type RunMigrationsOptions } from "@workglow/storage";
7
+ /**
8
+ * Context handed to an IndexedDB migration's `up()` body. IDB's spec only
9
+ * permits schema changes (createObjectStore, createIndex, etc.) inside an
10
+ * `onupgradeneeded` callback, so migrations receive both the {@link IDBDatabase}
11
+ * and the version-change {@link IDBTransaction} active during that callback.
12
+ *
13
+ * `up()` MUST be synchronous — IDB upgrade transactions auto-commit as soon as
14
+ * the callback returns control to the event loop, so any awaited Promise
15
+ * between IDB requests would silently lose the rest of the migration.
16
+ */
17
+ export interface IndexedDbUpgradeContext {
18
+ readonly db: IDBDatabase;
19
+ readonly tx: IDBTransaction;
20
+ readonly oldVersion: number;
21
+ readonly newVersion: number;
22
+ }
23
+ /** Convenience alias for IndexedDB-flavoured migrations. */
24
+ export type IndexedDbMigration = IMigration<IndexedDbUpgradeContext>;
25
+ /**
26
+ * Thrown when an in-flight migration is interrupted by another tab opening
27
+ * the same database at a higher version. Surfaces as the `run()` rejection
28
+ * so callers can distinguish a tab-coordination failure from a programming
29
+ * error in `up()`.
30
+ */
31
+ export declare class MigrationAbortedByOtherTabError extends Error {
32
+ constructor(dbName: string);
33
+ }
34
+ /**
35
+ * Runs versioned migrations against a single IndexedDB database.
36
+ *
37
+ * Bookkeeping-driven dispatch (NOT IDB-version-ordinal driven). The runner:
38
+ * 1. Probes the DB to read the `_storage_migrations` object store, building
39
+ * a set of already-applied `(component, version)` pairs. The probe
40
+ * registers an `onupgradeneeded` handler so that if the DB doesn't yet
41
+ * exist, IDB's auto-creation path also creates the bookkeeping store
42
+ * atomically (rather than leaving an empty v1 DB with no schema).
43
+ * 2. Computes the pending migrations as `sorted \ alreadyApplied` —
44
+ * identifying each migration by `(component, version)`, NOT by its
45
+ * position in the sorted array. This means inserting a new migration
46
+ * that sorts BEFORE existing ones (e.g. a new component name that's
47
+ * lexicographically earlier) is still correctly detected as pending.
48
+ * 3. If pending is empty, returns without bumping the IDB version.
49
+ * 4. Otherwise reopens at `currentVersion + 1` and runs every pending
50
+ * migration inside the upgrade transaction, recording each in the
51
+ * bookkeeping store as it goes.
52
+ *
53
+ * Concurrent `run()` calls against the same dbName (across instances) are
54
+ * serialized via {@link RUN_LOCKS} so that two callers don't deadlock each
55
+ * other on the open-at-higher-version handshake.
56
+ *
57
+ * The IDB database version is treated purely as a monotonic trigger for
58
+ * `onupgradeneeded`; we never use it to decide which migrations to apply.
59
+ *
60
+ * Caveats:
61
+ * - `up()` must be synchronous. IDB upgrade transactions auto-commit as
62
+ * soon as control returns to the event loop, so awaited Promises between
63
+ * IDB requests would silently lose the rest of the migration. The runner
64
+ * throws if `up()` returns a Promise.
65
+ */
66
+ export declare class IndexedDbMigrationRunner implements IMigrationRunner<IndexedDbUpgradeContext> {
67
+ private readonly dbName;
68
+ private readonly idb;
69
+ constructor(dbName: string, idb?: IDBFactory);
70
+ private probe;
71
+ /** Ensures the bookkeeping object store exists (created lazily by {@link probe}). */
72
+ ensureBookkeepingTable(): Promise<void>;
73
+ appliedVersions(component: string): Promise<Set<number>>;
74
+ run(migrations: ReadonlyArray<IndexedDbMigration>, options?: RunMigrationsOptions): Promise<ReadonlyArray<IndexedDbMigration>>;
75
+ private runLocked;
76
+ }
77
+ /**
78
+ * Convenience helper used by storage classes — runs the supplied migration
79
+ * groups (one per IDB database) against fresh runners and returns an array
80
+ * of the applied migrations across all groups.
81
+ *
82
+ * IndexedDB groups exist because some storages (e.g. the rate limiter) span
83
+ * multiple databases and expose them as separate `(dbName, migrations)` pairs
84
+ * via `getMigrations()`.
85
+ */
86
+ export interface IndexedDbMigrationGroup {
87
+ readonly dbName: string;
88
+ readonly migrations: ReadonlyArray<IndexedDbMigration>;
89
+ }
90
+ export declare function runIndexedDbMigrationGroups(groups: ReadonlyArray<IndexedDbMigrationGroup>, options?: RunMigrationsOptions & {
91
+ idb?: IDBFactory;
92
+ }): Promise<ReadonlyArray<IndexedDbMigration>>;
93
+ //# sourceMappingURL=IndexedDbMigrationRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndexedDbMigrationRunner.d.ts","sourceRoot":"","sources":["../../src/migrations/IndexedDbMigrationRunner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;GASG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,4DAA4D;AAC5D,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,uBAAuB,CAAC,CAAC;AAerE;;;;;GAKG;AACH,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,YAAY,MAAM,EAAE,MAAM,EAGzB;CACF;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,wBAAyB,YAAW,gBAAgB,CAAC,uBAAuB,CAAC;IAEtF,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFtB,YACmB,MAAM,EAAE,MAAM,EACd,GAAG,GAAE,UAA2B,EAC/C;YAQU,KAAK;IAiFnB,qFAAqF;IAC/E,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE5C;IAEK,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAW7D;IAEK,GAAG,CACP,UAAU,EAAE,aAAa,CAAC,kBAAkB,CAAC,EAC7C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAS5C;YAQa,SAAS;CAgKxB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CACxD;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,aAAa,CAAC,uBAAuB,CAAC,EAC9C,OAAO,GAAE,oBAAoB,GAAG;IAAE,GAAG,CAAC,EAAE,UAAU,CAAA;CAAO,GACxD,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAW5C"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { PrefixColumn } from "@workglow/job-queue";
7
+ import type { IndexedDbMigration, IndexedDbMigrationGroup } from "./IndexedDbMigrationRunner";
8
+ /**
9
+ * Initial migration set for the IndexedDB queue object store identified by
10
+ * `tableName`.
11
+ *
12
+ * Component name is `queue:indexeddb:<tableName>` so two queues with
13
+ * different table names get tracked independently in `_storage_migrations`.
14
+ *
15
+ * Schema: a single object store keyed by `id` plus four compound indexes
16
+ * (queue/status, queue/status/run_after, queue/job_run_id,
17
+ * queue/fingerprint/status). When `prefixes` is non-empty the prefix columns
18
+ * are prepended to every index key path so per-tenant queries can be served
19
+ * directly by the index.
20
+ */
21
+ export declare function indexedDbQueueMigrations(tableName: string, prefixes: readonly PrefixColumn[]): IndexedDbMigration[];
22
+ /** Returns the queue migrations packaged with their target IDB database name. */
23
+ export declare function indexedDbQueueMigrationGroup(tableName: string, prefixes: readonly PrefixColumn[]): IndexedDbMigrationGroup;
24
+ //# sourceMappingURL=indexedDbQueueMigrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexedDbQueueMigrations.d.ts","sourceRoot":"","sources":["../../src/migrations/indexedDbQueueMigrations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAE9F;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,YAAY,EAAE,GAChC,kBAAkB,EAAE,CAyBtB;AAED,iFAAiF;AACjF,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,YAAY,EAAE,GAChC,uBAAuB,CAKzB"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { PrefixColumn } from "@workglow/job-queue";
7
+ import type { IndexedDbMigration, IndexedDbMigrationGroup } from "./IndexedDbMigrationRunner";
8
+ /**
9
+ * Initial migrations for the IndexedDB rate-limiter execution table.
10
+ *
11
+ * Schema: an object store keyed by `id` (autoincrement-style; we generate
12
+ * UUIDs at the storage layer) plus a compound index `queue_executed_at` for
13
+ * windowed counts. Prefix columns are prepended to every index key path.
14
+ */
15
+ export declare function indexedDbRateLimiterExecutionMigrations(executionTableName: string, prefixes: readonly PrefixColumn[]): IndexedDbMigration[];
16
+ /**
17
+ * Initial migrations for the IndexedDB rate-limiter `next_available` table.
18
+ *
19
+ * Schema: object store keyed by a single synthetic field whose name is
20
+ * `prefixCols.concat(["queue_name"]).join("_")`. The storage layer writes
21
+ * a record where this field holds `prefixValues.concat([queueName]).join("_")`
22
+ * — i.e. tenant-qualified — so the same physical store can hold rows for
23
+ * multiple tenants without collisions. Without this, two tenants with the
24
+ * same queue name would silently overwrite each other's row (the
25
+ * `next_available_at` of one would be returned for the other).
26
+ *
27
+ * No `queue_name = "myqueue"` index is created because the storage's read
28
+ * path (`store.get(syntheticKey)`) goes through the primary key directly.
29
+ */
30
+ export declare function indexedDbRateLimiterNextAvailableMigrations(nextAvailableTableName: string, prefixes: readonly PrefixColumn[]): IndexedDbMigration[];
31
+ /**
32
+ * Returns the rate-limiter migrations packaged as IDB migration groups —
33
+ * one group per database, since `IndexedDbRateLimiterStorage` keeps the
34
+ * execution and next-available tables in separate databases.
35
+ */
36
+ export declare function indexedDbRateLimiterMigrationGroups(executionTableName: string, nextAvailableTableName: string, prefixes: readonly PrefixColumn[]): IndexedDbMigrationGroup[];
37
+ //# sourceMappingURL=indexedDbRateLimiterMigrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexedDbRateLimiterMigrations.d.ts","sourceRoot":"","sources":["../../src/migrations/indexedDbRateLimiterMigrations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAE9F;;;;;;GAMG;AACH,wBAAgB,uCAAuC,CACrD,kBAAkB,EAAE,MAAM,EAC1B,QAAQ,EAAE,SAAS,YAAY,EAAE,GAChC,kBAAkB,EAAE,CAoBtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2CAA2C,CACzD,sBAAsB,EAAE,MAAM,EAC9B,QAAQ,EAAE,SAAS,YAAY,EAAE,GAChC,kBAAkB,EAAE,CAoBtB;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,CACjD,kBAAkB,EAAE,MAAM,EAC1B,sBAAsB,EAAE,MAAM,EAC9B,QAAQ,EAAE,SAAS,YAAY,EAAE,GAChC,uBAAuB,EAAE,CAW3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"IndexedDbTable.d.ts","sourceRoot":"","sources":["../../src/storage/IndexedDbTable.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,WAAW,CAAC;IAChB,WAAW,EAAE,cAAc,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oFAAoF;IACpF,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,8CAA8C;IAC9C,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnE,yDAAyD;IACzD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/D;AAsZD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,EAC7B,eAAe,GAAE,uBAAuB,EAAO,EAC/C,OAAO,GAAE,gBAAqB,EAC9B,aAAa,GAAE,OAAe,GAC7B,OAAO,CAAC,WAAW,CAAC,CA6KtB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzE"}
1
+ {"version":3,"file":"IndexedDbTable.d.ts","sourceRoot":"","sources":["../../src/storage/IndexedDbTable.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,WAAW,CAAC;IAChB,WAAW,EAAE,cAAc,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oFAAoF;IACpF,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,8CAA8C;IAC9C,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnE,yDAAyD;IACzD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/D;AA6WD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,EAC7B,eAAe,GAAE,uBAAuB,EAAO,EAC/C,OAAO,GAAE,gBAAqB,EAC9B,aAAa,GAAE,OAAe,GAC7B,OAAO,CAAC,WAAW,CAAC,CA6KtB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzE"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type ITabularMigrationApplier, type TabularMigrationOp } from "@workglow/storage";
7
+ import { IndexedDbMigrationRunner } from "../migrations/IndexedDbMigrationRunner";
8
+ interface BackfillCapableStorage {
9
+ getPage: (req?: {
10
+ limit?: number;
11
+ cursor?: unknown;
12
+ }) => Promise<{
13
+ items: Array<Record<string, unknown>>;
14
+ nextCursor?: unknown;
15
+ }>;
16
+ put: (row: Record<string, unknown>) => Promise<unknown>;
17
+ delete: (row: Record<string, unknown>) => Promise<unknown>;
18
+ }
19
+ /**
20
+ * Read-only existence probe shared by `IndexedDbTabularMigrationApplier.tableExists`
21
+ * and `IndexedDbTabularStorage.probeObjectStoreExists`. Opens the IDB
22
+ * database without a version (which is the only documented way to read the
23
+ * existing version + object stores) and inspects `objectStoreNames`.
24
+ *
25
+ * **Side effect:** if the database does not yet exist, IDB's spec says
26
+ * `open(name)` *creates* it at version 1 with no object stores. The caller
27
+ * must be prepared to handle that — `ensureIndexedDbTable` already does, by
28
+ * deleting and recreating the empty DB before bumping its version.
29
+ */
30
+ export declare function idbObjectStoreExists(dbName: string, storeName: string): Promise<boolean>;
31
+ /**
32
+ * IndexedDB applier for tabular migrations.
33
+ *
34
+ * Op handling matches `InMemoryTabularMigrationApplier`'s schemaless model
35
+ * (column ops are no-ops) and `SqlTabularMigrationApplier`'s SQL-backed
36
+ * model (DDL is real) where each makes sense:
37
+ *
38
+ * - `addColumn` / `dropColumn` / `renameColumn` — **no-ops.** IDB stores
39
+ * arbitrary JS objects, so there is no schema to evolve. Authors who
40
+ * need to populate or rewrite a property on existing rows must pair
41
+ * the column op with an explicit `backfill` op (which runs on every
42
+ * backend, including SQL, where the backfill is in addition to the
43
+ * real ALTER TABLE). This keeps a single migration spec portable
44
+ * across backends.
45
+ * - `addIndex` / `dropIndex` — **real DDL.** Run inside an upgrade
46
+ * transaction issued by {@link IndexedDbMigrationRunner}, which writes
47
+ * the `_storage_migrations` row in the same transaction so DDL +
48
+ * bookkeeping commit atomically. `createIndex` / `deleteIndex` are
49
+ * guarded by `objectStore.indexNames.contains` so a re-run does not
50
+ * throw on already-existing / already-deleted indexes — mirroring
51
+ * SQL's `IF NOT EXISTS` / `IF EXISTS` semantics.
52
+ * - `backfill` — runs on a **separate** readwrite transaction *before*
53
+ * the upgrade tx, because IDB upgrade transactions cannot span async
54
+ * work. This means the backfill and the bookkeeping write are NOT
55
+ * atomic on this backend: if the upgrade tx fails after a partial
56
+ * backfill, the row mutations persist while no `(component, version)`
57
+ * row is written, and the next run re-invokes `transform()` on the
58
+ * already-mutated rows. **Backfill `transform`s on this applier MUST
59
+ * therefore be idempotent.** SQL backends wrap everything in
60
+ * `withTransaction` and do not have this requirement.
61
+ *
62
+ * Order of execution within a single migration: backfill first, then DDL.
63
+ * This means a `[backfill, addIndex]` pair sees the new index applied to
64
+ * the rewritten rows; the reverse order (`[addIndex, backfill]`) would
65
+ * still execute backfill first because the runner buffers DDL until the
66
+ * upgrade tx.
67
+ */
68
+ export declare class IndexedDbTabularMigrationApplier implements ITabularMigrationApplier {
69
+ private readonly dbName;
70
+ private readonly storeName;
71
+ private readonly storage;
72
+ private readonly runner;
73
+ constructor(dbName: string, storeName: string, storage: BackfillCapableStorage, runner?: IndexedDbMigrationRunner);
74
+ ensureBookkeeping(): Promise<void>;
75
+ appliedVersions(component: string): Promise<Set<number>>;
76
+ tableExists(): Promise<boolean>;
77
+ markAllApplied(component: string, versions: ReadonlyArray<{
78
+ version: number;
79
+ description: string | undefined;
80
+ }>): Promise<void>;
81
+ applyMigration(component: string, version: number, description: string | undefined, ops: ReadonlyArray<TabularMigrationOp>, onProgress?: (fraction: number) => void): Promise<void>;
82
+ }
83
+ export {};
84
+ //# sourceMappingURL=IndexedDbTabularMigrationApplier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndexedDbTabularMigrationApplier.d.ts","sourceRoot":"","sources":["../../src/storage/IndexedDbTabularMigrationApplier.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,wBAAwB,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EACL,wBAAwB,EAEzB,MAAM,wCAAwC,CAAC;AAEhD,UAAU,sBAAsB;IAC9B,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC;QAC/D,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QACtC,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC,CAAC;IACH,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAe9F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,qBAAa,gCAAiC,YAAW,wBAAwB;IAG7E,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAClD,YACmB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,sBAAsB,EAChD,MAAM,CAAC,EAAE,wBAAwB,EAGlC;IAEK,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAEvC;IAEK,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAE7D;IAEK,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAEpC;IAEK,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,GAC5E,OAAO,CAAC,IAAI,CAAC,CAUf;IAEK,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,GAAG,EAAE,aAAa,CAAC,kBAAkB,CAAC,EACtC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACtC,OAAO,CAAC,IAAI,CAAC,CA2Ff;CACF"}
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { DataPortSchemaObject, FromSchema, TypedArraySchemaOptions } from "@workglow/util/schema";
7
- import { BaseTabularStorage, ClientProvidedKeysOption, KeyGenerationStrategy, AnyTabularStorage, AutoGeneratedKeys, CoveringIndexQueryOptions, DeleteSearchCriteria, InsertEntity, QueryOptions, SearchCriteria, SimplifyPrimaryKey, TabularChangePayload, TabularSubscribeOptions } from "@workglow/storage";
7
+ import { BaseTabularStorage, ClientProvidedKeysOption, KeyGenerationStrategy, AnyTabularStorage, AutoGeneratedKeys, CoveringIndexQueryOptions, DeleteSearchCriteria, InsertEntity, QueryOptions, SearchCriteria, SimplifyPrimaryKey, TabularChangePayload, TabularSubscribeOptions, type ITabularMigration, type ITabularMigrationApplier } from "@workglow/storage";
8
8
  import { MigrationOptions } from "./IndexedDbTable";
9
9
  export declare const IDB_TABULAR_REPOSITORY: import("@workglow/util").ServiceToken<AnyTabularStorage>;
10
10
  /**
@@ -17,6 +17,15 @@ export declare class IndexedDbTabularStorage<Schema extends DataPortSchemaObject
17
17
  table: string;
18
18
  /** Promise that resolves to the IndexedDB database instance */
19
19
  private db;
20
+ /**
21
+ * True between `setupDatabase`'s call to `applyTabularMigrations` and its
22
+ * completion. Backfill ops inside the orchestrator may close `this.db`
23
+ * (via `onversionchange` from the next migration's upgrade) and trigger
24
+ * a re-entrant `setupDatabase` call from `getDb()`. The re-entrant call
25
+ * must only re-open the IDB connection — it MUST NOT recurse into the
26
+ * orchestrator, or migrations will be replayed mid-flight.
27
+ */
28
+ private applyingMigrations;
20
29
  /** Promise to track ongoing database setup to prevent concurrent setup calls */
21
30
  private setupPromise;
22
31
  /** Migration options for database schema changes */
@@ -46,14 +55,24 @@ export declare class IndexedDbTabularStorage<Schema extends DataPortSchemaObject
46
55
  constructor(table: string | undefined, schema: Schema, primaryKeyNames: PrimaryKeyNames, indexes?: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[], migrationOptions?: MigrationOptions & {
47
56
  readonly useBroadcastChannel?: boolean;
48
57
  readonly backupPollingIntervalMs?: number;
49
- }, clientProvidedKeys?: ClientProvidedKeysOption);
58
+ }, clientProvidedKeys?: ClientProvidedKeysOption, tabularMigrations?: ReadonlyArray<ITabularMigration>);
50
59
  private getDb;
51
60
  /**
52
61
  * Sets up the IndexedDB database table with the required schema and indexes.
53
62
  * Must be called before using any other methods.
54
63
  */
55
64
  setupDatabase(): Promise<void>;
65
+ /**
66
+ * Wires `onversionchange` so that when the migration runner bumps the IDB
67
+ * version (currentVersion + 1 to trigger onupgradeneeded), the current
68
+ * open connection is both closed AND cleared from `this.db`. Without the
69
+ * clear, getDb() would return a stale closed connection and throw
70
+ * InvalidStateError on the next transaction attempt (e.g. during backfill).
71
+ */
72
+ private rewireOnVersionChange;
73
+ private probeObjectStoreExists;
56
74
  private performSetup;
75
+ getMigrationApplier(): ITabularMigrationApplier | null;
57
76
  /**
58
77
  * Generates a key value for UUID keys
59
78
  * Integer autoincrement keys are handled by IndexedDB's autoIncrement
@@ -1 +1 @@
1
- {"version":3,"file":"IndexedDbTabularStorage.d.ts","sourceRoot":"","sources":["../../src/storage/IndexedDbTabularStorage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAClG,OAAO,EAEL,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,oBAAoB,EACpB,YAAY,EAEZ,YAAY,EACZ,cAAc,EAEd,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EAExB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAiD,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEnG,eAAO,MAAM,sBAAsB,0DAElC,CAAC;AA0BF;;;;;GAKG;AACH,qBAAa,uBAAuB,CAClC,MAAM,SAAS,oBAAoB,EACnC,eAAe,SAAS,aAAa,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,EAEjE,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,uBAAuB,CAAC,EACpD,UAAU,GAAG,kBAAkB,CAAC,MAAM,EAAE,eAAe,CAAC,EACxD,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAC5D,UAAU,SAAS,YAAY,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,YAAY,CAC/E,MAAM,EACN,iBAAiB,CAAC,MAAM,CAAC,CAC1B,CACD,SAAQ,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC;IAsCjF,KAAK,EAAE,MAAM;IArCtB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAA0B;IACpC,gFAAgF;IAChF,OAAO,CAAC,YAAY,CAAqC;IACzD,oDAAoD;IACpD,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,yCAAyC;IACzC,OAAO,CAAC,aAAa,CAIL;IAChB,kCAAkC;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAG5B;IACF;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB,CAAyC;IAElE;;;;;;;;;OASG;IACH,YACS,KAAK,EAAE,MAAM,YAAkB,EACtC,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,EAChC,OAAO,GAAE,SAAS,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAO,EACrF,gBAAgB,GAAE,gBAAgB,GAAG;QACnC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;QACvC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;KACtC,EACN,kBAAkB,GAAE,wBAAuC,EAQ5D;YAMa,KAAK;IAMnB;;;OAGG;IACmB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAanD;YAKa,YAAY;IA4C1B;;;;;;OAMG;IACH,UAAmB,gBAAgB,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,GAAG,MAAM,CAQjB;IAED;;;;;OAKG;IACG,GAAG,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CA6E7C;IAED;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGtD;IAED,UAAmB,2BAA2B,CAAC,GAAG,EAAE,UAAU,sEAI7D;IAED,OAAO,CAAC,aAAa;IAOrB;;;;;OAKG;IACG,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAiBtD;IAED;;;;OAIG;IACG,MAAM,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CAyC1E;IAED;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB3C;IAED;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAgB/B;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAS5B;IAED;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,kBAAkB;IA+D1B;;;;;;;OAOG;IACY,KAAK,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAqCvE;IAED;;;;;OAKG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CAwC1E;IAED;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IA2CvB;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,oBAAoB,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAkExE;IAED,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,kBAAkB;IAmG1B;;;;;;OAMG;IACG,KAAK,CACT,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,EAChC,OAAO,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CAsD/B;IAED;;;;;;;OAOG;IACY,UAAU,CAAC,CAAC,SAAS,MAAM,MAAM,GAAG,MAAM,EACvD,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,EAChC,OAAO,EAAE,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,GAC5C,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAsI5B;IAED;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA0CxB;;;;;;;OAOG;IACa,kBAAkB,CAChC,QAAQ,EAAE,CAAC,MAAM,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAAK,IAAI,EACxD,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,IAAI,CAMZ;IAED;;OAEG;IACa,OAAO,IAAI,IAAI,CAM9B;CACF"}
1
+ {"version":3,"file":"IndexedDbTabularStorage.d.ts","sourceRoot":"","sources":["../../src/storage/IndexedDbTabularStorage.ts"],"names":[],"mappings":"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"}