pbtsdb 0.11.0 → 2.0.1

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/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # pbtsdb
2
2
 
3
- > Type-safe PocketBase integration with TanStack Query and TanStack DB for React applications. Provides reactive collections with automatic real-time subscriptions, optimistic mutations, full TypeScript type safety, and minimal boilerplate.
3
+ > Type-safe PocketBase integration with TanStack DB for React applications. Provides reactive collections with automatic real-time subscriptions, optimistic mutations, full TypeScript type safety, and minimal boilerplate.
4
4
 
5
5
  This library connects PocketBase (backend-as-a-service) to TanStack's reactive database tools. Use it when building React applications that need real-time data synchronization with PocketBase while maintaining strict type safety.
6
6
 
@@ -26,7 +26,7 @@ export type Schema = {
26
26
  }
27
27
 
28
28
  // 2. Create collections using curried createCollection
29
- const c = createCollection<Schema>(pb, queryClient);
29
+ const c = createCollection<Schema>(pb);
30
30
  const collections = {
31
31
  books: c('books', {}),
32
32
  authors: c('authors', {}),
@@ -72,7 +72,7 @@ const [myBooks] = useStore('myBooks');
72
72
 
73
73
  ## Key Concepts
74
74
 
75
- - **createCollection**: Curried function `createCollection<Schema>(pb, queryClient, factoryOptions?)` returns `(collectionName, options) => Collection`
75
+ - **createCollection**: Curried function `createCollection<Schema>(pb, factoryOptions?)` returns `(collectionName, options) => Collection`
76
76
  - **createReactProvider**: Wraps collections for React, returns `{ Provider, useStore }`
77
77
  - **Collections are lazy**: No network activity until first query
78
78
  - **Subscriptions are automatic**: Start when component mounts, stop 5s after unmount
@@ -86,7 +86,7 @@ For non-React environments, use `createCollection` directly:
86
86
  ```typescript
87
87
  import { createCollection } from 'pbtsdb';
88
88
 
89
- const c = createCollection<Schema>(pb, queryClient);
89
+ const c = createCollection<Schema>(pb);
90
90
  const booksCollection = c('books', {});
91
91
 
92
92
  // Collections have TanStack DB interface
@@ -95,12 +95,12 @@ const booksCollection = c('books', {});
95
95
 
96
96
  ## Real-time Subscription Options
97
97
 
98
- The third `createCollection` argument applies to every collection the factory
98
+ The second `createCollection` argument applies to every collection the factory
99
99
  builds. `subscribeOptions` is a getter invoked at subscribe time, so the value
100
100
  may change across reconnects:
101
101
 
102
102
  ```typescript
103
- const c = createCollection<Schema>(pb, queryClient, {
103
+ const c = createCollection<Schema>(pb, {
104
104
  subscribeOptions: () => {
105
105
  const token = getShareToken();
106
106
  return token ? { headers: { 'X-Share-Token': token } } : undefined;
@@ -142,7 +142,7 @@ Collections support insert, update, and delete with automatic PocketBase sync:
142
142
  import { newRecordId, createCollection, createReactProvider } from 'pbtsdb';
143
143
 
144
144
  // Setup with custom mutation handlers (optional)
145
- const c = createCollection<Schema>(pb, queryClient);
145
+ const c = createCollection<Schema>(pb);
146
146
  const collections = {
147
147
  books: c('books', {
148
148
  onInsert: async ({ transaction }) => { /* custom logic */ },
@@ -176,37 +176,38 @@ function BooksList() {
176
176
  // Delete with optimistic update
177
177
  books.delete('record_id');
178
178
 
179
- // Batch mutations - merges multiple updates to same record
180
- books.utils.writeBatch(() => {
181
- books.update('id1', (draft) => { draft.field1 = 'value1' });
182
- books.update('id1', (draft) => { draft.field2 = 'value2' }); // Merged!
183
- books.update('id2', (draft) => { draft.field = 'value' });
184
- });
185
-
186
- // Wait for persistence
187
- await tx.isPersisted.promise; // States: pending → persisting → completed
179
+ // Wait for persistence (isPersisted.promise is deprecated)
180
+ await tx.when('settled'); // States: pending → persisting → completed
188
181
  }
189
182
  ```
190
183
 
191
184
  **Key Points:**
192
185
  - Mutations are optimistic by default (UI updates immediately)
193
186
  - Auto-syncs to PocketBase in background
194
- - Batch mutations merge updates to same record
187
+ - The built-in handlers write the server response into the collection before they settle, so the settled row is the server's row (`created`, `updated`, hook-rewritten values)
195
188
  - Transaction states: pending → persisting → completed
196
189
  - Use `newRecordId()` to generate PocketBase-compatible IDs
190
+ - `row.$hasPendingWrites` is true while a row has an unsettled optimistic change (`$synced` is deprecated)
191
+ - A custom `onInsert`/`onUpdate` should `await collection.accept(serverRows)` and a custom `onDelete` should `await collection.evict(ids)` before it returns `void`; otherwise the row shows its previous server value from settle until the realtime echo
192
+ - `collection.accept(rows)` lands server-returned rows as confirmed state; `collection.evict(ids)` removes rows the server deleted; `collection.reload()` refetches every live query's subset and drops rows the results do not confirm. All three resolve on acceptance and are also on `collection.utils`
197
193
 
198
194
  ## Common Patterns
199
195
 
200
196
  **Approach 1: Related data (Recommended)**
201
197
 
202
198
  PocketBase `expand` only files related records into their own collections;
203
- rows never carry `expand`. Read related records from the target collection.
199
+ rows never carry `expand`. Read related records from the target collection
200
+ through `materialize()` or a join inside the `useLiveQuery` that needs them.
201
+ Do not read them with `collection.get(id)` in a component: a `get()` does not
202
+ re-render when the row changes, and the row can leave the store while the
203
+ component still shows it. `get()` is for code outside React, such as a mutation
204
+ handler.
204
205
 
205
206
  ```typescript
206
207
  import { eq } from '@tanstack/db';
207
208
  import { materialize } from 'pbtsdb';
208
209
 
209
- const c = createCollection<Schema>(pb, queryClient);
210
+ const c = createCollection<Schema>(pb);
210
211
  const authors = c('authors', { syncMode: 'on-demand' });
211
212
  const books = c('books', {
212
213
  relations: { author: authors }, // where expanded records are filed
@@ -245,7 +246,7 @@ const { data } = useLiveQuery((q) => q.from({ books: books.fetchRelations('tags'
245
246
 
246
247
  **Approach 2: TanStack Joins**
247
248
  ```typescript
248
- const c = createCollection<Schema>(pb, queryClient);
249
+ const c = createCollection<Schema>(pb);
249
250
  const collections = {
250
251
  jobs: c('jobs', {}),
251
252
  customers: c('customers', {}),
@@ -271,13 +272,16 @@ const [jobs, customers] = useStore('jobs', 'customers');
271
272
 
272
273
  - Simple CRUD without real-time (PocketBase SDK is simpler)
273
274
  - Very large collections (>10k records - use pagination)
274
- - Non-PocketBase backends (use TanStack Query directly)
275
+ - Non-PocketBase backends (use `@tanstack/db` directly)
275
276
  - Server-side only Node.js (use PocketBase SDK directly)
276
277
 
277
278
  ### Package Details
278
279
 
279
- - Requires React 18+, TypeScript 5.0+, PocketBase 0.21.0+
280
- - Collections use TanStack Query for caching and TanStack DB for reactivity
281
- - Real-time via PocketBase Server-Sent Events (SSE)
282
- - Automatic reconnection with exponential backoff on subscription failures
280
+ - Requires React 18+, TypeScript 5.0+, PocketBase 0.22.0+
281
+ - Requires `@tanstack/db` 0.12.1+, `@tanstack/react-db` 0.5.5+
282
+ - Collections use TanStack DB's core sync API, with pbtsdb's own membership ledger
283
+ - Real-time via PocketBase Server-Sent Events (SSE), through pbtsdb's own client
284
+ - Automatic reconnection with exponential backoff; a reconnect the server did
285
+ not resume refetches every live query, since PocketBase does not replay
286
+ events missed during the gap
283
287
  - Default syncMode is 'eager' (matches TanStack DB default)
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "pbtsdb",
3
- "version": "0.11.0",
4
- "description": "Type-safe PocketBase integration with TanStack Query and TanStack DB",
3
+ "version": "2.0.1",
4
+ "description": "Type-safe PocketBase integration with TanStack DB",
5
5
  "keywords": [
6
6
  "pocketbase",
7
7
  "tanstack",
8
- "tanstack-query",
9
8
  "tanstack-db",
10
9
  "database",
11
10
  "react",
@@ -57,10 +56,8 @@
57
56
  "test:server:migrate": "pocketbase migrate --dir ./pb_data"
58
57
  },
59
58
  "peerDependencies": {
60
- "@tanstack/db": ">=0.9.0",
61
- "@tanstack/query-db-collection": ">=1.2.13",
62
- "@tanstack/react-db": ">=0.3.8",
63
- "@tanstack/react-query": ">=5.0.0",
59
+ "@tanstack/db": ">=0.12.1",
60
+ "@tanstack/react-db": ">=0.5.5",
64
61
  "pocketbase": ">=0.22.0",
65
62
  "react": ">=18.0.0",
66
63
  "react-dom": ">=18.0.0"
@@ -78,10 +75,8 @@
78
75
  },
79
76
  "devDependencies": {
80
77
  "@biomejs/biome": "^2.5.0",
81
- "@tanstack/db": ">=0.9.0",
82
- "@tanstack/query-db-collection": ">=1.2.13",
83
- "@tanstack/react-db": ">=0.3.8",
84
- "@tanstack/react-query": ">=5.101.0",
78
+ "@tanstack/db": ">=0.12.1",
79
+ "@tanstack/react-db": ">=0.5.5",
85
80
  "@testing-library/react": ">=16.3.2",
86
81
  "@types/node": ">=25.0.10",
87
82
  "@types/react": ">=19.2.10",