Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
150 commits
Select commit Hold shift + click to select a range
e79b4f0
docs: add sqlite persistence plan and phased guard rails
cursoragent Feb 10, 2026
121fc8d
feat: add sqlite persisted collection core phase-0 package
cursoragent Feb 10, 2026
2e472fd
feat(db): add index lifecycle events and removeIndex API
cursoragent Feb 10, 2026
bb8db6e
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
95d374e
feat(db): harden index lifecycle contract for phase-2 bootstrap
cursoragent Feb 10, 2026
6f0054e
test(db): align index metadata expectations with canonicalization
cursoragent Feb 10, 2026
47f8ef3
feat: implement phase 2 persisted wrapper runtime
cursoragent Feb 10, 2026
b4611e9
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
494e167
fix: stabilize phase 2 hydration and stream typing
cursoragent Feb 10, 2026
0369642
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
67d9ca5
fix: harden phase 2 consistency and recovery paths
cursoragent Feb 10, 2026
6c60750
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
52a20f6
feat: add sqlite core persistence adapter for phase 3
cursoragent Feb 10, 2026
0c2ee88
fix: address phase 3 adapter lint and test regressions
cursoragent Feb 10, 2026
ccd798d
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
e6f92c4
feat: harden phase 3 sqlite adapter semantics and contracts
cursoragent Feb 10, 2026
3bff526
fix: resolve relational comparator typing in sqlite adapter
cursoragent Feb 10, 2026
7dbaf1b
test: extend phase 3 sqlite adapter contract coverage
cursoragent Feb 10, 2026
cb11b94
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
369a465
feat: add time-based applied_tx pruning policy
cursoragent Feb 10, 2026
1a8b6ea
fix: align sqlite fallback equality with query semantics
cursoragent Feb 10, 2026
b11e2e6
fix: support alias-qualified paths in fallback evaluator
cursoragent Feb 10, 2026
af40468
refactor: reuse query evaluator in sqlite adapter fallback
cursoragent Feb 10, 2026
bc5315d
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
0092855
feat: add node sqlite persisted collection package
cursoragent Feb 10, 2026
1917260
fix: add better-sqlite3 type definitions for node adapter
cursoragent Feb 10, 2026
951eb25
test: extract reusable sqlite runtime contract suites
cursoragent Feb 10, 2026
c6c4f94
fix: tighten runtime contract typing in node tests
cursoragent Feb 10, 2026
7c4b03a
test: extract phase-3 sqlite adapter contract suite
cursoragent Feb 10, 2026
d95e575
test: exclude contract module from vitest test discovery
cursoragent Feb 10, 2026
fc16f5f
feat: add electron sqlite ipc bridge package
cursoragent Feb 10, 2026
f372172
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
d014d49
fix: tighten electron ipc protocol and contract typing
cursoragent Feb 10, 2026
98eedd2
fix: simplify electron ipc envelope typing
cursoragent Feb 10, 2026
daf7266
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
281209d
fix: stabilize electron renderer request typing
cursoragent Feb 10, 2026
88e398b
test: add portable runtime bridge e2e contract
cursoragent Feb 10, 2026
f8a9265
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
6ce057c
fix: stabilize electron runtime bridge e2e harness
cursoragent Feb 10, 2026
bc991e6
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
fb5ab89
test: run electron runtime e2e via built fixtures
cursoragent Feb 10, 2026
4b48789
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
be62073
test: split electron e2e vitest config
cursoragent Feb 10, 2026
f7c234b
fix: make electron e2e vitest config standalone
cursoragent Feb 10, 2026
5a2dade
test: build core db package before electron e2e
cursoragent Feb 10, 2026
3e10f83
test: build db-ivm before electron runtime e2e
cursoragent Feb 10, 2026
868b707
test: include stderr output on electron e2e timeout
cursoragent Feb 10, 2026
0774666
fix: avoid node native dependency in electron e2e harness
cursoragent Feb 10, 2026
f5e9d7c
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
b76cefd
fix: lazy-load node adapter without import-meta
cursoragent Feb 10, 2026
1c624ff
fix: load file-based renderer page in electron e2e
cursoragent Feb 10, 2026
7b7eadf
fix: run electron e2e under xvfb without headless
cursoragent Feb 10, 2026
26c53b7
fix: disable dev-shm usage for electron e2e
cursoragent Feb 10, 2026
347f548
fix: use cjs preload for electron runtime bridge e2e
cursoragent Feb 10, 2026
883d2e5
test: capture renderer diagnostics in electron e2e runner
cursoragent Feb 10, 2026
9d14e9c
fix: resolve preload renderer module via absolute path
cursoragent Feb 10, 2026
a1a1498
fix: disable sandbox for electron e2e preload
cursoragent Feb 10, 2026
56b9dab
test: exclude e2e fixtures from package typecheck scope
cursoragent Feb 10, 2026
471be28
test: add optional full-suite electron e2e mode
cursoragent Feb 10, 2026
1f4b753
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
4a9d7ca
fix: support multi-collection contract runs in e2e mode
cursoragent Feb 10, 2026
d7a131c
fix: allow graceful electron shutdown after e2e result
cursoragent Feb 10, 2026
24bd6a9
fix: avoid WAL sidecar drift in full electron e2e mode
cursoragent Feb 10, 2026
e225d7b
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
6a8c639
fix: support bigint and typed date comparisons in sqlite core
cursoragent Feb 10, 2026
ae7b5b4
test: add portable persisted collection conformance harness
cursoragent Feb 10, 2026
f669ace
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
bd3da5b
fix: harden typed conformance harness and rollback test
cursoragent Feb 10, 2026
c0e22bc
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
c9826da
fix: stabilize persisted cursor paging and node conformance harness
cursoragent Feb 10, 2026
3801d5c
test: add shared conformance suite for electron persisted
cursoragent Feb 10, 2026
7e6145f
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
5b71372
fix: harden electron full-e2e transport and timing
cursoragent Feb 10, 2026
81302b3
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
b3c0533
fix: preserve bigint payloads across electron fixture bridge
cursoragent Feb 10, 2026
8253f0c
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
fd62808
fix: serialize electron e2e results and extend full-mode timeouts
cursoragent Feb 10, 2026
1765035
fix: raise electron full-mode test time budgets via vitest config
cursoragent Feb 10, 2026
37fb303
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
47c1e87
fix: use function-safe e2e input encoding for electron bridge
cursoragent Feb 10, 2026
f8fa5b0
fix: strip subscription handles from electron loadSubset rpc
cursoragent Feb 10, 2026
f607f36
fix: preserve shared ir nodes in electron e2e input encoder
cursoragent Feb 10, 2026
b7c64c4
fix: make electron main require base path cjs-compatible
cursoragent Feb 10, 2026
ea666c6
test: serialize full-mode electron suites and align ipc timeouts
cursoragent Feb 10, 2026
5808b75
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
841ab87
test: isolate electron fixture env from vitest coverage vars
cursoragent Feb 10, 2026
a876cc3
test: increase full-mode electron rpc time budgets
cursoragent Feb 10, 2026
2c11b7e
fix: resolve electron require base path from absolute argv entry
cursoragent Feb 10, 2026
5a67602
feat: add react-native/expo sqlite persisted collection package
cursoragent Feb 10, 2026
95d9193
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
f234209
fix: align mobile adapter typing and burst persistence test
cursoragent Feb 10, 2026
405c629
ci: apply automated fixes
autofix-ci[bot] Feb 10, 2026
63da6b6
fix(react-native): harden transactions and expand parity coverage
cursoragent Feb 11, 2026
548c850
ci: apply automated fixes
autofix-ci[bot] Feb 11, 2026
680e654
test(react-native): stabilize lifecycle and runtime contract coverage
cursoragent Feb 11, 2026
92357a6
ci: apply automated fixes
autofix-ci[bot] Feb 11, 2026
112c515
fix(react-native): resolve transaction deadlock and harden runtime te…
cursoragent Feb 11, 2026
e61a0c0
ci: apply automated fixes
autofix-ci[bot] Feb 11, 2026
5af28a2
fix(sqlite-driver): enforce transaction callback parity across runtimes
cursoragent Feb 11, 2026
8a4c3f6
ci: apply automated fixes
autofix-ci[bot] Feb 11, 2026
ffe3264
test(react-native): add expo lifecycle coverage and ci e2e wiring
cursoragent Feb 11, 2026
15974dd
docs(ci): fix mobile setup examples and enforce runtime lane
cursoragent Feb 11, 2026
329ab78
ci: apply automated fixes
autofix-ci[bot] Feb 11, 2026
e07e9e6
ci(e2e): make mobile runtime lane enforceable but non-blocking by def…
cursoragent Feb 11, 2026
e37f760
ci(e2e): run node and electron persisted suites
cursoragent Feb 11, 2026
39377a7
feat: add cloudflare DO sqlite persistence with wrangler e2e
cursoragent Feb 11, 2026
cf7f287
test: harden cloudflare DO schema and transaction semantics
cursoragent Feb 11, 2026
c74efc1
docs: add complete API readmes for sqlite persistence packages
cursoragent Feb 11, 2026
66462d8
refactor: unify sqlite persistence APIs around shared persisters
cursoragent Feb 11, 2026
bf77c93
fix: preserve adapter defaults while keeping mode-aware persistence
cursoragent Feb 11, 2026
4f02ceb
refactor: simplify sqlite persistence APIs across runtimes
cursoragent Feb 11, 2026
0be8dd0
fix: satisfy generic cast in node persistence
cursoragent Feb 11, 2026
f3f0152
fix: narrow generic adapter cast in mobile persistence
cursoragent Feb 11, 2026
8aaf7fd
fix: narrow generic adapter cast in cloudflare persistence
cursoragent Feb 11, 2026
49af676
fix: tighten electron test harness and renderer typing
cursoragent Feb 11, 2026
f4d7f21
fix: tighten electron ipc test persistence typing
cursoragent Feb 11, 2026
2cde7a8
fix: normalize markIndexRemoved return type in electron tests
cursoragent Feb 11, 2026
0300fa6
fix(cloudflare-e2e): use collection-resolved adapter in worker fixture
cursoragent Feb 11, 2026
37e0f2f
fix(electron): preserve remote error code in renderer IPC
cursoragent Feb 11, 2026
286b6d3
fix(electron): catch async adapter errors in main IPC bridge
cursoragent Feb 11, 2026
818ceb0
feat(sqlite): accept native runtime handles in persistence factories
cursoragent Feb 11, 2026
49ca8c9
refactor(persistence): require native sqlite handles only
cursoragent Feb 12, 2026
9d8c07a
chore: refresh pnpm lockfile for cloudflare package peers
cursoragent Feb 12, 2026
aa92c9d
ci: apply automated fixes
autofix-ci[bot] Feb 12, 2026
f0c1d3e
feat(browser): implement phase 7 single-tab persistence
cursoragent Feb 12, 2026
2a4cee9
ci: apply automated fixes
autofix-ci[bot] Feb 12, 2026
5157fc0
fix(browser): move phase 7 opfs path into worker
cursoragent Feb 12, 2026
ffd3cfc
ci: apply automated fixes
autofix-ci[bot] Feb 12, 2026
e543ae3
fix(persistence): restore stream position on startup to prevent dupli…
kevin-dp Mar 4, 2026
8ff2a31
feat(persistence): inline row data in tx:committed broadcasts
kevin-dp Mar 5, 2026
5be9131
ci: apply automated fixes
autofix-ci[bot] Mar 5, 2026
2bc71f6
ci: apply automated fixes (attempt 2/3)
autofix-ci[bot] Mar 5, 2026
5dac6fa
docs: update phase 8 plan with implementation status annotations
kevin-dp Mar 5, 2026
8497cab
ci: apply automated fixes
autofix-ci[bot] Mar 5, 2026
8491dbe
feat(browser): implement Phase 8 BrowserCollectionCoordinator for mul…
kevin-dp Mar 5, 2026
51f6572
ci: apply automated fixes
autofix-ci[bot] Mar 5, 2026
4aa6d4a
fix(browser): prevent stuck leadership state on acquireLeadership errors
kevin-dp Mar 5, 2026
8703f6c
fix(persistence): always route mutations through coordinator to preve…
kevin-dp Mar 5, 2026
5f5fb17
fix(persistence): allow leader to process coordinator-delivered tx:co…
kevin-dp Mar 5, 2026
f040a62
ci: apply automated fixes
autofix-ci[bot] Mar 5, 2026
f0b341c
fix(persistence): handle delete messages with value in normalizeSyncW…
kevin-dp Mar 9, 2026
986862f
feat(electron-persistence): add ElectronCollectionCoordinator for cro…
kevin-dp Mar 10, 2026
027ac21
ci: apply automated fixes
autofix-ci[bot] Mar 10, 2026
b398c7a
chore: extract electron, node, and cloudflare persistence packages to…
kevin-dp Mar 12, 2026
5bf7370
fix(ci): remove extra blank line in e2e-tests workflow
kevin-dp Mar 12, 2026
d29b775
Delete plan
kevin-dp Mar 16, 2026
ca46819
Changeset
kevin-dp Mar 16, 2026
c0d7a9a
Strip virtual props from persistence tests
kevin-dp Mar 16, 2026
f563261
Changeset fix
kevin-dp Mar 16, 2026
8dc3daa
Formatting
kevin-dp Mar 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .changeset/sqlite-persistence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
'@tanstack/db': patch
'@tanstack/db-sqlite-persisted-collection-core': patch
'@tanstack/db-browser-wa-sqlite-persisted-collection': patch
'@tanstack/db-react-native-sqlite-persisted-collection': patch
---

