@tanstack/browser-db-sqlite-persistence 0.2.21 → 0.2.25

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 (40) hide show
  1. package/README.md +75 -1
  2. package/dist/assets/{opfs-worker-uyjx5Rus.js → opfs-worker-accoEoax.js} +17 -6
  3. package/dist/assets/{opfs-worker-uyjx5Rus.js.map → opfs-worker-accoEoax.js.map} +1 -1
  4. package/dist/cjs/browser-coordinator.cjs +5 -534
  5. package/dist/cjs/browser-coordinator.cjs.map +1 -1
  6. package/dist/cjs/browser-coordinator.d.cts +3 -65
  7. package/dist/cjs/browser-persistence.cjs +19 -8
  8. package/dist/cjs/browser-persistence.cjs.map +1 -1
  9. package/dist/cjs/index.cjs +16 -0
  10. package/dist/cjs/index.cjs.map +1 -1
  11. package/dist/cjs/index.d.cts +2 -2
  12. package/dist/cjs/opfs-database.cjs +58 -1
  13. package/dist/cjs/opfs-database.cjs.map +1 -1
  14. package/dist/cjs/opfs-database.d.cts +4 -0
  15. package/dist/cjs/opfs-worker.cjs +1 -1
  16. package/dist/cjs/wa-sqlite-driver.cjs +38 -14
  17. package/dist/cjs/wa-sqlite-driver.cjs.map +1 -1
  18. package/dist/cjs/wa-sqlite-driver.d.cts +3 -3
  19. package/dist/esm/browser-coordinator.d.ts +3 -65
  20. package/dist/esm/browser-coordinator.js +5 -534
  21. package/dist/esm/browser-coordinator.js.map +1 -1
  22. package/dist/esm/browser-persistence.js +19 -8
  23. package/dist/esm/browser-persistence.js.map +1 -1
  24. package/dist/esm/index.d.ts +2 -2
  25. package/dist/esm/index.js +5 -1
  26. package/dist/esm/opfs-database.d.ts +4 -0
  27. package/dist/esm/opfs-database.js +58 -1
  28. package/dist/esm/opfs-database.js.map +1 -1
  29. package/dist/esm/opfs-worker.js +1 -1
  30. package/dist/esm/wa-sqlite-driver.d.ts +3 -3
  31. package/dist/esm/wa-sqlite-driver.js +39 -15
  32. package/dist/esm/wa-sqlite-driver.js.map +1 -1
  33. package/package.json +9 -3
  34. package/src/browser-coordinator.ts +10 -834
  35. package/src/browser-persistence.ts +22 -14
  36. package/src/index.ts +9 -0
  37. package/src/opfs-database.ts +76 -1
  38. package/src/opfs-worker.ts +16 -5
  39. package/src/wa-sqlite-driver.ts +57 -15
  40. package/src/wa-sqlite-examples.d.ts +1 -0
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Browser SQLite persistence for TanStack DB using `wa-sqlite` + OPFS.
4
4
 
5
+ Start with the [SQLite Persistence guide](../../docs/guides/sqlite-persistence.md) for Collection setup and lifecycle behavior.
6
+
5
7
  Supports both single-tab (default) and multi-tab usage. Multi-tab coordination
6
8
  is opt-in by passing a `BrowserCollectionCoordinator`.
7
9
 
@@ -9,6 +11,7 @@ is opt-in by passing a `BrowserCollectionCoordinator`.
9
11
 
10
12
  - `createBrowserWASQLitePersistence(...)`
11
13
  - `openBrowserWASQLiteOPFSDatabase(...)`
14
+ - `BrowserCollectionCoordinator`
12
15
  - `persistedCollectionOptions(...)` (re-exported from core)
13
16
 
14
17
  ## Quick start (single-tab)
