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.
@@ -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 };