feat(persistence): add SQLite-based offline persistence for collections

Adds a new persistence layer that durably stores collection data in SQLite, enabling applications to survive page reloads and app restarts.

**Core persistence (`@tanstack/db-sqlite-persisted-collection-core`)**

- New package providing the shared SQLite persistence runtime: hydration, streaming, transaction tracking, and applied-tx pruning
- SQLite core adapter with full query compilation, index management, and schema migration support
- Portable conformance test contracts for runtime-specific adapters

**Browser (`@tanstack/db-browser-wa-sqlite-persisted-collection`)**

- New package for browser persistence via wa-sqlite backed by OPFS
- Single-tab persistence with OPFS-based SQLite storage
- `BrowserCollectionCoordinator` for multi-tab leader-election and cross-tab sync

**React Native (`@tanstack/db-react-native-sqlite-persisted-collection`)**

- New package for React Native persistence via op-sqlite
- Adapter with transaction deadlock prevention and runtime parity coverage
39 changes: 38 additions & 1 deletion .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
e2e-tests:
name: Run E2E Tests
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 35

steps:
- name: Checkout code
Expand Down Expand Up @@ -62,6 +62,43 @@ jobs:
env:
ELECTRIC_URL: http://localhost:3000

- name: Run React Native/Expo persisted collection E2E tests
run: |
cd packages/db-react-native-sqlite-persisted-collection
pnpm test:e2e