@@ -97,13 +100,84 @@ export const todosCollection = createCollection(
97
100
  See [`examples/react/offline-transactions`](../../examples/react/offline-transactions/src/db/persisted-todos.ts)
98
101
  for a full multi-tab example.
99
102
 
103
+ ### Committed transaction ownership
104
+
105
+ The persisted sync wrapper sends every source transaction with durable effects
106
+ through the coordinator's required
107
+ `requestApplyCommittedTx(collectionId, tx)` method.
108
+ `BrowserCollectionCoordinator` routes the complete transaction to the current
109
+ leader for that collection. The leader applies it with the adapter registered
110
+ for the same collection id, including that collection's resolved mode and
111
+ `schemaVersion`.
112
+
113
+ The route preserves truncation, row changes, row metadata, collection metadata,
114
+ and stream position as one `PersistedTx`. It does not feature-detect a partial
115
+ route or fall back to row-only mutation RPC. A custom coordinator that omits
116
+ `requestApplyCommittedTx` is rejected while the collection is configured,
117
+ before its sync source can publish rows. An effect-free source commit neither
118
+ publishes nor consumes a coordinator sequence.
119
+
120
+ Single-tab mode uses the same complete transaction contract. Its
121
+ `SingleProcessCoordinator` skips election and channel traffic but still routes
122
+ the transaction to the resolved adapter for that collection.
123
+
124
+ If a mutating RPC loses its response, Browser coordination replays it only
125
+ while the requester still knows the same non-null leader id and term. An
126
+ unknown initial route or any leader/term change rejects with
127
+ `IndeterminateCommitError`; the application must reconcile the outcome. The
128
+ coordinator does not retry that mutation against an unknown or replacement
129
+ leader.
130
+
131
+ ### Remote subset requests
132
+
133
+ `BrowserCollectionCoordinator.requestEnsureRemoteSubset(...)` validates and
134
+ projects the request before it chooses the local leader or `BroadcastChannel`
135
+ route. Registered owners receive the exported
136
+ `TransportedLoadSubsetOptions` type. It contains the supported
137
+ structured-clone wire data and excludes live `signal` and `subscription`
138
+ fields. Unsupported nested values fail immediately with
139
+ `RemoteSubsetWireValueError` and the exact value path; no owner callback or
140
+ channel post occurs. See the core package's remote subset wire contract for the
141
+ complete supported domain.
142
+
143
+ Each accepted request is an explicit lease. Retries of the same request object
144
+ reuse its acquisition identity, while distinct equal request objects remain
145
+ independent. Release is routed to the elected collection owner and unloads the
146
+ exact acquired options once. Leadership loss unloads the retiring owner's live
147
+ leases, and requesters replay still-live acquisitions against the next leader.
148
+ Registering a second owner for one collection throws
149
+ `DuplicateRemoteSubsetOwnerError`; no adapter fallback replaces the owner.
150
+ Remote follower transport/admission failures reject and retain demand for its
151
+ normal retry without entering the follower's local owner lifecycle. Terminal
152
+ release identities expire after the existing RPC dedupe horizon while delayed
153
+ duplicates inside that horizon remain idempotent.
154
+
100
155
  ## Notes
101
156
 
102
157
  - `openBrowserWASQLiteOPFSDatabase(...)` starts a dedicated Web Worker and
103
158
  routes SQL operations through it. OPFS sync access handle APIs are used in
104
159
  that worker context.
160
+ - Opening has a 30-second deadline by default. `timeoutMs` changes it; `0`
161
+ explicitly disables the deadline. A timed-out open rejects with
162
+ `TimeoutError` and terminates its pending worker, so it cannot acquire the
163
+ database later. Pass an `AbortSignal` to cancel earlier; the signal applies
164
+ only while opening, not to the established connection.
165
+ - On `pagehide`, the connection terminates its worker synchronously and rejects
166
+ pending initialization, queries, and close operations with `AbortError`. This
167
+ also applies when the document enters the back/forward cache. Applications
168
+ restored through
169
+ `pageshow` with `event.persisted` must create fresh database connections and
170
+ persistence/collection instances (or reload the application).
171
+ - Flush application writes and await `database.close()` before navigating when
172
+ possible. The `pagehide` cleanup releases resources; it cannot await pending
173
+ writes or serve as a durability guarantee.
105
174
  - Single-tab mode does not require `BroadcastChannel` or Web Locks for
106
- correctness.
175
+ election, but committed transactions still go through the collection's
176
+ registered persistence owner.
107
177
  - Multi-tab mode requires `BroadcastChannel` and the Web Locks API; both are
108
178
  available in all modern browsers.
109
179
  - OPFS capability failures are surfaced as `PersistenceUnavailableError`.
180
+ - SQLite open failures include the underlying VFS error name and message when
181
+ wa-sqlite exposes them. Some failures, including native access-handle
182
+ contention, are not currently exposed by wa-sqlite and retain SQLite's
183
+ generic open error.
@@ -5755,11 +5755,22 @@
5755
5755
  sqlite3.vfs_register(opfsVfs, true);
5756
5756
  const openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
5757
5757
  const databaseFileUri = `file:${request.databaseName}?vfs=${encodeURIComponent(request.vfsName)}`;
5758
- const dbHandle = await sqlite3.open_v2(
5759
- databaseFileUri,
5760
- openFlags,
5761
- request.vfsName
5762
- );
5758
+ let dbHandle;
5759
+ try {
5760
+ dbHandle = await sqlite3.open_v2(
5761
+ databaseFileUri,
5762
+ openFlags,
5763
+ request.vfsName
5764
+ );
5765
+ } catch (error) {
5766
+ const cause = opfsVfs.lastError;
5767
+ if (error instanceof Error && cause instanceof Error) {
5768
+ throw new Error(`${error.message}: ${cause.name}: ${cause.message}`, {
5769
+ cause
5770
+ });
5771
+ }
5772
+ throw error;
5773
+ }
5763
5774
  sqlite3Instance = sqlite3;
5764
5775
  sqliteDatabaseHandle = dbHandle;
5765
5776
  opfsVfsInstance = opfsVfs;
@@ -5876,4 +5887,4 @@
5876
5887
  });
5877
5888
  });
5878
5889
  })();
5879
- //# sourceMappingURL=opfs-worker-uyjx5Rus.js.map
5890
+ //# sourceMappingURL=opfs-worker-accoEoax.js.map