pbtsdb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1035 -0
- package/dist/index.d.ts +614 -0
- package/dist/index.js +545 -0
- package/dist/index.js.map +1 -0
- package/llms.txt +91 -0
- package/package.json +84 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
import PocketBase, { UnsubscribeFunc } from 'pocketbase';
|
|
2
|
+
import { Collection } from '@tanstack/db';
|
|
3
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
+
import { ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Schema declaration for type-safe collection management.
|
|
9
|
+
* Define your PocketBase collections with their record types and relations.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* interface MySchema extends SchemaDeclaration {
|
|
14
|
+
* users: {
|
|
15
|
+
* type: UserRecord;
|
|
16
|
+
* relations: {
|
|
17
|
+
* org: OrgRecord;
|
|
18
|
+
* };
|
|
19
|
+
* };
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
interface SchemaDeclaration {
|
|
24
|
+
[collectionName: string]: {
|
|
25
|
+
type: object;
|
|
26
|
+
relations?: {
|
|
27
|
+
[fieldName: string]: object | object[];
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* PocketBase real-time event structure.
|
|
33
|
+
* Matches RecordSubscription from the PocketBase SDK.
|
|
34
|
+
*/
|
|
35
|
+
interface RealtimeEvent<T extends object = object> {
|
|
36
|
+
action: string;
|
|
37
|
+
record: T;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Internal state tracking for subscription management.
|
|
41
|
+
* Includes reconnection logic and record-specific subscriptions.
|
|
42
|
+
*/
|
|
43
|
+
interface SubscriptionState {
|
|
44
|
+
unsubscribe: UnsubscribeFunc;
|
|
45
|
+
recordId?: string;
|
|
46
|
+
reconnectAttempts: number;
|
|
47
|
+
isReconnecting: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Enhanced collection interface with subscription management capabilities.
|
|
51
|
+
* Provides methods to control real-time updates from PocketBase.
|
|
52
|
+
*/
|
|
53
|
+
interface SubscribableCollection<T extends object = object> {
|
|
54
|
+
/**
|
|
55
|
+
* Subscribe to real-time updates for this collection.
|
|
56
|
+
* @param recordId - Optional: Subscribe to a specific record, or omit for collection-wide updates
|
|
57
|
+
*/
|
|
58
|
+
subscribe: (recordId?: string) => Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Unsubscribe from real-time updates.
|
|
61
|
+
* @param recordId - Optional: Unsubscribe from a specific record, or omit for collection-wide
|
|
62
|
+
*/
|
|
63
|
+
unsubscribe: (recordId?: string) => void;
|
|
64
|
+
/**
|
|
65
|
+
* Unsubscribe from all subscriptions for this collection.
|
|
66
|
+
*/
|
|
67
|
+
unsubscribeAll: () => void;
|
|
68
|
+
/**
|
|
69
|
+
* Check if currently subscribed to updates.
|
|
70
|
+
* @param recordId - Optional: Check a specific record subscription, or omit for collection-wide
|
|
71
|
+
*/
|
|
72
|
+
isSubscribed: (recordId?: string) => boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Wait for a subscription to be fully established (useful for testing).
|
|
75
|
+
* @param recordId - Optional record ID
|
|
76
|
+
* @param timeoutMs - Timeout in milliseconds (default: 5000)
|
|
77
|
+
*/
|
|
78
|
+
waitForSubscription: (recordId?: string, timeoutMs?: number) => Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Join helper for type-safe TanStack DB joins.
|
|
82
|
+
* Provides access to pre-configured relation collections.
|
|
83
|
+
*/
|
|
84
|
+
interface JoinHelper<Schema extends SchemaDeclaration, CollectionName extends keyof Schema, RecordType extends object> {
|
|
85
|
+
/**
|
|
86
|
+
* Get a pre-configured collection for joining a relation field.
|
|
87
|
+
* This returns the related collection that can be used with TanStack DB's .join() method.
|
|
88
|
+
*
|
|
89
|
+
* @param fieldName - The relation field name to join
|
|
90
|
+
* @returns The collection for the related entity, or undefined if not configured
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* const jobsCollection = factory.create('jobs', {
|
|
95
|
+
* relations: {
|
|
96
|
+
* customer: customersCollection,
|
|
97
|
+
* address: addressesCollection
|
|
98
|
+
* }
|
|
99
|
+
* });
|
|
100
|
+
*
|
|
101
|
+
* // Use with TanStack DB joins
|
|
102
|
+
* const query = q.from({ job: jobsCollection })
|
|
103
|
+
* .join(
|
|
104
|
+
* { customer: jobsCollection.relations.customer },
|
|
105
|
+
* ({ job, customer }) => eq(job.customer, customer.id),
|
|
106
|
+
* 'left'
|
|
107
|
+
* );
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
relations: RelationsConfig<Schema, CollectionName>;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Extracts the record type from a schema collection.
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
type ExtractRecordType<Schema extends SchemaDeclaration, CollectionName extends keyof Schema> = Schema[CollectionName]['type'];
|
|
117
|
+
/**
|
|
118
|
+
* Extracts the relations object from a schema collection.
|
|
119
|
+
* Returns never if the collection has no relations defined.
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
type ExtractRelations<Schema extends SchemaDeclaration, CollectionName extends keyof Schema> = Schema[CollectionName] extends {
|
|
123
|
+
relations: infer R;
|
|
124
|
+
} ? R : never;
|
|
125
|
+
/**
|
|
126
|
+
* Extracts expandable field names from a schema collection.
|
|
127
|
+
* Returns the union of all relation field names that can be expanded.
|
|
128
|
+
* @internal
|
|
129
|
+
*/
|
|
130
|
+
type ExpandableFields<Schema extends SchemaDeclaration, CollectionName extends keyof Schema> = ExtractRelations<Schema, CollectionName> extends never ? never : keyof ExtractRelations<Schema, CollectionName> & string;
|
|
131
|
+
/**
|
|
132
|
+
* Parses comma-separated relation field names into a union type.
|
|
133
|
+
* Recursively processes "field1,field2,field3" into "field1" | "field2" | "field3".
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ParseExpandFields<"customer,address"> => "customer" | "address"
|
|
137
|
+
* @internal
|
|
138
|
+
*/
|
|
139
|
+
type ParseExpandFields<T extends string> = T extends `${infer Field},${infer Rest}` ? Field | ParseExpandFields<Rest> : T;
|
|
140
|
+
/**
|
|
141
|
+
* Builds the expand object type based on field names.
|
|
142
|
+
* If expand fields are provided, adds an optional `expand` property with properly typed relations.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* // Without expand
|
|
147
|
+
* WithExpand<Schema, 'jobs', undefined> => JobRecord
|
|
148
|
+
*
|
|
149
|
+
* // With expand
|
|
150
|
+
* WithExpand<Schema, 'jobs', 'customer'> => JobRecord & {
|
|
151
|
+
* expand?: { customer?: CustomerRecord }
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
type WithExpand<Schema extends SchemaDeclaration, CollectionName extends keyof Schema, ExpandFields extends string | undefined> = ExpandFields extends string ? ExtractRecordType<Schema, CollectionName> & {
|
|
156
|
+
expand?: {
|
|
157
|
+
[K in ParseExpandFields<ExpandFields>]?: K extends keyof ExtractRelations<Schema, CollectionName> ? ExtractRelations<Schema, CollectionName>[K] extends Array<infer U> ? U[] : ExtractRelations<Schema, CollectionName>[K] : never;
|
|
158
|
+
};
|
|
159
|
+
} : ExtractRecordType<Schema, CollectionName>;
|
|
160
|
+
/**
|
|
161
|
+
* Removes undefined from a union type.
|
|
162
|
+
* Used to unwrap optional relation types.
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* NonNullable<Customer | undefined> => Customer
|
|
166
|
+
* @internal
|
|
167
|
+
*/
|
|
168
|
+
type NonNullable<T> = T extends (infer U) | undefined ? U : T;
|
|
169
|
+
/**
|
|
170
|
+
* Converts a schema relation type to its corresponding Collection type.
|
|
171
|
+
* Handles both single relations (T) and array relations (T[]).
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* RelationAsCollection<Customer> => Collection<Customer>
|
|
175
|
+
* RelationAsCollection<Customer[]> => Collection<Customer>
|
|
176
|
+
* @internal
|
|
177
|
+
*/
|
|
178
|
+
type RelationAsCollection<T> = T extends Array<infer U> ? U extends object ? Collection<U> : Collection<object> : T extends object ? Collection<T> : Collection<object>;
|
|
179
|
+
/**
|
|
180
|
+
* Configuration for relations - maps field names to their TanStack DB collections.
|
|
181
|
+
* Used to provide pre-configured collections for manual joins.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```ts
|
|
185
|
+
* const config: RelationsConfig<Schema, 'jobs'> = {
|
|
186
|
+
* customer: customersCollection,
|
|
187
|
+
* address: addressesCollection
|
|
188
|
+
* };
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
type RelationsConfig<Schema extends SchemaDeclaration, CollectionName extends keyof Schema> = ExtractRelations<Schema, CollectionName> extends never ? Record<string, never> : Partial<{
|
|
192
|
+
[K in keyof ExtractRelations<Schema, CollectionName>]: RelationAsCollection<NonNullable<ExtractRelations<Schema, CollectionName>[K]>>;
|
|
193
|
+
}>;
|
|
194
|
+
/**
|
|
195
|
+
* Options for creating a collection with optional expand and relations.
|
|
196
|
+
*/
|
|
197
|
+
interface CreateCollectionOptions<Schema extends SchemaDeclaration, CollectionName extends keyof Schema, Expand extends string | undefined = undefined> {
|
|
198
|
+
/**
|
|
199
|
+
* Pre-configured relation collections for manual TanStack DB joins.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```ts
|
|
203
|
+
* const jobsCollection = factory.create('jobs', {
|
|
204
|
+
* relations: {
|
|
205
|
+
* customer: customersCollection,
|
|
206
|
+
* address: addressesCollection
|
|
207
|
+
* }
|
|
208
|
+
* });
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
relations?: RelationsConfig<Schema, CollectionName>;
|
|
212
|
+
/**
|
|
213
|
+
* Relation fields to auto-expand from PocketBase.
|
|
214
|
+
* Can be a single field or comma-separated list.
|
|
215
|
+
* For best type inference, use `as const` when providing comma-separated strings.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* ```ts
|
|
219
|
+
* // Single relation
|
|
220
|
+
* const jobsCollection = factory.create('jobs', {
|
|
221
|
+
* expand: 'customer' // Type inference works automatically
|
|
222
|
+
* });
|
|
223
|
+
*
|
|
224
|
+
* // Multiple relations with type inference
|
|
225
|
+
* const jobsCollection = factory.create('jobs', {
|
|
226
|
+
* expand: 'customer,address' as const // `as const` gives proper typing
|
|
227
|
+
* });
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
expand?: Expand;
|
|
231
|
+
/**
|
|
232
|
+
* Whether to automatically sync (fetch) data when the collection is created.
|
|
233
|
+
* Default: false (lazy - sync starts after first query becomes active).
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```ts
|
|
237
|
+
* // Lazy loading (default) - sync starts after query
|
|
238
|
+
* const jobsCollection = factory.create('jobs');
|
|
239
|
+
* // or explicitly:
|
|
240
|
+
* const jobsCollection = factory.create('jobs', { startSync: false });
|
|
241
|
+
*
|
|
242
|
+
* // Eager loading - sync starts immediately on creation
|
|
243
|
+
* const jobsCollection = factory.create('jobs', {
|
|
244
|
+
* startSync: true
|
|
245
|
+
* });
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
startSync?: boolean;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Map of collection names to TanStack DB Collection instances.
|
|
253
|
+
* Keys are user-defined strings, values are Collection instances.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* const stores = {
|
|
258
|
+
* jobs: jobsCollection,
|
|
259
|
+
* customers: customersCollection,
|
|
260
|
+
* addresses: addressesCollection
|
|
261
|
+
* };
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
type CollectionsMap = Record<string, Collection<any>>;
|
|
265
|
+
/**
|
|
266
|
+
* Props for the CollectionsProvider component.
|
|
267
|
+
*/
|
|
268
|
+
interface CollectionsProviderProps {
|
|
269
|
+
/** Map of collection name to Collection instance */
|
|
270
|
+
collections: CollectionsMap;
|
|
271
|
+
/** React children to render */
|
|
272
|
+
children: ReactNode;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Provider component that makes collections available to all child components.
|
|
276
|
+
* Wrap your app with this provider to use the useStore and useStores hooks.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```tsx
|
|
280
|
+
* const factory = new CollectionFactory<Schema>(pb, queryClient);
|
|
281
|
+
* const collections = {
|
|
282
|
+
* jobs: factory.create('jobs'),
|
|
283
|
+
* customers: factory.create('customers'),
|
|
284
|
+
* addresses: factory.create('addresses')
|
|
285
|
+
* };
|
|
286
|
+
*
|
|
287
|
+
* function App() {
|
|
288
|
+
* return (
|
|
289
|
+
* <CollectionsProvider collections={collections}>
|
|
290
|
+
* <YourApp />
|
|
291
|
+
* </CollectionsProvider>
|
|
292
|
+
* );
|
|
293
|
+
* }
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
declare function CollectionsProvider({ collections, children }: CollectionsProviderProps): react_jsx_runtime.JSX.Element;
|
|
297
|
+
/**
|
|
298
|
+
* Hook to access a single collection from the provider.
|
|
299
|
+
* Returns the Collection instance for the specified key.
|
|
300
|
+
*
|
|
301
|
+
* @template T - The record type for the collection
|
|
302
|
+
* @param key - The collection key as defined in the provider
|
|
303
|
+
* @returns The Collection instance
|
|
304
|
+
* @throws Error if used outside of CollectionsProvider or if key doesn't exist
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```tsx
|
|
308
|
+
* function JobsList() {
|
|
309
|
+
* const jobsCollection = useStore<JobsRecord>('jobs');
|
|
310
|
+
*
|
|
311
|
+
* const { data } = useLiveQuery((q) =>
|
|
312
|
+
* q.from({ jobs: jobsCollection })
|
|
313
|
+
* );
|
|
314
|
+
*
|
|
315
|
+
* return (
|
|
316
|
+
* <ul>
|
|
317
|
+
* {data?.map(job => <li key={job.id}>{job.name}</li>)}
|
|
318
|
+
* </ul>
|
|
319
|
+
* );
|
|
320
|
+
* }
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
declare function useStore<T extends object = object>(key: string): Collection<T>;
|
|
324
|
+
/**
|
|
325
|
+
* Hook to access multiple collections from the provider.
|
|
326
|
+
* Returns an array of Collection instances matching the order of the keys array.
|
|
327
|
+
*
|
|
328
|
+
* @template T - Tuple type of record types for each collection
|
|
329
|
+
* @param keys - Array of collection keys as defined in the provider
|
|
330
|
+
* @returns Array of Collection instances in the same order as keys
|
|
331
|
+
* @throws Error if used outside of CollectionsProvider or if any key doesn't exist
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```tsx
|
|
335
|
+
* function JobsWithCustomers() {
|
|
336
|
+
* const [jobsCollection, customersCollection] = useStores<
|
|
337
|
+
* [JobsRecord, CustomersRecord]
|
|
338
|
+
* >(['jobs', 'customers']);
|
|
339
|
+
*
|
|
340
|
+
* const { data } = useLiveQuery((q) =>
|
|
341
|
+
* q.from({ job: jobsCollection })
|
|
342
|
+
* .join(
|
|
343
|
+
* { customer: customersCollection },
|
|
344
|
+
* ({ job, customer }) => eq(job.customer, customer.id),
|
|
345
|
+
* 'left'
|
|
346
|
+
* )
|
|
347
|
+
* );
|
|
348
|
+
*
|
|
349
|
+
* return <div>...</div>;
|
|
350
|
+
* }
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
353
|
+
declare function useStores<T extends readonly object[]>(keys: readonly string[]): {
|
|
354
|
+
[K in keyof T]: Collection<T[K]>;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Factory for creating type-safe TanStack DB collections backed by PocketBase.
|
|
359
|
+
* Integrates real-time subscriptions with automatic synchronization.
|
|
360
|
+
*/
|
|
361
|
+
declare class CollectionFactory<Schema extends SchemaDeclaration, TMaxDepth extends 0 | 1 | 2 | 3 | 4 | 5 | 6 = 2> {
|
|
362
|
+
pocketbase: PocketBase;
|
|
363
|
+
queryClient: QueryClient;
|
|
364
|
+
private subscriptionManager;
|
|
365
|
+
constructor(pocketbase: PocketBase, queryClient: QueryClient);
|
|
366
|
+
/**
|
|
367
|
+
* Setup automatic subscription lifecycle management.
|
|
368
|
+
* Hooks into TanStack DB's subscriber events to manage real-time subscriptions.
|
|
369
|
+
*/
|
|
370
|
+
private setupSubscriptionLifecycle;
|
|
371
|
+
/**
|
|
372
|
+
* Create a TanStack DB collection from a PocketBase collection.
|
|
373
|
+
*
|
|
374
|
+
* Collections are lazy by default - they don't fetch data or subscribe until queried.
|
|
375
|
+
* Real-time subscriptions automatically start when the first query becomes active
|
|
376
|
+
* and stop when the last query unmounts (with a cleanup delay to prevent thrashing).
|
|
377
|
+
*
|
|
378
|
+
* @param collection - The name of the collection
|
|
379
|
+
* @param options - Optional configuration including relations and expand
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* Basic usage with automatic lifecycle management:
|
|
383
|
+
* ```ts
|
|
384
|
+
* const jobsCollection = factory.create('jobs');
|
|
385
|
+
*
|
|
386
|
+
* // In your component - subscription starts automatically
|
|
387
|
+
* const { data } = useLiveQuery((q) =>
|
|
388
|
+
* q.from({ jobs: jobsCollection })
|
|
389
|
+
* );
|
|
390
|
+
* // Subscription stops automatically when component unmounts
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* With query operators (filters, sorting):
|
|
395
|
+
* ```ts
|
|
396
|
+
* const jobsCollection = factory.create('jobs');
|
|
397
|
+
*
|
|
398
|
+
* // In your component:
|
|
399
|
+
* const { data } = useLiveQuery((q) =>
|
|
400
|
+
* q.from({ jobs: jobsCollection })
|
|
401
|
+
* .where(({ jobs }) => and(
|
|
402
|
+
* eq(jobs.status, 'ACTIVE'),
|
|
403
|
+
* gt(jobs.created, new Date('2025-01-01'))
|
|
404
|
+
* ))
|
|
405
|
+
* .orderBy(({ jobs }) => jobs.created, 'desc')
|
|
406
|
+
* );
|
|
407
|
+
* ```
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* With relation expansion:
|
|
411
|
+
* ```ts
|
|
412
|
+
* const jobsCollection = factory.create('jobs', {
|
|
413
|
+
* expand: 'customer,location'
|
|
414
|
+
* });
|
|
415
|
+
*
|
|
416
|
+
* // Expanded relations available in record.expand
|
|
417
|
+
* ```
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* With relations (for manual joins):
|
|
421
|
+
* ```ts
|
|
422
|
+
* const customersCollection = factory.create('customers');
|
|
423
|
+
* const jobsCollection = factory.create('jobs', {
|
|
424
|
+
* relations: { customer: customersCollection }
|
|
425
|
+
* });
|
|
426
|
+
*
|
|
427
|
+
* // In your component, manually build joins:
|
|
428
|
+
* const { data } = useLiveQuery((q) =>
|
|
429
|
+
* q.from({ job: jobsCollection })
|
|
430
|
+
* .join(
|
|
431
|
+
* { customer: customersCollection },
|
|
432
|
+
* ({ job, customer }) => eq(job.customer, customer.id),
|
|
433
|
+
* "left"
|
|
434
|
+
* )
|
|
435
|
+
* .select(({ job, customer }) => ({
|
|
436
|
+
* ...job,
|
|
437
|
+
* expand: {
|
|
438
|
+
* customer: customer ? { ...customer } : undefined
|
|
439
|
+
* }
|
|
440
|
+
* }))
|
|
441
|
+
* );
|
|
442
|
+
* ```
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* Manual subscription control (advanced):
|
|
446
|
+
* ```ts
|
|
447
|
+
* const jobsCollection = factory.create('jobs');
|
|
448
|
+
*
|
|
449
|
+
* // Manually subscribe to specific record (bypasses automatic lifecycle)
|
|
450
|
+
* await jobsCollection.subscribe('record_id_123');
|
|
451
|
+
*
|
|
452
|
+
* // Check subscription status
|
|
453
|
+
* const isSubbed = jobsCollection.isSubscribed('record_id_123');
|
|
454
|
+
*
|
|
455
|
+
* // Manually unsubscribe
|
|
456
|
+
* jobsCollection.unsubscribe('record_id_123');
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
create<C extends keyof Schema & string, E extends string | undefined = undefined>(collection: C, options?: CreateCollectionOptions<Schema, C, E>): Collection<WithExpand<Schema, C, E>> & SubscribableCollection<WithExpand<Schema, C, E>> & JoinHelper<Schema, C, WithExpand<Schema, C, E>>;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
declare const SUBSCRIPTION_CONFIG: {
|
|
463
|
+
readonly MAX_RECONNECT_ATTEMPTS: 5;
|
|
464
|
+
readonly BASE_RECONNECT_DELAY_MS: 1000;
|
|
465
|
+
readonly DEFAULT_WAIT_TIMEOUT_MS: 5000;
|
|
466
|
+
readonly CLEANUP_DELAY_MS: 5000;
|
|
467
|
+
};
|
|
468
|
+
/**
|
|
469
|
+
* Manages real-time subscriptions to PocketBase collections.
|
|
470
|
+
* Handles subscription lifecycle, reconnection with exponential backoff,
|
|
471
|
+
* and automatic synchronization with TanStack DB collections.
|
|
472
|
+
*
|
|
473
|
+
* Subscriptions are automatically managed based on TanStack DB's subscriber count:
|
|
474
|
+
* - Start subscribing when first query becomes active
|
|
475
|
+
* - Stop subscribing when last query becomes inactive (with cleanup delay)
|
|
476
|
+
*/
|
|
477
|
+
declare class SubscriptionManager {
|
|
478
|
+
private pocketbase;
|
|
479
|
+
private subscriptions;
|
|
480
|
+
private subscriptionPromises;
|
|
481
|
+
private cleanupTimers;
|
|
482
|
+
private subscriberCounts;
|
|
483
|
+
constructor(pocketbase: PocketBase);
|
|
484
|
+
private setupSubscription;
|
|
485
|
+
private handleReconnection;
|
|
486
|
+
/**
|
|
487
|
+
* Subscribe to real-time updates for a collection.
|
|
488
|
+
* Returns a promise that resolves when the subscription is fully established.
|
|
489
|
+
*
|
|
490
|
+
* @param collectionName - The PocketBase collection name
|
|
491
|
+
* @param collection - The TanStack DB collection to sync with
|
|
492
|
+
* @param recordId - Optional: Subscribe to specific record, or omit for collection-wide updates
|
|
493
|
+
*/
|
|
494
|
+
subscribe<T extends object>(collectionName: string, collection: Collection<T>, recordId?: string): Promise<void>;
|
|
495
|
+
/**
|
|
496
|
+
* Unsubscribe from real-time updates.
|
|
497
|
+
*
|
|
498
|
+
* @param collectionName - The PocketBase collection name
|
|
499
|
+
* @param recordId - Optional: Unsubscribe from specific record, or omit for collection-wide
|
|
500
|
+
*/
|
|
501
|
+
unsubscribe(collectionName: string, recordId?: string): void;
|
|
502
|
+
/**
|
|
503
|
+
* Unsubscribe from all subscriptions for a collection.
|
|
504
|
+
*
|
|
505
|
+
* @param collectionName - The PocketBase collection name
|
|
506
|
+
*/
|
|
507
|
+
unsubscribeAll(collectionName: string): void;
|
|
508
|
+
/**
|
|
509
|
+
* Check if subscribed to a collection.
|
|
510
|
+
*
|
|
511
|
+
* @param collectionName - The PocketBase collection name
|
|
512
|
+
* @param recordId - Optional: Check specific record subscription, or omit for collection-wide
|
|
513
|
+
*/
|
|
514
|
+
isSubscribed(collectionName: string, recordId?: string): boolean;
|
|
515
|
+
/**
|
|
516
|
+
* Wait for a subscription to be fully established (useful for testing).
|
|
517
|
+
*
|
|
518
|
+
* @param collectionName - The collection name
|
|
519
|
+
* @param recordId - Optional specific record ID
|
|
520
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
521
|
+
*/
|
|
522
|
+
waitForSubscription(collectionName: string, recordId?: string, timeoutMs?: number): Promise<void>;
|
|
523
|
+
/**
|
|
524
|
+
* Track subscriber addition for a collection.
|
|
525
|
+
* Automatically subscribes when first subscriber is added.
|
|
526
|
+
*
|
|
527
|
+
* @param collectionName - The PocketBase collection name
|
|
528
|
+
* @param collection - The TanStack DB collection to sync with
|
|
529
|
+
*/
|
|
530
|
+
addSubscriber<T extends object>(collectionName: string, collection: Collection<T>): Promise<void>;
|
|
531
|
+
/**
|
|
532
|
+
* Track subscriber removal for a collection.
|
|
533
|
+
* Automatically unsubscribes (with delay) when last subscriber is removed.
|
|
534
|
+
*
|
|
535
|
+
* @param collectionName - The PocketBase collection name
|
|
536
|
+
*/
|
|
537
|
+
removeSubscriber(collectionName: string): void;
|
|
538
|
+
/**
|
|
539
|
+
* Get the current subscriber count for a collection.
|
|
540
|
+
* Useful for debugging and testing.
|
|
541
|
+
*
|
|
542
|
+
* @param collectionName - The PocketBase collection name
|
|
543
|
+
* @returns Current subscriber count
|
|
544
|
+
*/
|
|
545
|
+
getSubscriberCount(collectionName: string): number;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Logger interface for subscription events and internal operations.
|
|
550
|
+
* Users can provide their own implementation to integrate with external logging services.
|
|
551
|
+
*/
|
|
552
|
+
interface Logger {
|
|
553
|
+
/**
|
|
554
|
+
* Log debug-level messages (typically only shown in development).
|
|
555
|
+
* @param msg - The message to log
|
|
556
|
+
* @param context - Optional context object with additional information
|
|
557
|
+
*/
|
|
558
|
+
debug: (msg: string, context?: object) => void;
|
|
559
|
+
/**
|
|
560
|
+
* Log warning-level messages.
|
|
561
|
+
* @param msg - The message to log
|
|
562
|
+
* @param context - Optional context object with additional information
|
|
563
|
+
*/
|
|
564
|
+
warn: (msg: string, context?: object) => void;
|
|
565
|
+
/**
|
|
566
|
+
* Log error-level messages.
|
|
567
|
+
* @param msg - The message to log
|
|
568
|
+
* @param context - Optional context object with additional information
|
|
569
|
+
*/
|
|
570
|
+
error: (msg: string, context?: object) => void;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Set a custom logger implementation.
|
|
574
|
+
* This allows users to integrate with their own logging services (e.g., Sentry, LogRocket, etc.).
|
|
575
|
+
*
|
|
576
|
+
* @param customLogger - The custom logger implementation
|
|
577
|
+
*
|
|
578
|
+
* @example
|
|
579
|
+
* ```ts
|
|
580
|
+
* import { setLogger } from 'pocketbase-tanstack-db';
|
|
581
|
+
*
|
|
582
|
+
* // Example: Integration with a custom logging service
|
|
583
|
+
* setLogger({
|
|
584
|
+
* debug: (msg, context) => {
|
|
585
|
+
* myLogger.debug(msg, context);
|
|
586
|
+
* },
|
|
587
|
+
* warn: (msg, context) => {
|
|
588
|
+
* myLogger.warn(msg, context);
|
|
589
|
+
* },
|
|
590
|
+
* error: (msg, context) => {
|
|
591
|
+
* myLogger.error(msg, context);
|
|
592
|
+
* // Also send to error tracking service
|
|
593
|
+
* Sentry.captureMessage(msg, { level: 'error', extra: context });
|
|
594
|
+
* },
|
|
595
|
+
* });
|
|
596
|
+
* ```
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* ```ts
|
|
600
|
+
* // Example: Disable all logging
|
|
601
|
+
* setLogger({
|
|
602
|
+
* debug: () => {},
|
|
603
|
+
* warn: () => {},
|
|
604
|
+
* error: () => {},
|
|
605
|
+
* });
|
|
606
|
+
* ```
|
|
607
|
+
*/
|
|
608
|
+
declare function setLogger(customLogger: Logger): void;
|
|
609
|
+
/**
|
|
610
|
+
* Reset the logger to the default implementation.
|
|
611
|
+
*/
|
|
612
|
+
declare function resetLogger(): void;
|
|
613
|
+
|
|
614
|
+
export { CollectionFactory, type CollectionsMap, CollectionsProvider, type CollectionsProviderProps, type CreateCollectionOptions, type ExpandableFields, type ExtractRecordType, type ExtractRelations, type JoinHelper, type Logger, type NonNullable, type ParseExpandFields, type RealtimeEvent, type RelationAsCollection, type RelationsConfig, SUBSCRIPTION_CONFIG, type SchemaDeclaration, type SubscribableCollection, SubscriptionManager, type SubscriptionState, type WithExpand, resetLogger, setLogger, useStore, useStores };
|