- name: Run React Native/Expo runtime E2E lane
run: |
is_fork_pr=false
require_runtime_lane=${TANSTACK_DB_REQUIRE_MOBILE_RUNTIME_LANE:-0}
if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
is_fork_pr=$(jq -r '.pull_request.head.repo.fork' "${GITHUB_EVENT_PATH}")
fi

if [ "${is_fork_pr}" = "true" ]; then
echo "Skipping runtime mobile lane for fork PR (repo vars are unavailable)."
exit 0
fi

if [ -z "${TANSTACK_DB_MOBILE_SQLITE_FACTORY_MODULE}" ]; then
if [ "${require_runtime_lane}" = "1" ]; then
echo "::error::Missing repository variable TANSTACK_DB_MOBILE_SQLITE_FACTORY_MODULE while TANSTACK_DB_REQUIRE_MOBILE_RUNTIME_LANE=1."
echo "::error::Set TANSTACK_DB_MOBILE_SQLITE_FACTORY_MODULE (and optional TANSTACK_DB_MOBILE_SQLITE_FACTORY_EXPORT)."
exit 1
fi

echo "Skipping runtime mobile lane (no TANSTACK_DB_MOBILE_SQLITE_FACTORY_MODULE configured)."
echo "Set TANSTACK_DB_REQUIRE_MOBILE_RUNTIME_LANE=1 to enforce this lane."
exit 0
fi

