pbtsdb 0.7.2 → 0.8.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 +74 -28
- package/dist/chunk-KMR6I4ZC.js +950 -0
- package/dist/chunk-KMR6I4ZC.js.map +1 -0
- package/dist/core.d.ts +138 -60
- package/dist/core.js +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/llms.txt +11 -7
- package/package.json +4 -4
- package/dist/chunk-7DHFWXB3.js +0 -510
- package/dist/chunk-7DHFWXB3.js.map +0 -1
package/README.md
CHANGED
|
@@ -123,14 +123,19 @@ const queryClient = new QueryClient({
|
|
|
123
123
|
|
|
124
124
|
// Create collections with automatic type inference
|
|
125
125
|
const c = createCollection<BlogSchema>(pb, queryClient);
|
|
126
|
+
const users = c('users', {});
|
|
126
127
|
export const { Provider, useStore } = createReactProvider({
|
|
128
|
+
users,
|
|
127
129
|
posts: c('posts', {
|
|
128
|
-
omitOnInsert: ['created', 'updated'] as const
|
|
130
|
+
omitOnInsert: ['created', 'updated'] as const,
|
|
131
|
+
relations: { author: users },
|
|
132
|
+
alwaysExpand: ['author'],
|
|
129
133
|
}),
|
|
130
|
-
users: c('users', {}),
|
|
131
134
|
comments: c('comments', {
|
|
132
|
-
omitOnInsert: ['created', 'updated'] as const
|
|
133
|
-
|
|
135
|
+
omitOnInsert: ['created', 'updated'] as const,
|
|
136
|
+
relations: { author: users },
|
|
137
|
+
alwaysExpand: ['author'],
|
|
138
|
+
}),
|
|
134
139
|
});
|
|
135
140
|
|
|
136
141
|
export function App() {
|
|
@@ -320,7 +325,8 @@ const collection = c(collectionName: string, options?: CreateCollectionOptions);
|
|
|
320
325
|
- `options` - Optional configuration
|
|
321
326
|
|
|
322
327
|
**Options:**
|
|
323
|
-
- `
|
|
328
|
+
- `relations?: Record<string, Collection>` - Collections that receive expanded records for each relation; declares what `alwaysExpand` and `collection.expand()` may name
|
|
329
|
+
- `alwaysExpand?: readonly string[]` - Expand paths applied on every fetch (e.g. `['author', 'book.author']`)
|
|
324
330
|
- `omitOnInsert?: readonly string[]` - Fields to make optional during insert (e.g., `['created', 'updated'] as const`)
|
|
325
331
|
- `syncMode?: 'eager' | 'on-demand'` - Data fetching strategy (default: `'eager'`)
|
|
326
332
|
- `onInsert?: InsertMutationFn | false` - Custom insert handler or `false` to disable
|
|
@@ -339,40 +345,81 @@ const c = createCollection<MySchema>(pb, queryClient);
|
|
|
339
345
|
const booksCollection = c('books', {});
|
|
340
346
|
```
|
|
341
347
|
|
|
342
|
-
With
|
|
348
|
+
With always-expanded relations:
|
|
343
349
|
```typescript
|
|
344
350
|
const c = createCollection<MySchema>(pb, queryClient);
|
|
345
351
|
const authorsCollection = c('authors', {});
|
|
346
352
|
const booksCollection = c('books', {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
353
|
+
relations: { author: authorsCollection }, // where expanded authors are upserted
|
|
354
|
+
alwaysExpand: ['author'], // expanded on every fetch
|
|
350
355
|
});
|
|
351
356
|
|
|
352
|
-
// Expand is automatic on every fetch
|
|
353
357
|
const { data } = useLiveQuery((q) => q.from({ books: booksCollection }));
|
|
358
|
+
// data[0].expand?.author is typed and populated
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### Per-query expand
|
|
362
|
+
|
|
363
|
+
Declare relations once, then ask for expansion per query with `collection.expand()`.
|
|
364
|
+
A view shares the collection's store, realtime subscription, and mutations; only
|
|
365
|
+
its fetches add the `expand` parameter.
|
|
354
366
|
|
|
355
|
-
|
|
367
|
+
```typescript
|
|
368
|
+
const tagsCollection = c('tags', {});
|
|
369
|
+
const booksCollection = c('books', {
|
|
370
|
+
relations: { author: authorsCollection, tags: tagsCollection },
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
function BookList() {
|
|
374
|
+
const [books] = useStore('books');
|
|
375
|
+
const { data } = useLiveQuery((q) =>
|
|
376
|
+
q.from({ books: books.expand('tags') })
|
|
377
|
+
.where(({ books }) => eq(books.genre, 'Fiction'))
|
|
378
|
+
);
|
|
379
|
+
// data[0].expand?.tags is Tags[] | undefined; data[0].expand?.author is a type error
|
|
380
|
+
}
|
|
356
381
|
```
|
|
357
382
|
|
|
383
|
+
Paths can be nested through a target collection's own `relations`:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
const metadata = c('book_metadata', { relations: { book: booksCollection } });
|
|
387
|
+
const { data } = useLiveQuery((q) => q.from({ m: metadata.expand('book.author') }));
|
|
388
|
+
// data[0].expand?.book?.expand?.author?.name
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Rows fetched through a view keep their `expand` data in the shared store, and the
|
|
392
|
+
realtime subscription requests every relation in use, so echoes keep it populated.
|
|
393
|
+
|
|
394
|
+
Relation targets stay live too. While a query expands into `tags` (or through
|
|
395
|
+
it into `colors`), those collections keep their realtime subscriptions, and a
|
|
396
|
+
change to a tag or a color updates the embedded copy on affected rows in
|
|
397
|
+
place, so `book.expand?.tags?.[0].name` refreshes without a write to the book.
|
|
398
|
+
While an optimistic mutation is pending on the parent row, TanStack DB shows
|
|
399
|
+
the frozen optimistic snapshot, so a patched `expand` becomes visible once
|
|
400
|
+
that mutation settles. Deleting a related record clears the reference and the
|
|
401
|
+
copy, matching what PocketBase does server-side. Targets are released when
|
|
402
|
+
the last query on the parent unmounts.
|
|
403
|
+
|
|
358
404
|
#### Collection Options Passthrough
|
|
359
405
|
|
|
360
406
|
Pass any [TanStack DB `BaseCollectionConfig`](https://tanstack.com/db/latest/docs/overview) option directly via `collectionOptions`. This is useful for configuring indexing, garbage collection, and other collection-level settings:
|
|
361
407
|
|
|
362
408
|
```typescript
|
|
363
|
-
import { BasicIndex } from 'pbtsdb';
|
|
364
|
-
|
|
365
409
|
const c = createCollection<MySchema>(pb, queryClient);
|
|
366
410
|
const booksCollection = c('books', {
|
|
367
411
|
collectionOptions: {
|
|
368
|
-
autoIndex: 'eager',
|
|
369
|
-
defaultIndexType: BasicIndex,
|
|
370
412
|
gcTime: 60000, // 1 minute GC
|
|
371
413
|
startSync: true, // Start syncing immediately
|
|
372
414
|
}
|
|
373
415
|
});
|
|
374
416
|
```
|
|
375
417
|
|
|
418
|
+
pbtsdb defaults `autoIndex` to `'eager'` with `defaultIndexType: BTreeIndex`, so
|
|
419
|
+
`orderBy` + `limit` queries page lazily instead of loading the whole subset (and
|
|
420
|
+
TanStack DB does not warn about a missing index). Pass `autoIndex: 'off'` or a
|
|
421
|
+
different `defaultIndexType` in `collectionOptions` to change that per collection.
|
|
422
|
+
|
|
376
423
|
The following fields are managed by pbtsdb and excluded from `collectionOptions`: `getKey`, `syncMode`, `onInsert`, `onUpdate`, `onDelete`, `schema`.
|
|
377
424
|
|
|
378
425
|
### React Integration
|
|
@@ -890,7 +937,8 @@ Use PocketBase's `expand` to auto-populate a related collection, then use includ
|
|
|
890
937
|
const authorsCollection = c('authors', { syncMode: 'on-demand' });
|
|
891
938
|
const booksCollection = c('books', {
|
|
892
939
|
syncMode: 'on-demand',
|
|
893
|
-
|
|
940
|
+
relations: { author: authorsCollection }, // Auto-populates authorsCollection
|
|
941
|
+
alwaysExpand: ['author'],
|
|
894
942
|
});
|
|
895
943
|
|
|
896
944
|
const { data } = useLiveQuery((q) =>
|
|
@@ -944,12 +992,11 @@ const books = c('books', {
|
|
|
944
992
|
omitOnInsert: ['created', 'updated'] as const
|
|
945
993
|
});
|
|
946
994
|
|
|
947
|
-
// ✅ Good - with
|
|
995
|
+
// ✅ Good - with always-expanded relations
|
|
948
996
|
const authors = c('authors', {});
|
|
949
997
|
const books = c('books', {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
}
|
|
998
|
+
relations: { author: authors },
|
|
999
|
+
alwaysExpand: ['author'],
|
|
953
1000
|
});
|
|
954
1001
|
```
|
|
955
1002
|
|
|
@@ -979,16 +1026,16 @@ When using expand collections, create the target collection first:
|
|
|
979
1026
|
const c = createCollection<MySchema>(pb, queryClient);
|
|
980
1027
|
const authors = c('authors', {});
|
|
981
1028
|
const books = c('books', {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
}
|
|
1029
|
+
relations: { author: authors }, // authors is already created
|
|
1030
|
+
alwaysExpand: ['author'],
|
|
985
1031
|
});
|
|
986
1032
|
|
|
987
1033
|
// ❌ Bad - can't reference what doesn't exist yet
|
|
988
1034
|
const books = c('books', {
|
|
989
|
-
|
|
1035
|
+
relations: {
|
|
990
1036
|
author: ??? // Where is authors?
|
|
991
|
-
}
|
|
1037
|
+
},
|
|
1038
|
+
alwaysExpand: ['author'],
|
|
992
1039
|
});
|
|
993
1040
|
```
|
|
994
1041
|
|
|
@@ -1030,9 +1077,8 @@ Use PocketBase's expand feature for better performance:
|
|
|
1030
1077
|
const c = createCollection<MySchema>(pb, queryClient);
|
|
1031
1078
|
const authors = c('authors', {});
|
|
1032
1079
|
const posts = c('posts', {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
}
|
|
1080
|
+
relations: { author: authors },
|
|
1081
|
+
alwaysExpand: ['author'], // Auto-expand on every fetch
|
|
1036
1082
|
});
|
|
1037
1083
|
|
|
1038
1084
|
const { data } = useLiveQuery((q) => q.from({ posts }));
|