@tanstack/db-sqlite-persistence-core 0.2.21 → 0.4.0
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.
- package/README.md +258 -7
- package/dist/cjs/broadcast-coordinator.cjs +1689 -0
- package/dist/cjs/broadcast-coordinator.cjs.map +1 -0
- package/dist/cjs/broadcast-coordinator.d.cts +116 -0
- package/dist/cjs/errors.cjs +73 -0
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/errors.d.cts +44 -0
- package/dist/cjs/index.cjs +19 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +2 -0
- package/dist/cjs/persisted.cjs +1840 -399
- package/dist/cjs/persisted.cjs.map +1 -1
- package/dist/cjs/persisted.d.cts +177 -11
- package/dist/cjs/remote-subset-owner.cjs +20 -0
- package/dist/cjs/remote-subset-owner.cjs.map +1 -0
- package/dist/cjs/remote-subset-owner.d.cts +7 -0
- package/dist/cjs/remote-subset-wire.cjs +681 -0
- package/dist/cjs/remote-subset-wire.cjs.map +1 -0
- package/dist/cjs/remote-subset-wire.d.cts +59 -0
- package/dist/cjs/sqlite-core-adapter.cjs +969 -364
- package/dist/cjs/sqlite-core-adapter.cjs.map +1 -1
- package/dist/cjs/sqlite-core-adapter.d.cts +45 -1
- package/dist/cjs/sqlite-value.cjs +31 -0
- package/dist/cjs/sqlite-value.cjs.map +1 -0
- package/dist/cjs/sqlite-value.d.cts +10 -0
- package/dist/esm/broadcast-coordinator.d.ts +116 -0
- package/dist/esm/broadcast-coordinator.js +1689 -0
- package/dist/esm/broadcast-coordinator.js.map +1 -0
- package/dist/esm/errors.d.ts +44 -0
- package/dist/esm/errors.js +74 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +21 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/persisted.d.ts +177 -11
- package/dist/esm/persisted.js +1842 -401
- package/dist/esm/persisted.js.map +1 -1
- package/dist/esm/remote-subset-owner.d.ts +7 -0
- package/dist/esm/remote-subset-owner.js +20 -0
- package/dist/esm/remote-subset-owner.js.map +1 -0
- package/dist/esm/remote-subset-wire.d.ts +59 -0
- package/dist/esm/remote-subset-wire.js +681 -0
- package/dist/esm/remote-subset-wire.js.map +1 -0
- package/dist/esm/sqlite-core-adapter.d.ts +45 -1
- package/dist/esm/sqlite-core-adapter.js +955 -350
- package/dist/esm/sqlite-core-adapter.js.map +1 -1
- package/dist/esm/sqlite-value.d.ts +10 -0
- package/dist/esm/sqlite-value.js +31 -0
- package/dist/esm/sqlite-value.js.map +1 -0
- package/package.json +12 -2
- package/src/broadcast-coordinator.ts +2456 -0
- package/src/errors.ts +120 -0
- package/src/index.ts +2 -0
- package/src/persisted.ts +2690 -444
- package/src/remote-subset-owner.ts +36 -0
- package/src/remote-subset-wire.ts +946 -0
- package/src/sqlite-core-adapter.ts +1297 -410
- package/src/sqlite-value.ts +30 -0
package/README.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# @tanstack/db-sqlite-persistence-core
|
|
2
2
|
|
|
3
|
-
Shared SQLite persistence primitives for TanStack DB. Runtime
|
|
4
|
-
|
|
5
|
-
package.
|
|
3
|
+
Shared SQLite persistence primitives for TanStack DB. Runtime packages provide
|
|
4
|
+
the database drivers. Start with the [SQLite Persistence guide](../../docs/guides/sqlite-persistence.md) if you are adding persistence to an application.
|
|
6
5
|
|
|
7
6
|
## What this package provides
|
|
8
7
|
|
|
@@ -25,17 +24,40 @@ binding. Provide a runtime `SQLiteDriver` implementation from a wrapper package.
|
|
|
25
24
|
- `TxCommitted`
|
|
26
25
|
- `EnsureRemoteSubsetRequest`
|
|
27
26
|
- `EnsureRemoteSubsetResponse`
|
|
27
|
+
- `ReleaseRemoteSubsetRequest`
|
|
28
|
+
- `ReleaseRemoteSubsetResponse`
|
|
29
|
+
- `RemoteSubsetOwner`
|
|
30
|
+
- `DuplicateRemoteSubsetOwnerError`
|
|
31
|
+
- `TransportedLoadSubsetOptions`
|
|
32
|
+
- `RemoteSubsetWirePrimitive`
|
|
33
|
+
- `RemoteSubsetWireTypedArray`
|
|
34
|
+
- `RemoteSubsetWireRecord`
|
|
35
|
+
- `RemoteSubsetWireValue`
|
|
36
|
+
- `RemoteSubsetWireExpression`
|
|
37
|
+
- `RemoteSubsetWireCompareOptions`
|
|
38
|
+
- `RemoteSubsetWireOrderByClause`
|
|
39
|
+
- `RemoteSubsetWireCursor`
|
|
40
|
+
- `RemoteSubsetWireValueError`
|
|
41
|
+
- `toTransportedLoadSubsetOptions(...)`
|
|
28
42
|
- `ApplyLocalMutationsRequest`
|
|
29
43
|
- `ApplyLocalMutationsResponse`
|
|
44
|
+
- `ApplyCommittedTxRequest`
|
|
45
|
+
- `ApplyCommittedTxResponse`
|
|
30
46
|
- `PullSinceRequest`
|
|
31
47
|
- `PullSinceResponse`
|
|
32
48
|
- `CollectionReset`
|
|
33
49
|
- `PersistedIndexSpec`
|
|
50
|
+
- `PersistedRowMetadataMutation<TKey>`
|
|
51
|
+
- `PersistedCollectionMetadataMutation`
|
|
52
|
+
- `ReplayableTxDelta<T, TKey>`
|
|
53
|
+
- `PersistedScannedRow<T, TKey>`
|
|
54
|
+
- `PersistedRowScanOptions`
|
|
55
|
+
- `PersistedKeySetEvidence`
|
|
34
56
|
- `PersistedTx<T, TKey>`
|
|
35
|
-
- `PersistenceAdapter
|
|
57
|
+
- `PersistenceAdapter`
|
|
36
58
|
- `SQLiteDriver`
|
|
37
59
|
- `PersistedCollectionCoordinator`
|
|
38
|
-
- `PersistedCollectionPersistence
|
|
60
|
+
- `PersistedCollectionPersistence`
|
|
39
61
|
- `PersistedCollectionMode`
|
|
40
62
|
- `PersistedCollectionLeadershipState`
|
|
41
63
|
- `PersistedCollectionUtils`
|
|
@@ -64,12 +86,227 @@ and resolves persistence using:
|
|
|
64
86
|
This lets runtime wrappers expose one shared persistence instance per database
|
|
65
87
|
while still handling per-collection schema versions correctly.
|
|
66
88
|
|
|
89
|
+
### Network-first initial rendering
|
|
90
|
+
|
|
91
|
+
Set `initialRender` on every eager persisted source Collection in a query to
|
|
92
|
+
let React or Solid Suspense render restored SQLite rows when the network is
|
|
93
|
+
slow or unavailable:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
const todos = createCollection(
|
|
97
|
+
persistedCollectionOptions({
|
|
98
|
+
id: 'todos',
|
|
99
|
+
getKey: (todo) => todo.id,
|
|
100
|
+
persistence,
|
|
101
|
+
sync,
|
|
102
|
+
initialRender: {
|
|
103
|
+
strategy: 'network-first',
|
|
104
|
+
networkTimeoutMs: 3_000,
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
const result = useLiveQuery((q) => q.from({ todos }))
|
|
110
|
+
if (result.isPersistedReady) {
|
|
111
|
+
// The eager persisted restore completed, even if the network is pending.
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The live-query observer and framework hooks expose `persistedStatus`
|
|
116
|
+
(`unavailable`, `loading`, `ready`, or `error`), `isPersistedReady`, and
|
|
117
|
+
`persistedError`. `ready` means every source Collection in the query opted in
|
|
118
|
+
and completed its current eager persisted restore; an empty database also
|
|
119
|
+
counts as ready. One unconfigured source makes the query's persisted status
|
|
120
|
+
`unavailable`. A failed restore reports its original error through
|
|
121
|
+
`persistedError`. An SSR seed does not count as persisted restore.
|
|
122
|
+
|
|
123
|
+
The initial render prefers Collection readiness. If the network has not made
|
|
124
|
+
the query ready after `networkTimeoutMs`, Suspense may use a completed
|
|
125
|
+
persisted restore. A network failure allows that fallback sooner. If the
|
|
126
|
+
restore is still loading, the query waits for it or for the network. The
|
|
127
|
+
deadline never cancels network sync. The default deadline is 3 seconds;
|
|
128
|
+
`networkTimeoutMs: 0` allows fallback as soon as restore finishes. For a query
|
|
129
|
+
with multiple opted-in sources, the longest deadline applies. An unconfigured
|
|
130
|
+
source keeps the existing network-readiness gate. A query failure that did not
|
|
131
|
+
come from a source is still an error, not a network fallback. Ordinary
|
|
132
|
+
`useLiveQuery` row updates and Collection `status`, `isReady`, and `preload()` are unchanged;
|
|
133
|
+
`status` is a Collection lifecycle signal, not a pure network-health signal.
|
|
134
|
+
|
|
135
|
+
In React, a client query stream failure before the first render also allows a
|
|
136
|
+
completed persisted restore to release Suspense. React waits if the stream
|
|
137
|
+
fails before restore completes, including when it failed before the component
|
|
138
|
+
mounted. The derived query result can be empty. A derived-query failure still
|
|
139
|
+
reaches the Error Boundary.
|
|
140
|
+
|
|
141
|
+
Persisted readiness does not prove current authorization. A source error can
|
|
142
|
+
permit restored rows to render even when that error reports an authorization
|
|
143
|
+
failure. Applications with user- or tenant-specific data must isolate persisted
|
|
144
|
+
storage by identity and clear or replace it when the identity changes. If a
|
|
145
|
+
policy denial must hide cached rows, gate the view separately; `initialRender`
|
|
146
|
+
does not classify source errors.
|
|
147
|
+
|
|
148
|
+
`initialRender` is rejected with `syncMode: 'on-demand'`, since an on-demand
|
|
149
|
+
Collection has no complete startup snapshot to certify.
|
|
150
|
+
|
|
151
|
+
### Coordinator contract
|
|
152
|
+
|
|
153
|
+
Every `PersistedCollectionCoordinator` must implement
|
|
154
|
+
`requestApplyCommittedTx(collectionId, tx)`. A sync transaction with durable
|
|
155
|
+
effects is routed in full to the persistence adapter owned by that collection.
|
|
156
|
+
The `PersistedTx` includes any truncate, row mutations, row metadata mutations,
|
|
157
|
+
collection metadata mutations, and stream position. Multiprocess coordinators
|
|
158
|
+
must preserve the complete transaction when they forward it to the elected
|
|
159
|
+
writer. An effect-free source commit does not allocate a stream position,
|
|
160
|
+
publish an invalidation, or call persistence; the next durable transaction
|
|
161
|
+
retains the next coordinator-owned sequence.
|
|
162
|
+
|
|
163
|
+
This is a required invariant, not a capability to detect at commit time. The
|
|
164
|
+
TypeScript interface requires the method, and `persistedCollectionOptions(...)`
|
|
165
|
+
validates custom coordinators when it configures a collection. An untyped
|
|
166
|
+
integration that omits the method throws
|
|
167
|
+
`InvalidPersistedCollectionCoordinatorError` before the sync source starts or
|
|
168
|
+
publishes rows. Implementations must not fall back to a row-only route such as
|
|
169
|
+
`requestApplyLocalMutations(...)`, because that would discard transaction
|
|
170
|
+
semantics.
|
|
171
|
+
|
|
172
|
+
After a mutating RPC transport failure, replay is allowed only while the
|
|
173
|
+
requester can prove the same non-null leader id and term still own the route.
|
|
174
|
+
If either value was unknown for the first attempt, or either value changes,
|
|
175
|
+
the request rejects with `IndeterminateCommitError` and requires application
|
|
176
|
+
reconciliation. Coordinators never retry an indeterminate mutation against an
|
|
177
|
+
unknown or replacement leader.
|
|
178
|
+
|
|
179
|
+
`SingleProcessCoordinator` also implements the complete route. It is always
|
|
180
|
+
leader and has no cross-process transport, but it applies the transaction to
|
|
181
|
+
the resolved adapter registered for the specific collection. The Browser and
|
|
182
|
+
Electron coordinators provide the corresponding elected-owner route in their
|
|
183
|
+
runtime packages.
|
|
184
|
+
|
|
185
|
+
An adapter/storage rejection is surfaced as
|
|
186
|
+
`PersistedCollectionDurabilityError`, never as `CONFLICT`. The error preserves
|
|
187
|
+
the original local cause and its `code` and `path` fields. A transported
|
|
188
|
+
`PERSISTENCE_ERROR` response carries the source code/path that can cross the
|
|
189
|
+
coordinator boundary. Source writes remain published before their applied
|
|
190
|
+
receipt settles; if persistence then fails, the receipt rejects with the named
|
|
191
|
+
error and the collection enters its existing `error` lifecycle state. The
|
|
192
|
+
collection does not continue, retry, or fall back to a partial writer.
|
|
193
|
+
|
|
194
|
+
### Remote subset wire contract
|
|
195
|
+
|
|
196
|
+
`requestEnsureRemoteSubset(collectionId, options)` accepts the full live
|
|
197
|
+
`LoadSubsetOptions` input. Before choosing a local owner or remote transport,
|
|
198
|
+
every built-in coordinator projects it once to the exported
|
|
199
|
+
`TransportedLoadSubsetOptions` contract. A registered remote-subset owner
|
|
200
|
+
receives that transported type, never live-only fields such as `signal` or
|
|
201
|
+
`subscription`.
|
|
202
|
+
|
|
203
|
+
Expression values may contain structured-clone-safe primitives, plain records,
|
|
204
|
+
arrays (including sparse arrays), `Date`, zero-position `RegExp`, fixed
|
|
205
|
+
`ArrayBuffer`, fixed `DataView`, the views listed by the exported
|
|
206
|
+
`RemoteSubsetWireTypedArray` union (`Int8Array`, `Uint8Array`,
|
|
207
|
+
`Uint8ClampedArray`, `Int16Array`, `Uint16Array`, `Int32Array`, `Uint32Array`,
|
|
208
|
+
`Float32Array`, `Float64Array`, `BigInt64Array`, and `BigUint64Array`), `Map`,
|
|
209
|
+
and `Set`. Cycles and aliases are preserved. Other view types; shared,
|
|
210
|
+
resizable, growable, or detached buffers; accessors; non-enumerable or symbol
|
|
211
|
+
keys; native expandos; custom prototypes; promises; weak collections;
|
|
212
|
+
functions; and symbols are outside the contract. A rejected value throws the exported
|
|
213
|
+
`RemoteSubsetWireValueError` before owner work or transport, with its exact
|
|
214
|
+
path in the request. The wire contract does not provide codecs, coercion, or
|
|
215
|
+
lossy normalization for unsupported values.
|
|
216
|
+
|
|
217
|
+
Remote subset ownership is lease-based. A coordinator gives each accepted
|
|
218
|
+
request object a stable acquisition identity scoped to its collection and
|
|
219
|
+
requester. Retrying the same acquisition coalesces with the original; a second
|
|
220
|
+
request object with equal values is an independent lease. Releasing a lease
|
|
221
|
+
calls the registered owner's required `unloadSubset(...)` method with the exact
|
|
222
|
+
transported options object that was loaded. Releasing it again is a no-op.
|
|
223
|
+
`EnsureRemoteSubsetRequest.acquisitionId` is the wire identity established by
|
|
224
|
+
acquisition; `ReleaseRemoteSubsetRequest.acquisitionId` must carry that same
|
|
225
|
+
identity so the elected owner releases the matching lease.
|
|
226
|
+
|
|
227
|
+
The owner also provides a required `onError(error)` callback. A load or unload
|
|
228
|
+
throw by the actual elected owner, or a runtime thenable rejection from either
|
|
229
|
+
operation, is reported through that callback with the original value before
|
|
230
|
+
the awaited request rejects. A follower transport or remote-owner admission
|
|
231
|
+
failure rejects the acquisition and remains eligible for the existing demand
|
|
232
|
+
retry; it is not a failure of that follower's local owner lifecycle. Retirement
|
|
233
|
+
and disposal observe and report actual owner failures while continuing cleanup
|
|
234
|
+
of sibling leases; they do not retry or silently recover the failed lifecycle.
|
|
235
|
+
|
|
236
|
+
Only one remote subset owner may be registered per collection in a coordinator.
|
|
237
|
+
A second live registration throws `DuplicateRemoteSubsetOwnerError` instead of
|
|
238
|
+
replacing the first, and startup reports the named failure before readiness
|
|
239
|
+
rather than leaving a rejected registration promise unobserved. Released
|
|
240
|
+
acquisition identities remain as dedupe tombstones for the coordinator's
|
|
241
|
+
existing RPC dedupe horizon, then expire during later subset traffic. When a
|
|
242
|
+
leader loses ownership or is disposed, it unloads every transferred lease. A
|
|
243
|
+
requester that still owns a lease replays that same acquisition when the next
|
|
244
|
+
leader is observed. There is no adapter fallback or direct-writer escape hatch
|
|
245
|
+
for missing ownership.
|
|
246
|
+
|
|
247
|
+
The named-error and exact-path guarantee covers values the boundary can
|
|
248
|
+
identify with standard JavaScript reflection. A fully transparent `Proxy` is
|
|
249
|
+
outside the public wire type and cannot be portably distinguished from its
|
|
250
|
+
target. Untyped callers must not rely on Proxy identity, traps, or a
|
|
251
|
+
Proxy-specific diagnostic; no non-standard detection is attempted.
|
|
252
|
+
|
|
253
|
+
### Source replay ordering
|
|
254
|
+
|
|
255
|
+
The persisted wrapper buffers authoritative source sync transactions and
|
|
256
|
+
replays them into the Collection in FIFO order, one transaction at a time.
|
|
257
|
+
Local optimistic mutations remain visible immediately; this queue governs
|
|
258
|
+
source publication and its durable suffix. A source may mark a transaction
|
|
259
|
+
`immediate` when it must update the authoritative base beneath an active
|
|
260
|
+
optimistic layer. The wrapper still gives that transaction one FIFO turn and
|
|
261
|
+
writes its durable suffix before admitting the next source turn.
|
|
262
|
+
|
|
263
|
+
The wrapper deliberately rejects schedules that would require a second
|
|
264
|
+
ordering mechanism. An `immediate` source transaction cannot enter while an
|
|
265
|
+
earlier normal source publication is waiting, and a source transaction cannot
|
|
266
|
+
cross a hydration cycle. These cases throw
|
|
267
|
+
`InvalidPersistedCollectionConfigError` instead of reordering data or waiting
|
|
268
|
+
in a dependency cycle.
|
|
269
|
+
|
|
270
|
+
### Atomic resume snapshots
|
|
271
|
+
|
|
272
|
+
Persistence adapters implement
|
|
273
|
+
`loadResumeSnapshot(collectionId, options)` to let a sync source certify a
|
|
274
|
+
persisted resume baseline. One call must read rows, collection metadata, stream
|
|
275
|
+
position, reset epoch, and key-set evidence from the same atomic database
|
|
276
|
+
snapshot. `includeRows: false` requests the same certification data without
|
|
277
|
+
materializing rows; `requiredIndexSignatures` carries the indexes needed by a
|
|
278
|
+
row-bearing snapshot.
|
|
279
|
+
|
|
280
|
+
`PersistedKeySetEvidence.status` has three states:
|
|
281
|
+
|
|
282
|
+
- `consistent`: the persisted rows match the adapter's durable expected-key
|
|
283
|
+
ledger.
|
|
284
|
+
- `incompatible`: row loss, substitution, or a reset-generation change makes
|
|
285
|
+
the saved resume baseline unsafe.
|
|
286
|
+
- `unknown`: the adapter has no authoritative pre-migration key set and does
|
|
287
|
+
not claim completeness.
|
|
288
|
+
|
|
289
|
+
The method is required because the versioned `metadata.persistence` capability
|
|
290
|
+
always carries hydration, durable row scanning, certification, evidence, and
|
|
291
|
+
generation ownership as one complete bundle. Sync wrappers must forward the
|
|
292
|
+
capability object unchanged rather than copying individual methods. Adapter
|
|
293
|
+
methods are invoked with their receiver and may rely on instance state through
|
|
294
|
+
`this`.
|
|
295
|
+
|
|
296
|
+
`SyncMetadataApi.persistence` is always present. Core sync sources receive
|
|
297
|
+
`null`, which explicitly means that no persistence bridge is active. The
|
|
298
|
+
persisted wrapper replaces that sentinel with the complete versioned
|
|
299
|
+
capability. A wrapper that omits the property is invalid and fails before a
|
|
300
|
+
consumer can resume or query against uncertified durable state.
|
|
301
|
+
|
|
67
302
|
### SQLite core adapter APIs
|
|
68
303
|
|
|
69
304
|
- `SQLiteCoreAdapterOptions`
|
|
70
305
|
- `SQLitePullSinceResult<TKey>`
|
|
71
|
-
- `SQLiteCorePersistenceAdapter
|
|
72
|
-
- `
|
|
306
|
+
- `SQLiteCorePersistenceAdapter`
|
|
307
|
+
- `DEFAULT_APPLIED_TX_PRUNE_MAX_ROWS`
|
|
308
|
+
- `DEFAULT_APPLIED_TX_PRUNE_MAX_AGE_SECONDS`
|
|
309
|
+
- `createSQLiteCorePersistenceAdapter(...)`
|
|
73
310
|
|
|
74
311
|
### Error APIs
|
|
75
312
|
|
|
@@ -78,10 +315,21 @@ while still handling per-collection schema versions correctly.
|
|
|
78
315
|
- `InvalidSyncConfigError`
|
|
79
316
|
- `InvalidPersistedCollectionCoordinatorError`
|
|
80
317
|
- `InvalidPersistenceAdapterError`
|
|
318
|
+
- `PersistedCollectionDurabilityErrorOptions`
|
|
319
|
+
- `PersistedCollectionDurabilityError`
|
|
320
|
+
- `toPersistedCollectionDurabilityError(...)`
|
|
321
|
+
- `IndeterminateCommitRequestType`
|
|
322
|
+
- `IndeterminateCommitErrorOptions`
|
|
323
|
+
- `IndeterminateCommitError`
|
|
81
324
|
- `InvalidPersistedStorageKeyError`
|
|
82
325
|
- `InvalidPersistedStorageKeyEncodingError`
|
|
83
326
|
- `PersistenceUnavailableError`
|
|
84
327
|
|
|
328
|
+
Adapter and coordinator commit failures reject the applied receipt and become
|
|
329
|
+
the collection's terminal sync error as `PersistedCollectionDurabilityError`.
|
|
330
|
+
That error preserves its original `cause`, `code`, and `path`. Hydration and
|
|
331
|
+
source errors remain distinct and are not wrapped as durability errors.
|
|
332
|
+
|
|
85
333
|
## Typical usage (via runtime wrappers)
|
|
86
334
|
|
|
87
335
|
In most applications, use a runtime package directly:
|
|
@@ -90,6 +338,9 @@ In most applications, use a runtime package directly:
|
|
|
90
338
|
- `@tanstack/browser-db-sqlite-persistence`
|
|
91
339
|
- `@tanstack/electron-db-sqlite-persistence`
|
|
92
340
|
- `@tanstack/react-native-db-sqlite-persistence`
|
|
341
|
+
- `@tanstack/expo-db-sqlite-persistence`
|
|
342
|
+
- `@tanstack/capacitor-db-sqlite-persistence`
|
|
343
|
+
- `@tanstack/tauri-db-sqlite-persistence`
|
|
93
344
|
- `@tanstack/cloudflare-durable-objects-db-sqlite-persistence`
|
|
94
345
|
|
|
95
346
|
Those packages provide concrete drivers and runtime wiring.
|