cd packages/db-react-native-sqlite-persisted-collection
pnpm test:e2e:runtime
env:
TANSTACK_DB_MOBILE_SQLITE_FACTORY_MODULE: ${{ vars.TANSTACK_DB_MOBILE_SQLITE_FACTORY_MODULE }}
TANSTACK_DB_MOBILE_SQLITE_FACTORY_EXPORT: ${{ vars.TANSTACK_DB_MOBILE_SQLITE_FACTORY_EXPORT }}
TANSTACK_DB_REQUIRE_MOBILE_RUNTIME_LANE: ${{ vars.TANSTACK_DB_REQUIRE_MOBILE_RUNTIME_LANE }}

- name: Stop Docker services
if: always()
run: |
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
"pnpm": {
"overrides": {
"metro": "0.82.5"
}
},
"onlyBuiltDependencies": [
"better-sqlite3",
"electron"
]
},
"scripts": {
"build": "pnpm --filter \"./packages/**\" build",
Expand Down
54 changes: 54 additions & 0 deletions packages/db-browser-wa-sqlite-persisted-collection/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# @tanstack/db-browser-wa-sqlite-persisted-collection

Thin browser SQLite persistence for TanStack DB using `wa-sqlite` + OPFS.

## Public API

- `createBrowserWASQLitePersistence(...)`
- `openBrowserWASQLiteOPFSDatabase(...)`
- `persistedCollectionOptions(...)` (re-exported from core)

## Quick start

```ts
import { createCollection } from '@tanstack/db'
import {
createBrowserWASQLitePersistence,
openBrowserWASQLiteOPFSDatabase,
persistedCollectionOptions,
} from '@tanstack/db-browser-wa-sqlite-persisted-collection'

type Todo = {
id: string
title: string
completed: boolean
}

const database = await openBrowserWASQLiteOPFSDatabase({
databaseName: `tanstack-db.sqlite`,
})

const persistence = createBrowserWASQLitePersistence({
database,
})

export const todosCollection = createCollection(
persistedCollectionOptions<Todo, string>({
id: `todos`,
getKey: (todo) => todo.id,
persistence,
schemaVersion: 1, // Per-collection schema version
}),
)
```

## Notes

- This package is Phase 7 single-tab browser wiring: it uses
`SingleProcessCoordinator` semantics by default.
- `openBrowserWASQLiteOPFSDatabase(...)` starts a dedicated Web Worker and
routes SQL operations through it. OPFS sync access handle APIs are used in
that worker context.
- Single-tab mode does not require BroadcastChannel or Web Locks for
correctness.
- OPFS capability failures are surfaced as `PersistenceUnavailableError`.
Loading
Loading