pbtsdb 0.1.3 → 0.3.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 +119 -0
- package/dist/index.d.ts +46 -1
- package/dist/index.js +35 -17
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@ A TypeScript library that seamlessly integrates [PocketBase](https://pocketbase.
|
|
|
25
25
|
- [Basic Queries](#basic-queries)
|
|
26
26
|
- [Filtering and Sorting](#filtering-and-sorting)
|
|
27
27
|
- [Relations and Joins](#relations-and-joins)
|
|
28
|
+
- [Includes (Nested Subqueries)](#includes-nested-subqueries)
|
|
28
29
|
- [Real-time Updates](#real-time-updates)
|
|
29
30
|
- [Mutations](#mutations)
|
|
30
31
|
- [TypeScript](#typescript)
|
|
@@ -306,6 +307,8 @@ const collection = c(collectionName: string, options?: CreateCollectionOptions);
|
|
|
306
307
|
- `onInsert?: InsertMutationFn | false` - Custom insert handler or `false` to disable
|
|
307
308
|
- `onUpdate?: UpdateMutationFn | false` - Custom update handler or `false` to disable
|
|
308
309
|
- `onDelete?: DeleteMutationFn | false` - Custom delete handler or `false` to disable
|
|
310
|
+
- `ignoreAutoCancellation?: boolean` - Ignore PocketBase auto-cancellation errors (default: `true`)
|
|
311
|
+
- `collectionOptions?: object` - Additional TanStack DB collection options passed through directly (see [Collection Options Passthrough](#collection-options-passthrough))
|
|
309
312
|
|
|
310
313
|
**Returns:** Fully-typed Collection instance with subscription capabilities
|
|
311
314
|
|
|
@@ -333,6 +336,26 @@ const { data } = useLiveQuery((q) => q.from({ books: booksCollection }));
|
|
|
333
336
|
// Expanded records auto-inserted into authorsCollection
|
|
334
337
|
```
|
|
335
338
|
|
|
339
|
+
#### Collection Options Passthrough
|
|
340
|
+
|
|
341
|
+
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:
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
import { BasicIndex } from 'pbtsdb';
|
|
345
|
+
|
|
346
|
+
const c = createCollection<MySchema>(pb, queryClient);
|
|
347
|
+
const booksCollection = c('books', {
|
|
348
|
+
collectionOptions: {
|
|
349
|
+
autoIndex: 'eager',
|
|
350
|
+
defaultIndexType: BasicIndex,
|
|
351
|
+
gcTime: 60000, // 1 minute GC
|
|
352
|
+
startSync: true, // Start syncing immediately
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
The following fields are managed by pbtsdb and excluded from `collectionOptions`: `getKey`, `syncMode`, `onInsert`, `onUpdate`, `onDelete`, `schema`.
|
|
358
|
+
|
|
336
359
|
### React Integration
|
|
337
360
|
|
|
338
361
|
#### createReactProvider()
|
|
@@ -480,6 +503,30 @@ booksCollection.insert(newBook);
|
|
|
480
503
|
|
|
481
504
|
**Returns:** `string` - 15-character lowercase alphanumeric ID
|
|
482
505
|
|
|
506
|
+
#### Re-exported TanStack DB Utilities
|
|
507
|
+
|
|
508
|
+
pbtsdb re-exports commonly used TanStack DB utilities so you don't need to depend on `@tanstack/db` directly:
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
import {
|
|
512
|
+
// Includes helpers
|
|
513
|
+
toArray,
|
|
514
|
+
createEffect,
|
|
515
|
+
|
|
516
|
+
// Index types (for collectionOptions.defaultIndexType)
|
|
517
|
+
BasicIndex,
|
|
518
|
+
BTreeIndex,
|
|
519
|
+
ReverseIndex,
|
|
520
|
+
|
|
521
|
+
// Types
|
|
522
|
+
type DeltaEvent,
|
|
523
|
+
type DeltaType,
|
|
524
|
+
type EffectConfig,
|
|
525
|
+
type EffectContext,
|
|
526
|
+
type IndexConstructor,
|
|
527
|
+
} from 'pbtsdb';
|
|
528
|
+
```
|
|
529
|
+
|
|
483
530
|
## Usage Examples
|
|
484
531
|
|
|
485
532
|
### Example 1: Task Manager with Filtering
|
|
@@ -739,6 +786,78 @@ export function ProjectDashboard({ projectId }: { projectId: string }) {
|
|
|
739
786
|
|
|
740
787
|
Demonstrates variadic `useStore()`, client-side aggregations, and TanStack DB joins.
|
|
741
788
|
|
|
789
|
+
### Includes (Nested Subqueries)
|
|
790
|
+
|
|
791
|
+
TanStack DB 0.6.0 introduces **includes** — nested subqueries within `select()` that project normalized data into hierarchical shapes. This is useful when you want to compose related data from multiple collections reactively.
|
|
792
|
+
|
|
793
|
+
#### Single relation with `findOne()`
|
|
794
|
+
|
|
795
|
+
```typescript
|
|
796
|
+
import { useLiveQuery, eq } from '@tanstack/react-db';
|
|
797
|
+
|
|
798
|
+
const { data: booksWithAuthors } = useLiveQuery((q) =>
|
|
799
|
+
q.from({ b: booksCollection }).select(({ b }) => ({
|
|
800
|
+
id: b.id,
|
|
801
|
+
title: b.title,
|
|
802
|
+
author: q
|
|
803
|
+
.from({ a: authorsCollection })
|
|
804
|
+
.where(({ a }) => eq(a.id, b.author))
|
|
805
|
+
.select(({ a }) => ({ id: a.id, name: a.name }))
|
|
806
|
+
.findOne(),
|
|
807
|
+
}))
|
|
808
|
+
);
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
#### Many relation with `toArray()`
|
|
812
|
+
|
|
813
|
+
```typescript
|
|
814
|
+
import { useLiveQuery, eq, toArray } from '@tanstack/react-db';
|
|
815
|
+
// Or: import { toArray } from 'pbtsdb';
|
|
816
|
+
|
|
817
|
+
const { data: booksWithTags } = useLiveQuery((q) =>
|
|
818
|
+
q.from({ b: booksCollection }).select(({ b }) => ({
|
|
819
|
+
id: b.id,
|
|
820
|
+
title: b.title,
|
|
821
|
+
tags: toArray(
|
|
822
|
+
q.from({ bt: bookTagsCollection })
|
|
823
|
+
.where(({ bt }) => eq(bt.book, b.id))
|
|
824
|
+
.join({ t: tagsCollection }, ({ bt, t }) => eq(bt.tag, t.id))
|
|
825
|
+
.select(({ t }) => ({ id: t.id, name: t.name }))
|
|
826
|
+
),
|
|
827
|
+
}))
|
|
828
|
+
);
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
#### Combining expand with includes
|
|
832
|
+
|
|
833
|
+
Use PocketBase's `expand` to auto-populate a related collection, then use includes to query from it:
|
|
834
|
+
|
|
835
|
+
```typescript
|
|
836
|
+
const authorsCollection = c('authors', { syncMode: 'on-demand' });
|
|
837
|
+
const booksCollection = c('books', {
|
|
838
|
+
syncMode: 'on-demand',
|
|
839
|
+
expand: { author: authorsCollection }, // Auto-populates authorsCollection
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
const { data } = useLiveQuery((q) =>
|
|
843
|
+
q.from({ b: booksCollection }).select(({ b }) => ({
|
|
844
|
+
id: b.id,
|
|
845
|
+
title: b.title,
|
|
846
|
+
// Query from the expand-populated authorsCollection
|
|
847
|
+
author: q.from({ a: authorsCollection })
|
|
848
|
+
.where(({ a }) => eq(a.id, b.author))
|
|
849
|
+
.select(({ a }) => ({ id: a.id, name: a.name }))
|
|
850
|
+
.findOne(),
|
|
851
|
+
tags: toArray(
|
|
852
|
+
q.from({ bt: bookTagsCollection })
|
|
853
|
+
.where(({ bt }) => eq(bt.book, b.id))
|
|
854
|
+
.join({ t: tagsCollection }, ({ bt, t }) => eq(bt.tag, t.id))
|
|
855
|
+
.select(({ t }) => ({ id: t.id, name: t.name }))
|
|
856
|
+
),
|
|
857
|
+
}))
|
|
858
|
+
);
|
|
859
|
+
```
|
|
860
|
+
|
|
742
861
|
## TypeScript
|
|
743
862
|
|
|
744
863
|
pbtsdb is fully type-safe. Here's what you need to know:
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Collection, InsertMutationFn, UpdateMutationFn, DeleteMutationFn } from '@tanstack/db';
|
|
1
|
+
import { Collection, InsertMutationFn, UpdateMutationFn, DeleteMutationFn, BaseCollectionConfig } from '@tanstack/db';
|
|
2
|
+
export { BTreeIndex, BasicIndex, DeltaEvent, DeltaType, EffectConfig, EffectContext, IndexConstructor, ReverseIndex, createEffect, toArray } from '@tanstack/db';
|
|
2
3
|
import PocketBase from 'pocketbase';
|
|
3
4
|
import { Collection as Collection$1 } from '@tanstack/react-db';
|
|
4
5
|
import { QueryCollectionUtils } from '@tanstack/query-db-collection';
|
|
@@ -312,6 +313,50 @@ interface CreateCollectionOptions<Schema extends SchemaDeclaration, CollectionNa
|
|
|
312
313
|
* ```
|
|
313
314
|
*/
|
|
314
315
|
syncMode?: 'eager' | 'on-demand';
|
|
316
|
+
/**
|
|
317
|
+
* Whether to ignore PocketBase auto-cancellation errors.
|
|
318
|
+
*
|
|
319
|
+
* PocketBase automatically cancels pending requests when a new request is made
|
|
320
|
+
* to the same endpoint. This can throw ClientResponseError with a message
|
|
321
|
+
* containing "autocancelled". When this option is true, such errors are
|
|
322
|
+
* silently ignored and the existing cached data is returned for the cancelled request.
|
|
323
|
+
*
|
|
324
|
+
* @default true
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```ts
|
|
328
|
+
* // Default: auto-cancellation errors are ignored
|
|
329
|
+
* const collection = createCollection<Schema>(pb, queryClient)('books');
|
|
330
|
+
*
|
|
331
|
+
* // Explicitly handle auto-cancellation errors
|
|
332
|
+
* const collection = createCollection<Schema>(pb, queryClient)('books', {
|
|
333
|
+
* ignoreAutoCancellation: false
|
|
334
|
+
* });
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
337
|
+
ignoreAutoCancellation?: boolean;
|
|
338
|
+
/**
|
|
339
|
+
* Additional options passed directly to the underlying TanStack DB collection.
|
|
340
|
+
* Use this to configure indexing, garbage collection, comparison functions,
|
|
341
|
+
* and any other TanStack DB collection options not explicitly exposed by pbtsdb.
|
|
342
|
+
*
|
|
343
|
+
* Options set here are spread into the `queryCollectionOptions()` call.
|
|
344
|
+
* Fields managed by pbtsdb (`getKey`, `syncMode`, `onInsert`, `onUpdate`,
|
|
345
|
+
* `onDelete`, `schema`) are excluded from the type.
|
|
346
|
+
*
|
|
347
|
+
* @example
|
|
348
|
+
* ```ts
|
|
349
|
+
* import { BasicIndex } from 'pbtsdb'
|
|
350
|
+
* const collection = createCollection<Schema>(pb, queryClient)('books', {
|
|
351
|
+
* collectionOptions: {
|
|
352
|
+
* autoIndex: 'eager',
|
|
353
|
+
* defaultIndexType: BasicIndex,
|
|
354
|
+
* gcTime: 60000,
|
|
355
|
+
* }
|
|
356
|
+
* });
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
359
|
+
collectionOptions?: Omit<Partial<BaseCollectionConfig<ExtractRecordType<Schema, CollectionName>, string | number>>, 'getKey' | 'syncMode' | 'onInsert' | 'onUpdate' | 'onDelete' | 'schema'>;
|
|
315
360
|
}
|
|
316
361
|
|
|
317
362
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createCollection as createCollection$1 } from '@tanstack/react-db';
|
|
2
2
|
import { queryCollectionOptions } from '@tanstack/query-db-collection';
|
|
3
3
|
import { parseWhereExpression, parseOrderByExpression } from '@tanstack/db';
|
|
4
|
+
export { BTreeIndex, BasicIndex, ReverseIndex, createEffect, toArray } from '@tanstack/db';
|
|
4
5
|
import { createContext, useContext } from 'react';
|
|
5
6
|
import { jsx } from 'react/jsx-runtime';
|
|
6
7
|
|
|
@@ -138,26 +139,34 @@ function createCollection(pb, queryClient) {
|
|
|
138
139
|
return (collectionName, options) => {
|
|
139
140
|
const expandStores = options?.expand;
|
|
140
141
|
const expandString = expandStores ? Object.keys(expandStores).sort().join(",") : void 0;
|
|
142
|
+
const ignoreAutoCancellation = options?.ignoreAutoCancellation ?? true;
|
|
141
143
|
async function fetchRecords(loadOptions) {
|
|
142
144
|
const filter = convertToPocketBaseFilter(loadOptions?.where);
|
|
143
145
|
const sort = convertToPocketBaseSort(loadOptions?.orderBy);
|
|
144
146
|
const limit = loadOptions?.limit;
|
|
145
147
|
let items;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
148
|
+
try {
|
|
149
|
+
if (limit) {
|
|
150
|
+
const result = await pb.collection(collectionName).getList(1, limit, {
|
|
151
|
+
filter,
|
|
152
|
+
sort,
|
|
153
|
+
skipTotal: true,
|
|
154
|
+
// Optimize by skipping total count
|
|
155
|
+
expand: expandString
|
|
156
|
+
});
|
|
157
|
+
items = result.items;
|
|
158
|
+
} else {
|
|
159
|
+
items = await pb.collection(collectionName).getFullList({
|
|
160
|
+
filter,
|
|
161
|
+
sort,
|
|
162
|
+
expand: expandString
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
} catch (error) {
|
|
166
|
+
if (ignoreAutoCancellation && error instanceof Error && error.message.includes("autocancelled")) {
|
|
167
|
+
return queryClient.getQueryData([collectionName]) ?? [];
|
|
168
|
+
}
|
|
169
|
+
throw error;
|
|
161
170
|
}
|
|
162
171
|
if (expandStores) {
|
|
163
172
|
for (const record of items) {
|
|
@@ -182,6 +191,7 @@ function createCollection(pb, queryClient) {
|
|
|
182
191
|
return items;
|
|
183
192
|
}
|
|
184
193
|
const collectionOptions = queryCollectionOptions({
|
|
194
|
+
...options?.collectionOptions,
|
|
185
195
|
queryClient,
|
|
186
196
|
queryKey: [collectionName],
|
|
187
197
|
syncMode: options?.syncMode ?? "eager",
|
|
@@ -191,14 +201,22 @@ function createCollection(pb, queryClient) {
|
|
|
191
201
|
getKey: (item) => {
|
|
192
202
|
const record = item;
|
|
193
203
|
if (!record || typeof record !== "object" || !("id" in record)) {
|
|
194
|
-
throw new Error(
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Record in collection '${collectionName}' is missing required 'id' field. Received: ${JSON.stringify(item)}`
|
|
206
|
+
);
|
|
195
207
|
}
|
|
196
208
|
return record.id;
|
|
197
209
|
},
|
|
198
210
|
onInsert: options?.onInsert === false ? void 0 : options?.onInsert ?? (async ({ transaction }) => {
|
|
199
211
|
await Promise.all(
|
|
200
212
|
transaction.mutations.map(async (mutation) => {
|
|
201
|
-
const {
|
|
213
|
+
const {
|
|
214
|
+
created,
|
|
215
|
+
updated,
|
|
216
|
+
collectionId,
|
|
217
|
+
collectionName: _,
|
|
218
|
+
...data
|
|
219
|
+
} = mutation.modified;
|
|
202
220
|
await pb.collection(collectionName).create(data);
|
|
203
221
|
})
|
|
204
222
|
);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pocketbase-query-converter.ts","../src/logger.ts","../src/collection.ts","../src/react.tsx","../src/util.ts"],"names":["createTanStackCollection"],"mappings":"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","file":"index.js","sourcesContent":["import { parseWhereExpression, parseOrderByExpression, type FieldPath, type ParsedOrderBy } from '@tanstack/db';\nimport type { IR } from '@tanstack/db';\n\ntype BasicExpression<T = unknown> = IR.BasicExpression<T>;\n\nfunction escapeValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n if (typeof value === 'number') {\n return value.toString();\n }\n if (typeof value === 'string') {\n return `\"${value.replace(/\"/g, '\\\\\"')}\"`;\n }\n if (value instanceof Date) {\n return `\"${value.toISOString()}\"`;\n }\n if (Array.isArray(value)) {\n return `[${value.map(escapeValue).join(',')}]`;\n }\n return `\"${String(value)}\"`;\n}\n\nfunction fieldPathToString(path: FieldPath): string {\n return path.join('.');\n}\n\nexport function convertToPocketBaseFilter(\n where: BasicExpression<boolean> | undefined | null\n): string | undefined {\n if (!where) {\n return undefined;\n }\n\n const result = parseWhereExpression(where, {\n handlers: {\n eq: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} = ${escapeValue(value)}`;\n },\n gt: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} > ${escapeValue(value)}`;\n },\n gte: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} >= ${escapeValue(value)}`;\n },\n lt: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} < ${escapeValue(value)}`;\n },\n lte: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} <= ${escapeValue(value)}`;\n },\n and: (...conditions: string[]) => {\n if (conditions.length === 0) return '';\n if (conditions.length === 1) return conditions[0];\n return `(${conditions.join(' && ')})`;\n },\n or: (...conditions: string[]) => {\n if (conditions.length === 0) return '';\n if (conditions.length === 1) return conditions[0];\n return `(${conditions.join(' || ')})`;\n },\n not: (condition: string) => {\n return `!(${condition})`;\n },\n in: (field: FieldPath, values: unknown) => {\n const valueArray = Array.isArray(values) ? values : [values];\n const uniqueValues = [...new Set(valueArray)];\n const fieldStr = fieldPathToString(field);\n const conditions = uniqueValues.map((v) => `${fieldStr} = ${escapeValue(v)}`);\n return conditions.length > 1 ? `(${conditions.join(' || ')})` : conditions[0];\n },\n like: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} ~ ${escapeValue(value)}`;\n },\n isNull: (field: FieldPath) => {\n return `${fieldPathToString(field)} = null`;\n },\n isUndefined: (field: FieldPath) => {\n return `${fieldPathToString(field)} = null`;\n },\n },\n onUnknownOperator: (operator: string, args: unknown[]) => {\n throw new Error(\n `Unsupported operator '${operator}' for PocketBase filter conversion. ` +\n `Supported operators: eq, gt, gte, lt, lte, in, like, and, or, not, isNull, isUndefined`\n );\n },\n });\n\n return result || undefined;\n}\n\nexport function convertToPocketBaseSort(\n orderBy: IR.OrderBy | undefined | null\n): string | undefined {\n if (!orderBy) {\n return undefined;\n }\n\n const sorts = parseOrderByExpression(orderBy);\n\n if (sorts.length === 0) {\n return undefined;\n }\n\n return sorts\n .map((sort: ParsedOrderBy) => {\n const field = fieldPathToString(sort.field);\n return sort.direction === 'desc' ? `-${field}` : field;\n })\n .join(',');\n}\n","/**\n * Logger interface for subscription events and internal operations.\n * Users can provide their own implementation to integrate with external logging services.\n */\nexport interface Logger {\n /**\n * Log debug-level messages (typically only shown in development).\n * @param msg - The message to log\n * @param context - Optional context object with additional information\n */\n debug: (msg: string, context?: object) => void;\n\n /**\n * Log info-level messages.\n * @param msg - The message to log\n * @param context - Optional context object with additional information\n */\n info: (msg: string, context?: object) => void;\n\n /**\n * Log warning-level messages.\n * @param msg - The message to log\n * @param context - Optional context object with additional information\n */\n warn: (msg: string, context?: object) => void;\n\n /**\n * Log error-level messages.\n * @param msg - The message to log\n * @param context - Optional context object with additional information\n */\n error: (msg: string, context?: object) => void;\n}\n\n/**\n * Default console-based logger implementation.\n * Only logs debug messages in development mode.\n */\nconst defaultLogger: Logger = {\n debug: (msg: string, context?: object) => {\n // Only log debug in development\n if (process.env.NODE_ENV === 'development') {\n // biome-ignore lint/suspicious/noConsoleLog: Debug logging is acceptable in development\n console.log(`[pbtsdb] ${msg}`, context || '');\n }\n },\n info: (msg: string, context?: object) => {\n // biome-ignore lint/suspicious/noConsoleLog: Info logging is acceptable\n console.info(`[pbtsdb] ${msg}`, context || '');\n },\n warn: (msg: string, context?: object) => {\n // biome-ignore lint/suspicious/noConsoleLog: Warning logging is acceptable\n console.warn(`[pbtsdb] ${msg}`, context || '');\n },\n error: (msg: string, context?: object) => {\n // biome-ignore lint/suspicious/noConsoleLog: Error logging is acceptable\n console.error(`[pbtsdb] ${msg}`, context || '');\n },\n};\n\n/**\n * Current logger instance (can be replaced by users).\n */\nlet currentLogger: Logger = defaultLogger;\n\n/**\n * Internal logger instance used by the library.\n */\nexport const logger: Logger = {\n debug: (msg: string, context?: object) => currentLogger.debug(msg, context),\n info: (msg: string, context?: object) => currentLogger.info(msg, context),\n warn: (msg: string, context?: object) => currentLogger.warn(msg, context),\n error: (msg: string, context?: object) => currentLogger.error(msg, context),\n};\n\n/**\n * Set a custom logger implementation.\n * This allows users to integrate with their own logging services (e.g., Sentry, LogRocket, etc.).\n *\n * @param customLogger - The custom logger implementation\n *\n * @example\n * ```ts\n * import { setLogger } from 'pbtsdb';\n *\n * // Integration with a custom logging service\n * setLogger({\n * debug: (msg, context) => myLogger.debug(msg, context),\n * warn: (msg, context) => myLogger.warn(msg, context),\n * error: (msg, context) => {\n * myLogger.error(msg, context);\n * Sentry.captureMessage(msg, { level: 'error', extra: context });\n * },\n * });\n * ```\n *\n * @example\n * ```ts\n * // Disable all logging\n * setLogger({\n * debug: () => {},\n * warn: () => {},\n * error: () => {},\n * });\n * ```\n */\nexport function setLogger(customLogger: Logger): void {\n currentLogger = customLogger;\n}\n\n/**\n * Reset the logger to the default implementation.\n */\nexport function resetLogger(): void {\n currentLogger = defaultLogger;\n}\n","import PocketBase from 'pocketbase';\nimport type { RecordSubscription } from 'pocketbase';\nimport { createCollection as createTanStackCollection, type Collection, type LoadSubsetOptions } from \"@tanstack/react-db\"\nimport { queryCollectionOptions, type QueryCollectionUtils } from \"@tanstack/query-db-collection\"\nimport { QueryClient } from '@tanstack/react-query'\nimport { convertToPocketBaseFilter, convertToPocketBaseSort } from './pocketbase-query-converter';\nimport type {\n SchemaDeclaration,\n CreateCollectionOptions,\n ExtractRecordType,\n ExpandTargetCollection,\n BaseRecord,\n} from './types';\nimport { logger } from './logger';\n\nexport type {\n SchemaDeclaration,\n CreateCollectionOptions,\n BaseRecord,\n} from './types';\n\n/**\n * Extended LoadSubsetOptions that includes PocketBase-specific expand parameter.\n * @internal\n */\ntype ExtendedLoadSubsetOptions = LoadSubsetOptions & {\n pbExpand?: string;\n};\n\n/**\n * Compute the record type with expand property when expand option is configured.\n * @internal\n */\ntype WithExpandFromConfig<\n Schema extends SchemaDeclaration,\n C extends keyof Schema,\n Opts\n> = Opts extends { expand: infer E }\n ? ExtractRecordType<Schema, C> & {\n expand?: {\n [K in keyof E]: K extends keyof import('./types').ExtractRelations<Schema, C>\n ? import('./types').ExtractRelations<Schema, C>[K] extends Array<infer U>\n ? U[]\n : import('./types').ExtractRelations<Schema, C>[K]\n : never;\n };\n }\n : ExtractRecordType<Schema, C>;\n\n/**\n * Subscription helpers added to collection instances.\n * @internal\n */\ninterface CollectionSubscriptionHelpers {\n /** The PocketBase collection name */\n collectionName: string;\n /** Wait for subscription to be established (useful in tests) */\n waitForSubscription: (timeout?: number) => Promise<void>;\n /** Check if collection has an active subscription */\n isSubscribed: () => boolean;\n}\n\n/**\n * Inferred collection type from config options.\n * @internal\n */\ntype InferCollectionType<\n Schema extends SchemaDeclaration,\n C extends keyof Schema,\n Opts extends CreateCollectionOptions<Schema, C>\n> = Collection<\n WithExpandFromConfig<Schema, C, Opts>,\n string | number,\n // TUtils - QueryCollectionUtils from TanStack Query DB Collection\n QueryCollectionUtils<WithExpandFromConfig<Schema, C, Opts>, string | number, WithExpandFromConfig<Schema, C, Opts>>,\n // TSchema - we don't use StandardSchema validation\n never,\n Opts extends { omitOnInsert: infer O extends readonly import('./types').OmittableFields<ExtractRecordType<Schema, C>>[] }\n ? import('./types').ComputeInsertType<ExtractRecordType<Schema, C>, O>\n : ExtractRecordType<Schema, C>\n> & CollectionSubscriptionHelpers;\n\n\n/**\n * Creates a type-safe TanStack DB collection backed by PocketBase.\n * Use this when you need fine-grained control or need to create collections with dependencies.\n *\n * @param pb - PocketBase client instance\n * @param queryClient - TanStack Query client\n * @returns A curried function that takes collection name and options\n *\n * @example\n * Basic usage:\n * ```ts\n * const booksCollection = createCollection<Schema>(pb, queryClient)('books', {});\n *\n * // Use directly\n * const books = await booksCollection.getFullList();\n * ```\n *\n * @example\n * With auto-expand relations:\n * ```ts\n * const authorsCollection = createCollection<Schema>(pb, queryClient)('authors', {});\n * const booksCollection = createCollection<Schema>(pb, queryClient)('books', {\n * expand: {\n * author: authorsCollection // Always expand, auto-upsert into authorsCollection\n * }\n * });\n *\n * // Expand is automatic - no .expand() call needed\n * const { data } = useLiveQuery((q) => q.from({ books: booksCollection }));\n * // data[0].expand.author is typed and populated\n * ```\n */\nexport function createCollection<Schema extends SchemaDeclaration>(\n pb: PocketBase,\n queryClient: QueryClient\n) {\n return <\n C extends keyof Schema & string,\n Opts extends CreateCollectionOptions<Schema, C> = CreateCollectionOptions<Schema, C>\n >(\n collectionName: C,\n options?: Opts\n ): InferCollectionType<Schema, C, Opts> => {\n type RecordType = ExtractRecordType<Schema, C>;\n const expandStores = options?.expand as Record<string, ExpandTargetCollection> | undefined;\n const expandString = expandStores ? Object.keys(expandStores).sort().join(',') : undefined;\n\n async function fetchRecords(loadOptions?: ExtendedLoadSubsetOptions): Promise<RecordType[]> {\n const filter = convertToPocketBaseFilter(loadOptions?.where);\n const sort = convertToPocketBaseSort(loadOptions?.orderBy);\n const limit = loadOptions?.limit;\n\n let items: RecordType[];\n if (limit) {\n // Use getList when limit is specified to avoid fetching all records\n const result = await pb.collection(collectionName).getList(1, limit, {\n filter,\n sort,\n skipTotal: true, // Optimize by skipping total count\n expand: expandString,\n });\n items = result.items as unknown as RecordType[];\n } else {\n // Use getFullList to fetch all records with automatic pagination\n items = await pb.collection(collectionName).getFullList({\n filter,\n sort,\n expand: expandString,\n }) as unknown as RecordType[];\n }\n\n if (expandStores) {\n for (const record of items) {\n const expandData = (record as RecordType & { expand?: Record<string, object | object[]> }).expand;\n if (!expandData) continue;\n\n for (const [key, value] of Object.entries(expandData)) {\n const targetStore = expandStores[key];\n if (!targetStore.utils) continue;\n if (!targetStore.isReady()) {\n if (targetStore.config?.syncMode === 'on-demand') {\n await targetStore._sync.startSync();\n } else {\n logger.warn(`not syncing ${key} on ${collectionName} because store is not yet ready`)\n continue\n }\n }\n const values = Array.isArray(value) ? value : [value];\n targetStore.utils.writeUpsert(values);\n }\n }\n }\n\n return items;\n }\n\n const collectionOptions = queryCollectionOptions({\n queryClient,\n queryKey: [collectionName],\n syncMode: options?.syncMode ?? 'eager',\n queryFn: async (ctx): Promise<RecordType[]> => {\n return fetchRecords(ctx.meta?.loadSubsetOptions as ExtendedLoadSubsetOptions | undefined);\n },\n getKey: (item: RecordType) => {\n const record = item as any;\n if (!record || typeof record !== 'object' || !('id' in record)) {\n throw new Error(`Record in collection '${collectionName}' is missing required 'id' field. Received: ${JSON.stringify(item)}`);\n }\n return record.id;\n },\n onInsert: options?.onInsert === false ? undefined : options?.onInsert ?? (async ({ transaction }) => {\n await Promise.all(\n transaction.mutations.map(async (mutation) => {\n const { created, updated, collectionId, collectionName: _, ...data } = mutation.modified as unknown as Record<string, unknown>;\n await pb.collection(collectionName).create(data);\n })\n );\n }),\n onUpdate: options?.onUpdate === false ? undefined : options?.onUpdate ?? (async ({ transaction }) => {\n await Promise.all(\n transaction.mutations.map(async (mutation) => {\n const recordWithId = mutation.original as { id: string };\n await pb.collection(collectionName).update(recordWithId.id, mutation.changes);\n })\n );\n }),\n onDelete: options?.onDelete === false ? undefined : options?.onDelete ?? (async ({ transaction }) => {\n await Promise.all(\n transaction.mutations.map(async (mutation) => {\n const recordWithId = mutation.original as { id: string };\n await pb.collection(collectionName).delete(recordWithId.id);\n })\n );\n })\n });\n\n const collection = createTanStackCollection(collectionOptions);\n\n // Real-time subscription state\n let unsubscribeFn: (() => Promise<void>) | null = null;\n let isSubscribed = false;\n let subscriptionPromise: Promise<void> | null = null;\n let subscriptionResolve: (() => void) | null = null;\n\n // Handle real-time events from PocketBase\n const handleRealtimeEvent = (event: RecordSubscription<RecordType>) => {\n if (!collection.utils) return;\n\n collection.utils.writeBatch(() => {\n switch (event.action) {\n case 'create':\n collection.utils.writeInsert(event.record);\n break;\n case 'update':\n collection.utils.writeUpsert(event.record);\n break;\n case 'delete':\n if (event.record && 'id' in event.record) {\n collection.utils.writeDelete((event.record as { id: string }).id);\n }\n break;\n }\n });\n };\n\n // Start PocketBase real-time subscription\n const startSubscription = async () => {\n if (isSubscribed) return;\n\n // Create promise before starting so waiters can await it\n if (!subscriptionPromise) {\n subscriptionPromise = new Promise<void>((resolve) => {\n subscriptionResolve = resolve;\n });\n }\n\n try {\n unsubscribeFn = await pb.collection(collectionName).subscribe('*', handleRealtimeEvent);\n isSubscribed = true;\n logger.debug('Subscription started', { collectionName });\n // Resolve the promise to notify waiters\n if (subscriptionResolve) {\n subscriptionResolve();\n }\n } catch (error) {\n logger.error('Failed to start subscription', { collectionName, error });\n }\n };\n\n // Stop PocketBase real-time subscription\n const stopSubscription = async () => {\n if (!isSubscribed || !unsubscribeFn) return;\n\n try {\n await unsubscribeFn();\n unsubscribeFn = null;\n isSubscribed = false;\n // Reset promise for next subscription cycle\n subscriptionPromise = null;\n subscriptionResolve = null;\n logger.debug('Subscription stopped', { collectionName });\n } catch (error) {\n logger.debug('Unsubscribe failed (expected if connection closed)', { collectionName, error });\n }\n };\n\n // Wait for subscription to be established (for testing)\n const waitForSubscription = async (timeout = 5000): Promise<void> => {\n if (isSubscribed) return;\n\n if (!subscriptionPromise) {\n // No subscription in progress, wait for one to start\n await new Promise<void>((resolve) => {\n const checkInterval = setInterval(() => {\n if (subscriptionPromise) {\n clearInterval(checkInterval);\n resolve();\n }\n }, 10);\n setTimeout(() => {\n clearInterval(checkInterval);\n resolve();\n }, timeout);\n });\n }\n\n if (subscriptionPromise) {\n await Promise.race([\n subscriptionPromise,\n new Promise<void>((_, reject) =>\n setTimeout(() => reject(new Error('Subscription timeout')), timeout)\n )\n ]);\n }\n };\n\n // Manage subscription based on collection subscriber count\n collection.on('subscribers:change', (event: { subscriberCount: number; previousSubscriberCount: number }) => {\n const newCount = event.subscriberCount;\n const previousCount = event.previousSubscriberCount;\n\n if (newCount > 0 && previousCount === 0) {\n // First subscriber - start real-time subscription\n startSubscription().catch(() => {});\n } else if (newCount === 0 && previousCount > 0) {\n // Last subscriber removed - stop real-time subscription\n stopSubscription().catch(() => {});\n }\n });\n\n // Add collectionName and subscription helpers\n Object.assign(collection, {\n collectionName,\n waitForSubscription,\n isSubscribed: () => isSubscribed,\n });\n\n return collection as any;\n };\n}\n\n","import React, { createContext, useContext, type ReactNode } from 'react';\n\n/**\n * UseStore hook type for variadic collection access.\n * @internal\n */\ntype UseStoreFn<CollectionsMap> = <K extends (keyof CollectionsMap)[]>(\n ...keys: K\n) => { [I in keyof K]: K[I] extends keyof CollectionsMap ? CollectionsMap[K[I]] : never };\n\n/**\n * Return type for createReactProvider function.\n */\nexport interface ReactProviderResult<CollectionsMap> {\n /**\n * React Context Provider component.\n * Wrap your app with this provider to make collections available to useStore.\n */\n Provider: React.FC<{ children: ReactNode }>;\n\n /**\n * Hook to access collections from the provider.\n * Uses variadic arguments for clean syntax with automatic type inference.\n *\n * @example\n * ```tsx\n * // Single collection\n * const [books] = useStore('books');\n *\n * // Multiple collections (no 'as const' needed!)\n * const [books, authors] = useStore('books', 'authors');\n * ```\n */\n useStore: UseStoreFn<CollectionsMap>;\n}\n\n/**\n * Creates a React Provider and useStore hook from a collections map.\n *\n * @param collections - Map of collection keys to Collection instances\n * @returns Object containing Provider component and useStore hook\n *\n * @example\n * Basic usage:\n * ```tsx\n * import { createCollection, createReactProvider } from 'pbtsdb';\n * import { useLiveQuery } from '@tanstack/react-db';\n *\n * // Step 1: Create collections\n * const c = createCollection<Schema>(pb, queryClient);\n * const collections = {\n * books: c('books', {}),\n * authors: c('authors', {}),\n * };\n *\n * // Step 2: Wrap for React\n * const { Provider, useStore } = createReactProvider(collections);\n *\n * // Step 3: Wrap your app\n * function App() {\n * return (\n * <QueryClientProvider client={queryClient}>\n * <Provider>\n * <BooksList />\n * </Provider>\n * </QueryClientProvider>\n * );\n * }\n *\n * // Step 4: Use in components\n * function BooksList() {\n * const [books] = useStore('books');\n * const { data } = useLiveQuery((q) => q.from({ books }));\n * return <div>{data?.map(book => <p key={book.id}>{book.title}</p>)}</div>;\n * }\n * ```\n *\n * @example\n * Variadic useStore pattern:\n * ```tsx\n * function BooksWithAuthors() {\n * const [books, authors] = useStore('books', 'authors');\n *\n * const { data } = useLiveQuery((q) =>\n * q.from({ book: books })\n * .join(\n * { author: authors },\n * ({ book, author }) => eq(book.author, author.id),\n * 'left'\n * )\n * );\n *\n * return <div>...</div>;\n * }\n * ```\n *\n * @example\n * With auto-expand collections:\n * ```tsx\n * const c = createCollection<Schema>(pb, queryClient);\n * const authors = c('authors', {});\n * const books = c('books', {\n * expand: {\n * author: authors\n * }\n * });\n *\n * const { Provider, useStore } = createReactProvider({ authors, books });\n *\n * function BooksWithExpandedAuthors() {\n * const [books] = useStore('books');\n * const { data } = useLiveQuery((q) => q.from({ books }));\n *\n * return (\n * <ul>\n * {data?.map(book => (\n * <li key={book.id}>\n * {book.title} by {book.expand?.author?.name}\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function createReactProvider<CollectionsMap extends Record<string, any>>(\n collections: CollectionsMap\n): ReactProviderResult<CollectionsMap> {\n const Context = createContext<CollectionsMap | null>(null);\n\n const Provider: React.FC<{ children: ReactNode }> = ({ children }) => (\n <Context.Provider value={collections}>{children}</Context.Provider>\n );\n\n function useStore<K extends (keyof CollectionsMap)[]>(\n ...keys: K\n ): { [I in keyof K]: K[I] extends keyof CollectionsMap ? CollectionsMap[K[I]] : never } {\n const context = useContext(Context);\n\n if (!context) {\n throw new Error('useStore must be used within the Provider returned by createReactProvider');\n }\n\n return keys.map((key) => {\n if (!(key in context)) {\n throw new Error(`Collection \"${String(key)}\" not found in collections`);\n }\n return context[key];\n }) as { [I in keyof K]: K[I] extends keyof CollectionsMap ? CollectionsMap[K[I]] : never };\n }\n\n return {\n Provider,\n useStore: useStore as UseStoreFn<CollectionsMap>,\n };\n}\n","/**\n * Generates a new PocketBase-compatible record ID.\n * Returns a 15-character alphanumeric string (lowercase letters and numbers).\n *\n * PocketBase uses 15-character IDs for records, formatted as lowercase alphanumeric.\n *\n * @returns A 15-character alphanumeric string suitable for use as a PocketBase record ID\n *\n * @example\n * ```ts\n * const id = newRecordId(); // \"a1b2c3d4e5f6g7h\"\n * ```\n */\nexport function newRecordId(): string {\n const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n for (let i = 0; i < 15; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/pocketbase-query-converter.ts","../src/logger.ts","../src/collection.ts","../src/react.tsx","../src/util.ts"],"names":["createTanStackCollection"],"mappings":"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","file":"index.js","sourcesContent":["import { parseWhereExpression, parseOrderByExpression, type FieldPath, type ParsedOrderBy } from '@tanstack/db';\nimport type { IR } from '@tanstack/db';\n\ntype BasicExpression<T = unknown> = IR.BasicExpression<T>;\n\nfunction escapeValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n if (typeof value === 'number') {\n return value.toString();\n }\n if (typeof value === 'string') {\n return `\"${value.replace(/\"/g, '\\\\\"')}\"`;\n }\n if (value instanceof Date) {\n return `\"${value.toISOString()}\"`;\n }\n if (Array.isArray(value)) {\n return `[${value.map(escapeValue).join(',')}]`;\n }\n return `\"${String(value)}\"`;\n}\n\nfunction fieldPathToString(path: FieldPath): string {\n return path.join('.');\n}\n\nexport function convertToPocketBaseFilter(\n where: BasicExpression<boolean> | undefined | null\n): string | undefined {\n if (!where) {\n return undefined;\n }\n\n const result = parseWhereExpression(where, {\n handlers: {\n eq: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} = ${escapeValue(value)}`;\n },\n gt: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} > ${escapeValue(value)}`;\n },\n gte: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} >= ${escapeValue(value)}`;\n },\n lt: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} < ${escapeValue(value)}`;\n },\n lte: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} <= ${escapeValue(value)}`;\n },\n and: (...conditions: string[]) => {\n if (conditions.length === 0) return '';\n if (conditions.length === 1) return conditions[0];\n return `(${conditions.join(' && ')})`;\n },\n or: (...conditions: string[]) => {\n if (conditions.length === 0) return '';\n if (conditions.length === 1) return conditions[0];\n return `(${conditions.join(' || ')})`;\n },\n not: (condition: string) => {\n return `!(${condition})`;\n },\n in: (field: FieldPath, values: unknown) => {\n const valueArray = Array.isArray(values) ? values : [values];\n const uniqueValues = [...new Set(valueArray)];\n const fieldStr = fieldPathToString(field);\n const conditions = uniqueValues.map((v) => `${fieldStr} = ${escapeValue(v)}`);\n return conditions.length > 1 ? `(${conditions.join(' || ')})` : conditions[0];\n },\n like: (field: FieldPath, value: unknown) => {\n return `${fieldPathToString(field)} ~ ${escapeValue(value)}`;\n },\n isNull: (field: FieldPath) => {\n return `${fieldPathToString(field)} = null`;\n },\n isUndefined: (field: FieldPath) => {\n return `${fieldPathToString(field)} = null`;\n },\n },\n onUnknownOperator: (operator: string, args: unknown[]) => {\n throw new Error(\n `Unsupported operator '${operator}' for PocketBase filter conversion. ` +\n `Supported operators: eq, gt, gte, lt, lte, in, like, and, or, not, isNull, isUndefined`\n );\n },\n });\n\n return result || undefined;\n}\n\nexport function convertToPocketBaseSort(\n orderBy: IR.OrderBy | undefined | null\n): string | undefined {\n if (!orderBy) {\n return undefined;\n }\n\n const sorts = parseOrderByExpression(orderBy);\n\n if (sorts.length === 0) {\n return undefined;\n }\n\n return sorts\n .map((sort: ParsedOrderBy) => {\n const field = fieldPathToString(sort.field);\n return sort.direction === 'desc' ? `-${field}` : field;\n })\n .join(',');\n}\n","/**\n * Logger interface for subscription events and internal operations.\n * Users can provide their own implementation to integrate with external logging services.\n */\nexport interface Logger {\n /**\n * Log debug-level messages (typically only shown in development).\n * @param msg - The message to log\n * @param context - Optional context object with additional information\n */\n debug: (msg: string, context?: object) => void;\n\n /**\n * Log info-level messages.\n * @param msg - The message to log\n * @param context - Optional context object with additional information\n */\n info: (msg: string, context?: object) => void;\n\n /**\n * Log warning-level messages.\n * @param msg - The message to log\n * @param context - Optional context object with additional information\n */\n warn: (msg: string, context?: object) => void;\n\n /**\n * Log error-level messages.\n * @param msg - The message to log\n * @param context - Optional context object with additional information\n */\n error: (msg: string, context?: object) => void;\n}\n\n/**\n * Default console-based logger implementation.\n * Only logs debug messages in development mode.\n */\nconst defaultLogger: Logger = {\n debug: (msg: string, context?: object) => {\n // Only log debug in development\n if (process.env.NODE_ENV === 'development') {\n // biome-ignore lint/suspicious/noConsoleLog: Debug logging is acceptable in development\n console.log(`[pbtsdb] ${msg}`, context || '');\n }\n },\n info: (msg: string, context?: object) => {\n // biome-ignore lint/suspicious/noConsoleLog: Info logging is acceptable\n console.info(`[pbtsdb] ${msg}`, context || '');\n },\n warn: (msg: string, context?: object) => {\n // biome-ignore lint/suspicious/noConsoleLog: Warning logging is acceptable\n console.warn(`[pbtsdb] ${msg}`, context || '');\n },\n error: (msg: string, context?: object) => {\n // biome-ignore lint/suspicious/noConsoleLog: Error logging is acceptable\n console.error(`[pbtsdb] ${msg}`, context || '');\n },\n};\n\n/**\n * Current logger instance (can be replaced by users).\n */\nlet currentLogger: Logger = defaultLogger;\n\n/**\n * Internal logger instance used by the library.\n */\nexport const logger: Logger = {\n debug: (msg: string, context?: object) => currentLogger.debug(msg, context),\n info: (msg: string, context?: object) => currentLogger.info(msg, context),\n warn: (msg: string, context?: object) => currentLogger.warn(msg, context),\n error: (msg: string, context?: object) => currentLogger.error(msg, context),\n};\n\n/**\n * Set a custom logger implementation.\n * This allows users to integrate with their own logging services (e.g., Sentry, LogRocket, etc.).\n *\n * @param customLogger - The custom logger implementation\n *\n * @example\n * ```ts\n * import { setLogger } from 'pbtsdb';\n *\n * // Integration with a custom logging service\n * setLogger({\n * debug: (msg, context) => myLogger.debug(msg, context),\n * warn: (msg, context) => myLogger.warn(msg, context),\n * error: (msg, context) => {\n * myLogger.error(msg, context);\n * Sentry.captureMessage(msg, { level: 'error', extra: context });\n * },\n * });\n * ```\n *\n * @example\n * ```ts\n * // Disable all logging\n * setLogger({\n * debug: () => {},\n * warn: () => {},\n * error: () => {},\n * });\n * ```\n */\nexport function setLogger(customLogger: Logger): void {\n currentLogger = customLogger;\n}\n\n/**\n * Reset the logger to the default implementation.\n */\nexport function resetLogger(): void {\n currentLogger = defaultLogger;\n}\n","import PocketBase from \"pocketbase\";\nimport type { RecordSubscription } from \"pocketbase\";\nimport {\n createCollection as createTanStackCollection,\n type Collection,\n type LoadSubsetOptions,\n} from \"@tanstack/react-db\";\nimport { queryCollectionOptions, type QueryCollectionUtils } from \"@tanstack/query-db-collection\";\nimport { QueryClient } from \"@tanstack/react-query\";\nimport { convertToPocketBaseFilter, convertToPocketBaseSort } from \"./pocketbase-query-converter\";\nimport type {\n SchemaDeclaration,\n CreateCollectionOptions,\n ExtractRecordType,\n ExpandTargetCollection,\n BaseRecord,\n} from \"./types\";\nimport { logger } from \"./logger\";\n\nexport type { SchemaDeclaration, CreateCollectionOptions, BaseRecord } from \"./types\";\n\n/**\n * Extended LoadSubsetOptions that includes PocketBase-specific expand parameter.\n * @internal\n */\ntype ExtendedLoadSubsetOptions = LoadSubsetOptions & {\n pbExpand?: string;\n};\n\n/**\n * Compute the record type with expand property when expand option is configured.\n * @internal\n */\ntype WithExpandFromConfig<Schema extends SchemaDeclaration, C extends keyof Schema, Opts> = Opts extends {\n expand: infer E;\n}\n ? ExtractRecordType<Schema, C> & {\n expand?: {\n [K in keyof E]: K extends keyof import(\"./types\").ExtractRelations<Schema, C>\n ? import(\"./types\").ExtractRelations<Schema, C>[K] extends Array<infer U>\n ? U[]\n : import(\"./types\").ExtractRelations<Schema, C>[K]\n : never;\n };\n }\n : ExtractRecordType<Schema, C>;\n\n/**\n * Subscription helpers added to collection instances.\n * @internal\n */\ninterface CollectionSubscriptionHelpers {\n /** The PocketBase collection name */\n collectionName: string;\n /** Wait for subscription to be established (useful in tests) */\n waitForSubscription: (timeout?: number) => Promise<void>;\n /** Check if collection has an active subscription */\n isSubscribed: () => boolean;\n}\n\n/**\n * Inferred collection type from config options.\n * @internal\n */\ntype InferCollectionType<\n Schema extends SchemaDeclaration,\n C extends keyof Schema,\n Opts extends CreateCollectionOptions<Schema, C>,\n> = Collection<\n WithExpandFromConfig<Schema, C, Opts>,\n string | number,\n // TUtils - QueryCollectionUtils from TanStack Query DB Collection\n QueryCollectionUtils<WithExpandFromConfig<Schema, C, Opts>, string | number, WithExpandFromConfig<Schema, C, Opts>>,\n // TSchema - we don't use StandardSchema validation\n never,\n Opts extends {\n omitOnInsert: infer O extends readonly import(\"./types\").OmittableFields<ExtractRecordType<Schema, C>>[];\n }\n ? import(\"./types\").ComputeInsertType<ExtractRecordType<Schema, C>, O>\n : ExtractRecordType<Schema, C>\n> &\n CollectionSubscriptionHelpers;\n\n/**\n * Creates a type-safe TanStack DB collection backed by PocketBase.\n * Use this when you need fine-grained control or need to create collections with dependencies.\n *\n * @param pb - PocketBase client instance\n * @param queryClient - TanStack Query client\n * @returns A curried function that takes collection name and options\n *\n * @example\n * Basic usage:\n * ```ts\n * const booksCollection = createCollection<Schema>(pb, queryClient)('books', {});\n *\n * // Use directly\n * const books = await booksCollection.getFullList();\n * ```\n *\n * @example\n * With auto-expand relations:\n * ```ts\n * const authorsCollection = createCollection<Schema>(pb, queryClient)('authors', {});\n * const booksCollection = createCollection<Schema>(pb, queryClient)('books', {\n * expand: {\n * author: authorsCollection // Always expand, auto-upsert into authorsCollection\n * }\n * });\n *\n * // Expand is automatic - no .expand() call needed\n * const { data } = useLiveQuery((q) => q.from({ books: booksCollection }));\n * // data[0].expand.author is typed and populated\n * ```\n */\nexport function createCollection<Schema extends SchemaDeclaration>(pb: PocketBase, queryClient: QueryClient) {\n return <\n C extends keyof Schema & string,\n Opts extends CreateCollectionOptions<Schema, C> = CreateCollectionOptions<Schema, C>,\n >(\n collectionName: C,\n options?: Opts,\n ): InferCollectionType<Schema, C, Opts> => {\n type RecordType = ExtractRecordType<Schema, C>;\n const expandStores = options?.expand as Record<string, ExpandTargetCollection> | undefined;\n const expandString = expandStores ? Object.keys(expandStores).sort().join(\",\") : undefined;\n\n const ignoreAutoCancellation = options?.ignoreAutoCancellation ?? true;\n\n async function fetchRecords(loadOptions?: ExtendedLoadSubsetOptions): Promise<RecordType[]> {\n const filter = convertToPocketBaseFilter(loadOptions?.where);\n const sort = convertToPocketBaseSort(loadOptions?.orderBy);\n const limit = loadOptions?.limit;\n\n let items: RecordType[];\n try {\n if (limit) {\n // Use getList when limit is specified to avoid fetching all records\n const result = await pb.collection(collectionName).getList(1, limit, {\n filter,\n sort,\n skipTotal: true, // Optimize by skipping total count\n expand: expandString,\n });\n items = result.items as unknown as RecordType[];\n } else {\n // Use getFullList to fetch all records with automatic pagination\n items = (await pb.collection(collectionName).getFullList({\n filter,\n sort,\n expand: expandString,\n })) as unknown as RecordType[];\n }\n } catch (error) {\n if (ignoreAutoCancellation && error instanceof Error && error.message.includes(\"autocancelled\")) {\n return queryClient.getQueryData<RecordType[]>([collectionName]) ?? [];\n }\n throw error;\n }\n\n if (expandStores) {\n for (const record of items) {\n const expandData = (record as RecordType & { expand?: Record<string, object | object[]> }).expand;\n if (!expandData) continue;\n\n for (const [key, value] of Object.entries(expandData)) {\n const targetStore = expandStores[key];\n if (!targetStore.utils) continue;\n if (!targetStore.isReady()) {\n if (targetStore.config?.syncMode === \"on-demand\") {\n await targetStore._sync.startSync();\n } else {\n logger.warn(`not syncing ${key} on ${collectionName} because store is not yet ready`);\n continue;\n }\n }\n const values = Array.isArray(value) ? value : [value];\n targetStore.utils.writeUpsert(values);\n }\n }\n }\n\n return items;\n }\n\n const collectionOptions = queryCollectionOptions({\n ...options?.collectionOptions,\n queryClient,\n queryKey: [collectionName],\n syncMode: options?.syncMode ?? \"eager\",\n queryFn: async (ctx): Promise<RecordType[]> => {\n return fetchRecords(ctx.meta?.loadSubsetOptions as ExtendedLoadSubsetOptions | undefined);\n },\n getKey: (item: RecordType) => {\n const record = item as any;\n if (!record || typeof record !== \"object\" || !(\"id\" in record)) {\n throw new Error(\n `Record in collection '${collectionName}' is missing required 'id' field. Received: ${JSON.stringify(item)}`,\n );\n }\n return record.id;\n },\n onInsert:\n options?.onInsert === false\n ? undefined\n : (options?.onInsert ??\n (async ({ transaction }) => {\n await Promise.all(\n transaction.mutations.map(async (mutation) => {\n const {\n created,\n updated,\n collectionId,\n collectionName: _,\n ...data\n } = mutation.modified as unknown as Record<string, unknown>;\n await pb.collection(collectionName).create(data);\n }),\n );\n })),\n onUpdate:\n options?.onUpdate === false\n ? undefined\n : (options?.onUpdate ??\n (async ({ transaction }) => {\n await Promise.all(\n transaction.mutations.map(async (mutation) => {\n const recordWithId = mutation.original as { id: string };\n await pb.collection(collectionName).update(recordWithId.id, mutation.changes);\n }),\n );\n })),\n onDelete:\n options?.onDelete === false\n ? undefined\n : (options?.onDelete ??\n (async ({ transaction }) => {\n await Promise.all(\n transaction.mutations.map(async (mutation) => {\n const recordWithId = mutation.original as { id: string };\n await pb.collection(collectionName).delete(recordWithId.id);\n }),\n );\n })),\n });\n\n const collection = createTanStackCollection(collectionOptions);\n\n // Real-time subscription state\n let unsubscribeFn: (() => Promise<void>) | null = null;\n let isSubscribed = false;\n let subscriptionPromise: Promise<void> | null = null;\n let subscriptionResolve: (() => void) | null = null;\n\n // Handle real-time events from PocketBase\n const handleRealtimeEvent = (event: RecordSubscription<RecordType>) => {\n if (!collection.utils) return;\n\n collection.utils.writeBatch(() => {\n switch (event.action) {\n case \"create\":\n collection.utils.writeInsert(event.record);\n break;\n case \"update\":\n collection.utils.writeUpsert(event.record);\n break;\n case \"delete\":\n if (event.record && \"id\" in event.record) {\n collection.utils.writeDelete((event.record as { id: string }).id);\n }\n break;\n }\n });\n };\n\n // Start PocketBase real-time subscription\n const startSubscription = async () => {\n if (isSubscribed) return;\n\n // Create promise before starting so waiters can await it\n if (!subscriptionPromise) {\n subscriptionPromise = new Promise<void>((resolve) => {\n subscriptionResolve = resolve;\n });\n }\n\n try {\n unsubscribeFn = await pb.collection(collectionName).subscribe(\"*\", handleRealtimeEvent);\n isSubscribed = true;\n logger.debug(\"Subscription started\", { collectionName });\n // Resolve the promise to notify waiters\n if (subscriptionResolve) {\n subscriptionResolve();\n }\n } catch (error) {\n logger.error(\"Failed to start subscription\", { collectionName, error });\n }\n };\n\n // Stop PocketBase real-time subscription\n const stopSubscription = async () => {\n if (!isSubscribed || !unsubscribeFn) return;\n\n try {\n await unsubscribeFn();\n unsubscribeFn = null;\n isSubscribed = false;\n // Reset promise for next subscription cycle\n subscriptionPromise = null;\n subscriptionResolve = null;\n logger.debug(\"Subscription stopped\", { collectionName });\n } catch (error) {\n logger.debug(\"Unsubscribe failed (expected if connection closed)\", { collectionName, error });\n }\n };\n\n // Wait for subscription to be established (for testing)\n const waitForSubscription = async (timeout = 5000): Promise<void> => {\n if (isSubscribed) return;\n\n if (!subscriptionPromise) {\n // No subscription in progress, wait for one to start\n await new Promise<void>((resolve) => {\n const checkInterval = setInterval(() => {\n if (subscriptionPromise) {\n clearInterval(checkInterval);\n resolve();\n }\n }, 10);\n setTimeout(() => {\n clearInterval(checkInterval);\n resolve();\n }, timeout);\n });\n }\n\n if (subscriptionPromise) {\n await Promise.race([\n subscriptionPromise,\n new Promise<void>((_, reject) =>\n setTimeout(() => reject(new Error(\"Subscription timeout\")), timeout),\n ),\n ]);\n }\n };\n\n // Manage subscription based on collection subscriber count\n collection.on(\"subscribers:change\", (event: { subscriberCount: number; previousSubscriberCount: number }) => {\n const newCount = event.subscriberCount;\n const previousCount = event.previousSubscriberCount;\n\n if (newCount > 0 && previousCount === 0) {\n // First subscriber - start real-time subscription\n startSubscription().catch(() => {});\n } else if (newCount === 0 && previousCount > 0) {\n // Last subscriber removed - stop real-time subscription\n stopSubscription().catch(() => {});\n }\n });\n\n // Add collectionName and subscription helpers\n Object.assign(collection, {\n collectionName,\n waitForSubscription,\n isSubscribed: () => isSubscribed,\n });\n\n return collection as any;\n };\n}\n","import React, { createContext, useContext, type ReactNode } from 'react';\n\n/**\n * UseStore hook type for variadic collection access.\n * @internal\n */\ntype UseStoreFn<CollectionsMap> = <K extends (keyof CollectionsMap)[]>(\n ...keys: K\n) => { [I in keyof K]: K[I] extends keyof CollectionsMap ? CollectionsMap[K[I]] : never };\n\n/**\n * Return type for createReactProvider function.\n */\nexport interface ReactProviderResult<CollectionsMap> {\n /**\n * React Context Provider component.\n * Wrap your app with this provider to make collections available to useStore.\n */\n Provider: React.FC<{ children: ReactNode }>;\n\n /**\n * Hook to access collections from the provider.\n * Uses variadic arguments for clean syntax with automatic type inference.\n *\n * @example\n * ```tsx\n * // Single collection\n * const [books] = useStore('books');\n *\n * // Multiple collections (no 'as const' needed!)\n * const [books, authors] = useStore('books', 'authors');\n * ```\n */\n useStore: UseStoreFn<CollectionsMap>;\n}\n\n/**\n * Creates a React Provider and useStore hook from a collections map.\n *\n * @param collections - Map of collection keys to Collection instances\n * @returns Object containing Provider component and useStore hook\n *\n * @example\n * Basic usage:\n * ```tsx\n * import { createCollection, createReactProvider } from 'pbtsdb';\n * import { useLiveQuery } from '@tanstack/react-db';\n *\n * // Step 1: Create collections\n * const c = createCollection<Schema>(pb, queryClient);\n * const collections = {\n * books: c('books', {}),\n * authors: c('authors', {}),\n * };\n *\n * // Step 2: Wrap for React\n * const { Provider, useStore } = createReactProvider(collections);\n *\n * // Step 3: Wrap your app\n * function App() {\n * return (\n * <QueryClientProvider client={queryClient}>\n * <Provider>\n * <BooksList />\n * </Provider>\n * </QueryClientProvider>\n * );\n * }\n *\n * // Step 4: Use in components\n * function BooksList() {\n * const [books] = useStore('books');\n * const { data } = useLiveQuery((q) => q.from({ books }));\n * return <div>{data?.map(book => <p key={book.id}>{book.title}</p>)}</div>;\n * }\n * ```\n *\n * @example\n * Variadic useStore pattern:\n * ```tsx\n * function BooksWithAuthors() {\n * const [books, authors] = useStore('books', 'authors');\n *\n * const { data } = useLiveQuery((q) =>\n * q.from({ book: books })\n * .join(\n * { author: authors },\n * ({ book, author }) => eq(book.author, author.id),\n * 'left'\n * )\n * );\n *\n * return <div>...</div>;\n * }\n * ```\n *\n * @example\n * With auto-expand collections:\n * ```tsx\n * const c = createCollection<Schema>(pb, queryClient);\n * const authors = c('authors', {});\n * const books = c('books', {\n * expand: {\n * author: authors\n * }\n * });\n *\n * const { Provider, useStore } = createReactProvider({ authors, books });\n *\n * function BooksWithExpandedAuthors() {\n * const [books] = useStore('books');\n * const { data } = useLiveQuery((q) => q.from({ books }));\n *\n * return (\n * <ul>\n * {data?.map(book => (\n * <li key={book.id}>\n * {book.title} by {book.expand?.author?.name}\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function createReactProvider<CollectionsMap extends Record<string, any>>(\n collections: CollectionsMap\n): ReactProviderResult<CollectionsMap> {\n const Context = createContext<CollectionsMap | null>(null);\n\n const Provider: React.FC<{ children: ReactNode }> = ({ children }) => (\n <Context.Provider value={collections}>{children}</Context.Provider>\n );\n\n function useStore<K extends (keyof CollectionsMap)[]>(\n ...keys: K\n ): { [I in keyof K]: K[I] extends keyof CollectionsMap ? CollectionsMap[K[I]] : never } {\n const context = useContext(Context);\n\n if (!context) {\n throw new Error('useStore must be used within the Provider returned by createReactProvider');\n }\n\n return keys.map((key) => {\n if (!(key in context)) {\n throw new Error(`Collection \"${String(key)}\" not found in collections`);\n }\n return context[key];\n }) as { [I in keyof K]: K[I] extends keyof CollectionsMap ? CollectionsMap[K[I]] : never };\n }\n\n return {\n Provider,\n useStore: useStore as UseStoreFn<CollectionsMap>,\n };\n}\n","/**\n * Generates a new PocketBase-compatible record ID.\n * Returns a 15-character alphanumeric string (lowercase letters and numbers).\n *\n * PocketBase uses 15-character IDs for records, formatted as lowercase alphanumeric.\n *\n * @returns A 15-character alphanumeric string suitable for use as a PocketBase record ID\n *\n * @example\n * ```ts\n * const id = newRecordId(); // \"a1b2c3d4e5f6g7h\"\n * ```\n */\nexport function newRecordId(): string {\n const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n for (let i = 0; i < 15; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbtsdb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Type-safe PocketBase integration with TanStack Query and TanStack DB",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pocketbase",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"lint": "biome check .",
|
|
48
48
|
"lint:fix": "biome check . --write",
|
|
49
49
|
"typecheck": "tsc --noEmit --skipLibCheck",
|
|
50
|
-
"test": "start-server-and-test test:server http://127.0.0.1:8210/api/health 'vitest $TEST'",
|
|
50
|
+
"test": "NODE_OPTIONS='--localstorage-file=.localstorage-test' start-server-and-test test:server http://127.0.0.1:8210/api/health 'vitest $TEST'",
|
|
51
51
|
"test:run": "vitest",
|
|
52
52
|
"test:server": "./scripts/start-test-server.sh",
|
|
53
53
|
"test:server:migrate": "pocketbase migrate --dir ./pb_data"
|
|
@@ -61,24 +61,24 @@
|
|
|
61
61
|
"react-dom": ">=18.0.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@tanstack/query-db-collection": ">=1.0.
|
|
65
|
-
"@tanstack/react-db": ">=0.1.
|
|
66
|
-
"@tanstack/react-query": ">=5.90.
|
|
67
|
-
"@testing-library/react": ">=16.3.
|
|
68
|
-
"@types/node": ">=
|
|
69
|
-
"@types/react": ">=19.2.
|
|
64
|
+
"@tanstack/query-db-collection": ">=1.0.31",
|
|
65
|
+
"@tanstack/react-db": ">=0.1.78",
|
|
66
|
+
"@tanstack/react-query": ">=5.90.20",
|
|
67
|
+
"@testing-library/react": ">=16.3.2",
|
|
68
|
+
"@types/node": ">=25.0.10",
|
|
69
|
+
"@types/react": ">=19.2.10",
|
|
70
70
|
"biome": ">=0.3.3",
|
|
71
71
|
"dotenv": ">=17.2.3",
|
|
72
72
|
"eventsource": ">=4.1.0",
|
|
73
|
-
"jsdom": ">=27.
|
|
73
|
+
"jsdom": ">=27.4.0",
|
|
74
74
|
"npm-run-all": ">=4.1.5",
|
|
75
|
-
"pocketbase": ">=0.26.
|
|
76
|
-
"react": ">=19.2.
|
|
77
|
-
"react-dom": ">=19.2.
|
|
75
|
+
"pocketbase": ">=0.26.7",
|
|
76
|
+
"react": ">=19.2.4",
|
|
77
|
+
"react-dom": ">=19.2.4",
|
|
78
78
|
"start-server-and-test": ">=2.1.3",
|
|
79
79
|
"tsup": "^8.5.1",
|
|
80
80
|
"tsx": ">=4.21.0",
|
|
81
81
|
"typescript": ">=5.9.3",
|
|
82
|
-
"vitest": ">=4.0.
|
|
82
|
+
"vitest": ">=4.0.18"
|
|
83
83
|
}
|
|
84
84
|
}
|