From 66ea51cb9e6602ec5e0537db7f49edaf2eb70c4a Mon Sep 17 00:00:00 2001 From: Kevin De Porre Date: Thu, 7 May 2026 10:05:13 +0200 Subject: [PATCH] docs(browser-db-sqlite-persistence): document multi-tab coordinator usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The README described the package as "Phase 7 single-tab browser wiring", which suggested multi-tab was not supported. In fact, single-tab is just the default — passing a `BrowserCollectionCoordinator` via the `coordinator` option enables multi-tab coordination today. Drop the internal phase reference, list `BrowserCollectionCoordinator` in the public API, split the quick start into single-tab and multi-tab sections, and link to the offline-transactions example for the multi-tab case. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../browser-db-sqlite-persistence/README.md | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/packages/browser-db-sqlite-persistence/README.md b/packages/browser-db-sqlite-persistence/README.md index b14c83b32..84175bf7c 100644 --- a/packages/browser-db-sqlite-persistence/README.md +++ b/packages/browser-db-sqlite-persistence/README.md @@ -1,6 +1,9 @@ # @tanstack/browser-db-sqlite-persistence -Thin browser SQLite persistence for TanStack DB using `wa-sqlite` + OPFS. +Browser SQLite persistence for TanStack DB using `wa-sqlite` + OPFS. + +Supports both single-tab (default) and multi-tab usage. Multi-tab coordination +is opt-in by passing a `BrowserCollectionCoordinator`. ## Public API @@ -8,7 +11,12 @@ Thin browser SQLite persistence for TanStack DB using `wa-sqlite` + OPFS. - `openBrowserWASQLiteOPFSDatabase(...)` - `persistedCollectionOptions(...)` (re-exported from core) -## Quick start +## Quick start (single-tab) + +By default, `createBrowserWASQLitePersistence` uses `SingleProcessCoordinator` +semantics — no leader election, no `BroadcastChannel`, no Web Locks. This is +the right choice when your app is only ever open in one tab at a time, or when +each tab uses its own database. ```ts import { createCollection } from '@tanstack/db' @@ -42,13 +50,60 @@ export const todosCollection = createCollection( ) ``` +## Multi-tab usage + +To safely share a single OPFS database across multiple tabs of the same +origin, pass a `BrowserCollectionCoordinator` via the `coordinator` option. +The coordinator uses the Web Locks API to elect a leader tab, and +`BroadcastChannel` to fan out committed transactions to follower tabs. +Follower tabs forward writes to the leader via RPC over the channel. + +```ts +import { createCollection } from '@tanstack/db' +import { + BrowserCollectionCoordinator, + createBrowserWASQLitePersistence, + openBrowserWASQLiteOPFSDatabase, + persistedCollectionOptions, +} from '@tanstack/browser-db-sqlite-persistence' + +const database = await openBrowserWASQLiteOPFSDatabase({ + databaseName: `tanstack-db.sqlite`, +}) + +const coordinator = new BrowserCollectionCoordinator({ + dbName: `tanstack-db`, +}) + +const persistence = createBrowserWASQLitePersistence({ + database, + coordinator, +}) + +export const todosCollection = createCollection( + persistedCollectionOptions({ + id: `todos`, + getKey: (todo) => todo.id, + persistence, + schemaVersion: 1, + }), +) + +// On teardown: +// coordinator.dispose() +// await database.close?.() +``` + +See [`examples/react/offline-transactions`](../../examples/react/offline-transactions/src/db/persisted-todos.ts) +for a full multi-tab example. + ## 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 +- Single-tab mode does not require `BroadcastChannel` or Web Locks for correctness. +- Multi-tab mode requires `BroadcastChannel` and the Web Locks API; both are + available in all modern browsers. - OPFS capability failures are surfaced as `PersistenceUnavailableError`.