pbtsdb 0.4.0 → 0.5.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 +14 -0
- package/dist/{chunk-B3RODB7I.js → chunk-UYH4FKXY.js} +6 -2
- package/dist/chunk-UYH4FKXY.js.map +1 -0
- package/dist/core.d.ts +20 -0
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-B3RODB7I.js.map +0 -1
package/README.md
CHANGED
|
@@ -268,6 +268,20 @@ const { data } = useLiveQuery((q) =>
|
|
|
268
268
|
- **Shared:** Multiple components using the same collection share one subscription
|
|
269
269
|
- **No manual control needed:** The collection handles all subscription management internally
|
|
270
270
|
|
|
271
|
+
### Mutations and Refetch
|
|
272
|
+
|
|
273
|
+
By default, pbtsdb does **not** refetch the entire collection after a successful insert, update, or delete. The realtime subscription delivers server-confirmed rows — including server-assigned fields like `id`, `created`, `updated`, and any values rewritten by PocketBase hooks — and TanStack DB's optimistic write keeps the UI consistent in the meantime. The post-mutation refetch is therefore redundant.
|
|
274
|
+
|
|
275
|
+
Set `refetchOnMutation: true` to opt back into the previous behavior — for example, when realtime is unreliable in your environment, or when a server-side hook produces a field you must read synchronously after the mutation resolves:
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
const collection = c('books', {
|
|
279
|
+
refetchOnMutation: true,
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The option only affects the built-in default handlers. If you supply your own `onInsert`, `onUpdate`, or `onDelete`, you control its return value yourself — return `{ refetch: false }` (or omit a return) to skip the refetch, return `{ refetch: true }` to force one.
|
|
284
|
+
|
|
271
285
|
### Type Safety
|
|
272
286
|
|
|
273
287
|
Full TypeScript support with compile-time type checking:
|
|
@@ -137,6 +137,7 @@ function createCollection(pb, queryClient) {
|
|
|
137
137
|
const expandStores = options?.expand;
|
|
138
138
|
const expandString = expandStores ? Object.keys(expandStores).sort().join(",") : void 0;
|
|
139
139
|
const ignoreAutoCancellation = options?.ignoreAutoCancellation ?? true;
|
|
140
|
+
const refetchOnMutation = options?.refetchOnMutation ?? false;
|
|
140
141
|
async function fetchRecords(loadOptions) {
|
|
141
142
|
const filter = convertToPocketBaseFilter(loadOptions?.where);
|
|
142
143
|
const sort = convertToPocketBaseSort(loadOptions?.orderBy);
|
|
@@ -217,6 +218,7 @@ function createCollection(pb, queryClient) {
|
|
|
217
218
|
await pb.collection(collectionName).create(data);
|
|
218
219
|
})
|
|
219
220
|
);
|
|
221
|
+
return { refetch: refetchOnMutation };
|
|
220
222
|
}),
|
|
221
223
|
onUpdate: options?.onUpdate === false ? void 0 : options?.onUpdate ?? (async ({ transaction }) => {
|
|
222
224
|
await Promise.all(
|
|
@@ -225,6 +227,7 @@ function createCollection(pb, queryClient) {
|
|
|
225
227
|
await pb.collection(collectionName).update(recordWithId.id, mutation.changes);
|
|
226
228
|
})
|
|
227
229
|
);
|
|
230
|
+
return { refetch: refetchOnMutation };
|
|
228
231
|
}),
|
|
229
232
|
onDelete: options?.onDelete === false ? void 0 : options?.onDelete ?? (async ({ transaction }) => {
|
|
230
233
|
await Promise.all(
|
|
@@ -233,6 +236,7 @@ function createCollection(pb, queryClient) {
|
|
|
233
236
|
await pb.collection(collectionName).delete(recordWithId.id);
|
|
234
237
|
})
|
|
235
238
|
);
|
|
239
|
+
return { refetch: refetchOnMutation };
|
|
236
240
|
})
|
|
237
241
|
});
|
|
238
242
|
const collection = createCollection$1(collectionOptions);
|
|
@@ -345,5 +349,5 @@ function newRecordId() {
|
|
|
345
349
|
}
|
|
346
350
|
|
|
347
351
|
export { createCollection, newRecordId, resetLogger, setLogger };
|
|
348
|
-
//# sourceMappingURL=chunk-
|
|
349
|
-
//# sourceMappingURL=chunk-
|
|
352
|
+
//# sourceMappingURL=chunk-UYH4FKXY.js.map
|
|
353
|
+
//# sourceMappingURL=chunk-UYH4FKXY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pocketbase-query-converter.ts","../src/logger.ts","../src/collection.ts","../src/util.ts"],"names":["createTanStackCollection"],"mappings":"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","file":"chunk-UYH4FKXY.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/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 const refetchOnMutation = options?.refetchOnMutation ?? false;\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 return { refetch: refetchOnMutation };\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 return { refetch: refetchOnMutation };\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 return { refetch: refetchOnMutation };\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 * 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/dist/core.d.ts
CHANGED
|
@@ -286,6 +286,26 @@ interface CreateCollectionOptions<Schema extends SchemaDeclaration, CollectionNa
|
|
|
286
286
|
* ```
|
|
287
287
|
*/
|
|
288
288
|
onDelete?: DeleteMutationFn<ExtractRecordType<Schema, CollectionName>> | false;
|
|
289
|
+
/**
|
|
290
|
+
* If true, refetch the entire collection after a successful insert,
|
|
291
|
+
* update, or delete. Defaults to false: pbtsdb relies on its PocketBase
|
|
292
|
+
* realtime subscription to deliver server-confirmed rows. Set true if
|
|
293
|
+
* you do not trust realtime to reconcile in time (e.g. flaky socket,
|
|
294
|
+
* server-side hooks producing fields you must read synchronously).
|
|
295
|
+
*
|
|
296
|
+
* Only affects the built-in default handlers. If you supply your own
|
|
297
|
+
* onInsert/onUpdate/onDelete, you control the return value yourself.
|
|
298
|
+
*
|
|
299
|
+
* @default false
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```ts
|
|
303
|
+
* const collection = createCollection<Schema>(pb, queryClient)('books', {
|
|
304
|
+
* refetchOnMutation: true,
|
|
305
|
+
* });
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
refetchOnMutation?: boolean;
|
|
289
309
|
/**
|
|
290
310
|
* Sync mode for the collection. Controls when and how data is fetched from PocketBase.
|
|
291
311
|
*
|
package/dist/core.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { BTreeIndex, BasicIndex, ReverseIndex, createCollection, createEffect, newRecordId, resetLogger, setLogger, toArray } from './chunk-
|
|
1
|
+
export { BTreeIndex, BasicIndex, ReverseIndex, createCollection, createEffect, newRecordId, resetLogger, setLogger, toArray } from './chunk-UYH4FKXY.js';
|
|
2
2
|
//# sourceMappingURL=core.js.map
|
|
3
3
|
//# sourceMappingURL=core.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { BTreeIndex, BasicIndex, ReverseIndex, createCollection, createEffect, newRecordId, resetLogger, setLogger, toArray } from './chunk-
|
|
1
|
+
export { BTreeIndex, BasicIndex, ReverseIndex, createCollection, createEffect, newRecordId, resetLogger, setLogger, toArray } from './chunk-UYH4FKXY.js';
|
|
2
2
|
import { createContext, useContext } from 'react';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pocketbase-query-converter.ts","../src/logger.ts","../src/collection.ts","../src/util.ts"],"names":["createTanStackCollection"],"mappings":"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","file":"chunk-B3RODB7I.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/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","/**\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"]}
|