@pol-studios/db 1.0.0 → 1.0.2

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.
Files changed (49) hide show
  1. package/README.md +434 -0
  2. package/dist/EntityPermissions-DwFt4tUd.d.ts +35 -0
  3. package/dist/FilterConfig-Bt2Ek74z.d.ts +99 -0
  4. package/dist/UserMetadataContext-BYYqA6LI.d.ts +89 -0
  5. package/dist/auth/context.d.ts +47 -0
  6. package/dist/auth/context.js +12791 -0
  7. package/dist/auth/context.js.map +1 -0
  8. package/dist/auth/guards.d.ts +180 -0
  9. package/dist/auth/guards.js +7651 -0
  10. package/dist/auth/guards.js.map +1 -0
  11. package/dist/auth/hooks.d.ts +312 -0
  12. package/dist/auth/hooks.js +10600 -0
  13. package/dist/auth/hooks.js.map +1 -0
  14. package/dist/auth/index.d.ts +10 -0
  15. package/dist/auth/index.js +13035 -0
  16. package/dist/auth/index.js.map +1 -0
  17. package/dist/client/index.d.ts +16 -0
  18. package/dist/core/index.d.ts +508 -0
  19. package/dist/executor-CB4KHyYG.d.ts +507 -0
  20. package/dist/gen/index.d.ts +1099 -0
  21. package/dist/hooks/index.d.ts +83 -0
  22. package/dist/index-DNrSptau.d.ts +8780 -0
  23. package/dist/index.d.ts +338 -0
  24. package/dist/index.js +10320 -7124
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.web.d.ts +318 -0
  27. package/dist/index.web.js +56795 -0
  28. package/dist/index.web.js.map +1 -0
  29. package/dist/mutation/index.d.ts +58 -0
  30. package/dist/mutation/index.js +4581 -76
  31. package/dist/mutation/index.js.map +1 -1
  32. package/dist/parser/index.d.ts +366 -0
  33. package/dist/parser/index.js +26 -26
  34. package/dist/parser/index.js.map +1 -1
  35. package/dist/query/index.d.ts +723 -0
  36. package/dist/query/index.js +13124 -10324
  37. package/dist/query/index.js.map +1 -1
  38. package/dist/realtime/index.d.ts +44 -0
  39. package/dist/realtime/index.js +13217 -9297
  40. package/dist/realtime/index.js.map +1 -1
  41. package/dist/select-query-parser-CLkOKHzc.d.ts +352 -0
  42. package/dist/types/index.d.ts +6 -0
  43. package/dist/types-CKsWM8T3.d.ts +62 -0
  44. package/dist/useBatchUpsert-ooLlpJMg.d.ts +24 -0
  45. package/dist/useDbCount-B5-Va9sg.d.ts +1740 -0
  46. package/dist/useDbQuery-C-TL8jY1.d.ts +19 -0
  47. package/dist/useResolveFeedback-DuGP4Tgb.d.ts +1165 -0
  48. package/dist/useSupabase-pPhUZHcl.d.ts +27 -0
  49. package/package.json +31 -7
@@ -0,0 +1,1740 @@
1
+ import * as react from 'react';
2
+ import { Dispatch, SetStateAction } from 'react';
3
+ import { SupabaseClient } from '@supabase/supabase-js';
4
+ import { QueryClient } from '@tanstack/react-query';
5
+ import { DatabaseSchema, QueryOptions, DataLayerConfig, TableStrategy, SyncStatus, SyncControl, WhereClause } from './core/index.js';
6
+ import { P as PowerSyncDatabase } from './executor-CB4KHyYG.js';
7
+
8
+ /**
9
+ * V3 Data Layer Adapter Types
10
+ *
11
+ * Extended types for the adapter layer that complement the core DataAdapter interface.
12
+ * These types support the Strategy pattern for routing queries to different backends.
13
+ */
14
+
15
+ /**
16
+ * Result from adapter query operations.
17
+ * Extends the basic array with optional count for pagination.
18
+ */
19
+ interface AdapterQueryResult<T> {
20
+ /** The queried data */
21
+ data: T[];
22
+ /** Total count of matching records (for pagination) */
23
+ count?: number;
24
+ }
25
+ /**
26
+ * Extended adapter interface that accepts table name for multi-table routing.
27
+ *
28
+ * This interface is used by the AdapterRegistry to provide table-aware adapters
29
+ * that can handle multiple tables with a single adapter instance.
30
+ *
31
+ * Differences from core DataAdapter:
32
+ * - Includes table name parameter in all methods
33
+ * - Returns AdapterQueryResult with optional count
34
+ * - Supports optional subscribe method for reactivity
35
+ */
36
+ interface TableDataAdapter {
37
+ /**
38
+ * Unique identifier for the adapter type
39
+ */
40
+ readonly name: string;
41
+ /**
42
+ * Execute a query and return results
43
+ *
44
+ * @param table - The table name to query
45
+ * @param options - Query options (select, where, orderBy, limit, offset)
46
+ * @returns Promise resolving to query results with optional count
47
+ */
48
+ query<T>(table: string, options: QueryOptions): Promise<AdapterQueryResult<T>>;
49
+ /**
50
+ * Query a single record by ID
51
+ *
52
+ * @param table - The table name to query
53
+ * @param id - The record ID
54
+ * @param options - Optional query options (mainly for select)
55
+ * @returns Promise resolving to the record or null if not found
56
+ */
57
+ queryById?<T>(table: string, id: string, options?: Pick<QueryOptions, "select">): Promise<T | null>;
58
+ /**
59
+ * Subscribe to real-time changes on a query.
60
+ * Not all adapters support this - it's optional.
61
+ *
62
+ * @param table - The table name to watch
63
+ * @param options - Query options to filter what to watch
64
+ * @param callback - Function called with updated data
65
+ * @returns Unsubscribe function
66
+ */
67
+ subscribe?<T>(table: string, options: QueryOptions, callback: (data: T[]) => void): () => void;
68
+ /**
69
+ * Insert a new record
70
+ *
71
+ * @param table - The table name
72
+ * @param data - The data to insert
73
+ * @returns Promise resolving to the inserted record
74
+ */
75
+ insert<T>(table: string, data: Partial<T>): Promise<T>;
76
+ /**
77
+ * Update an existing record by ID
78
+ *
79
+ * @param table - The table name
80
+ * @param id - The record ID to update
81
+ * @param data - The data to update
82
+ * @returns Promise resolving to the updated record
83
+ */
84
+ update<T>(table: string, id: string, data: Partial<T>): Promise<T>;
85
+ /**
86
+ * Upsert (insert or update) a record
87
+ * If the record has an ID and exists, it will be updated.
88
+ * Otherwise, a new record will be inserted.
89
+ *
90
+ * @param table - The table name
91
+ * @param data - The data to upsert
92
+ * @returns Promise resolving to the upserted record
93
+ */
94
+ upsert<T>(table: string, data: Partial<T>): Promise<T>;
95
+ /**
96
+ * Delete a record by ID
97
+ *
98
+ * @param table - The table name
99
+ * @param id - The record ID to delete
100
+ * @returns Promise that resolves when deletion is complete
101
+ */
102
+ delete(table: string, id: string): Promise<void>;
103
+ }
104
+ /**
105
+ * Configuration for creating an adapter
106
+ */
107
+ interface AdapterConfig {
108
+ /**
109
+ * The strategy type to create
110
+ */
111
+ strategy: "powersync" | "supabase" | "cached" | "hybrid";
112
+ /**
113
+ * Additional strategy-specific configuration
114
+ */
115
+ [key: string]: unknown;
116
+ }
117
+ /**
118
+ * Factory interface for creating adapters
119
+ */
120
+ interface AdapterFactory {
121
+ /**
122
+ * Create a new adapter instance based on configuration
123
+ *
124
+ * @param config - Adapter configuration
125
+ * @returns The created adapter instance
126
+ */
127
+ create(config: AdapterConfig): TableDataAdapter;
128
+ }
129
+ /**
130
+ * Describes the capabilities of an adapter
131
+ */
132
+ interface AdapterCapabilities {
133
+ /**
134
+ * Whether the adapter supports real-time subscriptions
135
+ */
136
+ supportsSubscribe: boolean;
137
+ /**
138
+ * Whether the adapter works offline
139
+ */
140
+ supportsOffline: boolean;
141
+ /**
142
+ * Whether the adapter caches data locally
143
+ */
144
+ supportsCache: boolean;
145
+ /**
146
+ * Whether the adapter syncs data bidirectionally
147
+ */
148
+ supportsSync: boolean;
149
+ }
150
+ /**
151
+ * Extended adapter interface with capability reporting
152
+ */
153
+ interface CapableDataAdapter extends TableDataAdapter {
154
+ /**
155
+ * Get the capabilities of this adapter
156
+ */
157
+ readonly capabilities: AdapterCapabilities;
158
+ }
159
+ /**
160
+ * Dependencies required to initialize adapters.
161
+ * Uses 'unknown' type for external dependencies to allow proper typing
162
+ * when concrete implementations are provided.
163
+ */
164
+ interface AdapterDependencies {
165
+ /**
166
+ * PowerSync database instance
167
+ * Will be typed as PowerSyncDatabase when PowerSync is integrated
168
+ */
169
+ powerSync: unknown;
170
+ /**
171
+ * Supabase client instance
172
+ * Will be typed as SupabaseClient when imported
173
+ */
174
+ supabase: unknown;
175
+ /**
176
+ * TanStack Query client for caching
177
+ * Will be typed as QueryClient when imported
178
+ */
179
+ queryClient: unknown;
180
+ /**
181
+ * Database schema for relationship resolution
182
+ */
183
+ schema: DatabaseSchema;
184
+ }
185
+ /**
186
+ * String literals for adapter strategy types
187
+ */
188
+ declare const ADAPTER_STRATEGIES: {
189
+ readonly POWERSYNC: "powersync";
190
+ readonly SUPABASE: "supabase";
191
+ readonly CACHED: "cached";
192
+ readonly HYBRID: "hybrid";
193
+ readonly AUTO: "auto";
194
+ };
195
+
196
+ /**
197
+ * Type for adapter strategy values
198
+ */
199
+ type AdapterStrategyType = (typeof ADAPTER_STRATEGIES)[keyof typeof ADAPTER_STRATEGIES];
200
+
201
+ /**
202
+ * Adapter Auto-Detector
203
+ *
204
+ * Detects available backends (PowerSync, Supabase) at runtime and recommends
205
+ * the best one to use based on availability and configuration preferences.
206
+ *
207
+ * This enables the V3 data layer to automatically select the optimal backend
208
+ * for offline-first or online-first experiences.
209
+ */
210
+
211
+ /**
212
+ * Status of a backend adapter
213
+ */
214
+ declare enum BackendStatus {
215
+ /** Backend is available and ready to use */
216
+ AVAILABLE = "available",
217
+ /** Backend is initializing (e.g., PowerSync syncing) */
218
+ INITIALIZING = "initializing",
219
+ /** Backend is not available */
220
+ UNAVAILABLE = "unavailable"
221
+ }
222
+ /**
223
+ * Result of auto-detection
224
+ */
225
+ interface AutoDetectionResult {
226
+ /** PowerSync availability status */
227
+ powerSyncStatus: BackendStatus;
228
+ /** Supabase availability status */
229
+ supabaseStatus: BackendStatus;
230
+ /** Recommended backend to use */
231
+ recommendedBackend: "powersync" | "supabase";
232
+ /** Whether device is online */
233
+ isOnline: boolean;
234
+ /** Reason for recommendation */
235
+ reason: string;
236
+ }
237
+ /**
238
+ * Options for auto-detection
239
+ */
240
+ interface AutoDetectorOptions {
241
+ /** Prefer PowerSync when available (default: true) */
242
+ preferPowerSync?: boolean;
243
+ /** Timeout for status checks in ms (default: 1000) */
244
+ statusCheckTimeout?: number;
245
+ }
246
+ /**
247
+ * Listener for backend change events
248
+ */
249
+ type BackendChangeListener = (result: AutoDetectionResult) => void;
250
+ /**
251
+ * Detects available backends and recommends the best one to use.
252
+ *
253
+ * The auto-detector checks for PowerSync and Supabase availability and
254
+ * makes intelligent recommendations based on:
255
+ * - Backend availability
256
+ * - Network connectivity
257
+ * - User preferences (preferPowerSync option)
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * const detector = new AdapterAutoDetector(powerSyncDb, supabaseClient, {
262
+ * preferPowerSync: true,
263
+ * });
264
+ *
265
+ * const result = detector.detect();
266
+ * console.log(`Using ${result.recommendedBackend}: ${result.reason}`);
267
+ * ```
268
+ */
269
+ declare class AdapterAutoDetector {
270
+ private powerSyncDb;
271
+ private supabase;
272
+ private options;
273
+ private listeners;
274
+ private lastResult;
275
+ constructor(powerSyncDb: PowerSyncDatabase | null, supabase: SupabaseClient | null, options?: AutoDetectorOptions);
276
+ /**
277
+ * Detect backend availability and recommend best option.
278
+ *
279
+ * The detection logic follows this priority:
280
+ * 1. If preferPowerSync is true and PowerSync is available, use PowerSync
281
+ * 2. If PowerSync is initializing and online with Supabase available, use Supabase temporarily
282
+ * 3. If online with Supabase available, use Supabase
283
+ * 4. If offline but PowerSync available, use PowerSync (offline mode)
284
+ * 5. Default to Supabase as fallback
285
+ *
286
+ * @returns Detection result with recommendation and reasoning
287
+ */
288
+ detect(): AutoDetectionResult;
289
+ /**
290
+ * Check if PowerSync is available.
291
+ *
292
+ * PowerSync is considered available if we have a database instance.
293
+ * The actual sync status would be checked via PowerSync's status API
294
+ * when the full SDK is integrated.
295
+ *
296
+ * @returns PowerSync backend status
297
+ */
298
+ detectPowerSyncStatus(): BackendStatus;
299
+ /**
300
+ * Check if Supabase is available.
301
+ *
302
+ * Supabase is considered available if we have a client instance.
303
+ * The actual network connectivity is checked separately via checkOnlineStatus().
304
+ *
305
+ * @returns Supabase backend status
306
+ */
307
+ detectSupabaseStatus(): BackendStatus;
308
+ /**
309
+ * Check if device is online.
310
+ *
311
+ * Uses navigator.onLine in browser environments.
312
+ * Returns true by default for non-browser environments (React Native
313
+ * would need NetInfo integration via dependency injection).
314
+ *
315
+ * @returns Whether the device has network connectivity
316
+ */
317
+ checkOnlineStatus(): boolean;
318
+ /**
319
+ * Update PowerSync instance (e.g., when it becomes available).
320
+ *
321
+ * @param db - New PowerSync database instance or null
322
+ */
323
+ setPowerSync(db: PowerSyncDatabase | null): void;
324
+ /**
325
+ * Update Supabase instance.
326
+ *
327
+ * @param supabase - New Supabase client instance or null
328
+ */
329
+ setSupabase(supabase: SupabaseClient | null): void;
330
+ /**
331
+ * Get current PowerSync instance.
332
+ *
333
+ * @returns Current PowerSync database instance or null
334
+ */
335
+ getPowerSync(): PowerSyncDatabase | null;
336
+ /**
337
+ * Get current Supabase instance.
338
+ *
339
+ * @returns Current Supabase client instance or null
340
+ */
341
+ getSupabase(): SupabaseClient | null;
342
+ /**
343
+ * Update detector options.
344
+ *
345
+ * @param options - New options to merge with existing
346
+ */
347
+ setOptions(options: Partial<AutoDetectorOptions>): void;
348
+ /**
349
+ * Get current detector options.
350
+ *
351
+ * @returns Current detector options
352
+ */
353
+ getOptions(): Required<AutoDetectorOptions>;
354
+ /**
355
+ * Add a listener for backend change events.
356
+ *
357
+ * @param listener - Callback to invoke when detection result changes
358
+ * @returns Function to remove the listener
359
+ */
360
+ addListener(listener: BackendChangeListener): () => void;
361
+ /**
362
+ * Remove a listener for backend change events.
363
+ *
364
+ * @param listener - Listener to remove
365
+ */
366
+ removeListener(listener: BackendChangeListener): void;
367
+ /**
368
+ * Get the last detection result.
369
+ *
370
+ * @returns Last detection result or null if never detected
371
+ */
372
+ getLastResult(): AutoDetectionResult | null;
373
+ /**
374
+ * Check if the detection result has changed from the last result.
375
+ */
376
+ private hasResultChanged;
377
+ /**
378
+ * Notify all listeners of a detection result change.
379
+ */
380
+ private notifyListeners;
381
+ }
382
+ /**
383
+ * Create an AdapterAutoDetector instance.
384
+ *
385
+ * @param powerSyncDb - PowerSync database instance or null
386
+ * @param supabase - Supabase client instance or null
387
+ * @param options - Detection options
388
+ * @returns New AdapterAutoDetector instance
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * const detector = createAdapterAutoDetector(powerSyncDb, supabaseClient, {
393
+ * preferPowerSync: true,
394
+ * statusCheckTimeout: 2000,
395
+ * });
396
+ *
397
+ * const { recommendedBackend, reason } = detector.detect();
398
+ * ```
399
+ */
400
+ declare function createAdapterAutoDetector(powerSyncDb: PowerSyncDatabase | null, supabase: SupabaseClient | null, options?: AutoDetectorOptions): AdapterAutoDetector;
401
+
402
+ /**
403
+ * V3 Data Layer Adapter Registry
404
+ *
405
+ * Factory that creates and manages adapter instances based on table configuration.
406
+ * Uses lazy initialization to create adapters on first access.
407
+ */
408
+
409
+ /**
410
+ * Registry that manages and provides adapters based on table configuration.
411
+ *
412
+ * The registry:
413
+ * - Stores configuration for table strategies
414
+ * - Lazily creates adapters when first accessed
415
+ * - Caches created adapters for reuse
416
+ * - Provides default fallback for unconfigured tables
417
+ *
418
+ * Usage:
419
+ * ```typescript
420
+ * const registry = createAdapterRegistry(config);
421
+ *
422
+ * // Later, when providers initialize:
423
+ * registry.setPowerSyncAdapter(powerSyncAdapter);
424
+ * registry.setSupabaseAdapter(supabaseAdapter);
425
+ *
426
+ * // Get adapter for a table:
427
+ * const adapter = registry.getAdapter("Project");
428
+ * ```
429
+ */
430
+ declare class AdapterRegistry {
431
+ private config;
432
+ /**
433
+ * Cache of created adapters by table name
434
+ */
435
+ private adapters;
436
+ /**
437
+ * PowerSync adapter instance (set during initialization)
438
+ */
439
+ private powerSyncAdapter;
440
+ /**
441
+ * Supabase adapter instance (set during initialization)
442
+ */
443
+ private supabaseAdapter;
444
+ /**
445
+ * Cached adapter instance (wraps Supabase with TanStack Query)
446
+ */
447
+ private cachedAdapter;
448
+ /**
449
+ * Dependencies for creating adapters
450
+ */
451
+ private deps;
452
+ /**
453
+ * Whether the registry has been initialized with adapters
454
+ */
455
+ private _isInitialized;
456
+ /**
457
+ * Auto-detector instance for automatic backend selection
458
+ */
459
+ private autoDetector;
460
+ /**
461
+ * Listeners for backend change events
462
+ */
463
+ private backendChangeListeners;
464
+ /**
465
+ * Last auto-detection result for debugging and status
466
+ */
467
+ private lastDetectionResult;
468
+ /**
469
+ * Create a new adapter registry
470
+ *
471
+ * @param config - Data layer configuration with table strategies
472
+ */
473
+ constructor(config: DataLayerConfig);
474
+ /**
475
+ * Check if the registry has been initialized
476
+ */
477
+ get isInitialized(): boolean;
478
+ /**
479
+ * Initialize the registry with dependencies.
480
+ * Called by DataLayerProvider when PowerSync and Supabase are ready.
481
+ *
482
+ * @param deps - Dependencies needed to create adapters
483
+ */
484
+ initialize(deps: AdapterDependencies): void;
485
+ /**
486
+ * Set the PowerSync adapter instance
487
+ *
488
+ * @param adapter - PowerSync adapter implementation
489
+ */
490
+ setPowerSyncAdapter(adapter: TableDataAdapter): void;
491
+ /**
492
+ * Set the Supabase adapter instance
493
+ *
494
+ * @param adapter - Supabase adapter implementation
495
+ */
496
+ setSupabaseAdapter(adapter: TableDataAdapter): void;
497
+ /**
498
+ * Set the Cached adapter instance
499
+ *
500
+ * @param adapter - Cached adapter implementation
501
+ */
502
+ setCachedAdapter(adapter: TableDataAdapter): void;
503
+ /**
504
+ * Initialize auto-detection with a detector instance
505
+ *
506
+ * @param detector - The auto-detector to use
507
+ */
508
+ initializeAutoDetection(detector: AdapterAutoDetector): void;
509
+ /**
510
+ * Get the appropriate adapter for a table based on configuration.
511
+ *
512
+ * The adapter is selected based on the table's strategy in config.tables:
513
+ * - "powersync": Returns PowerSyncAdapter
514
+ * - "supabase": Returns SupabaseAdapter
515
+ * - "cached": Returns CachedAdapter (wrapping Supabase)
516
+ * - "hybrid": Returns HybridAdapter (combining PowerSync + Cached)
517
+ * - "auto": Uses auto-detection to select the best backend
518
+ *
519
+ * For tables not in config, defaults to auto-detection if available,
520
+ * otherwise falls back to SupabaseAdapter.
521
+ *
522
+ * @param table - The table name
523
+ * @returns The appropriate adapter for the table
524
+ * @throws Error if adapters are not initialized
525
+ */
526
+ getAdapter(table: string): TableDataAdapter;
527
+ /**
528
+ * Get the PowerSync adapter directly
529
+ *
530
+ * @returns PowerSync adapter or null if not initialized
531
+ */
532
+ getPowerSyncAdapter(): TableDataAdapter | null;
533
+ /**
534
+ * Get the Supabase adapter directly
535
+ *
536
+ * @returns Supabase adapter or null if not initialized
537
+ */
538
+ getSupabaseAdapter(): TableDataAdapter | null;
539
+ /**
540
+ * Get the Cached adapter directly
541
+ *
542
+ * @returns Cached adapter or null if not initialized
543
+ */
544
+ getCachedAdapter(): TableDataAdapter | null;
545
+ /**
546
+ * Get all configured table names
547
+ *
548
+ * @returns Array of table names with explicit strategy configuration
549
+ */
550
+ getConfiguredTables(): string[];
551
+ /**
552
+ * Get the strategy for a specific table
553
+ *
554
+ * @param table - The table name
555
+ * @returns The table strategy or undefined if not configured
556
+ */
557
+ getTableStrategy(table: string): TableStrategy | undefined;
558
+ /**
559
+ * Check if a table uses PowerSync strategy
560
+ *
561
+ * @param table - The table name
562
+ * @returns True if table uses PowerSync or Hybrid strategy
563
+ */
564
+ usesPowerSync(table: string): boolean;
565
+ /**
566
+ * Get all tables that use PowerSync
567
+ *
568
+ * @returns Array of table names using PowerSync or Hybrid strategy
569
+ */
570
+ getPowerSyncTables(): string[];
571
+ /**
572
+ * Get adapter using auto-detection
573
+ *
574
+ * @param strategy - Optional auto strategy configuration
575
+ * @returns The automatically selected adapter
576
+ */
577
+ private getAutoAdapter;
578
+ /**
579
+ * Subscribe to backend changes
580
+ *
581
+ * @param callback - Function called when recommended backend changes
582
+ * @returns Unsubscribe function
583
+ */
584
+ onBackendChange(callback: (backend: "powersync" | "supabase") => void): () => void;
585
+ /**
586
+ * Notify listeners of backend change
587
+ *
588
+ * @param backend - The new recommended backend
589
+ */
590
+ private notifyBackendChange;
591
+ /**
592
+ * Get the last auto-detection result
593
+ *
594
+ * @returns Last detection result or null if never detected
595
+ */
596
+ getLastDetectionResult(): AutoDetectionResult | null;
597
+ /**
598
+ * Get the auto-detector instance
599
+ *
600
+ * @returns Auto-detector instance or null if not initialized
601
+ */
602
+ getAutoDetector(): AdapterAutoDetector | null;
603
+ /**
604
+ * Create an adapter based on the strategy type
605
+ *
606
+ * @param strategy - The table strategy configuration
607
+ * @returns The created adapter
608
+ * @throws Error if the required base adapter is not initialized
609
+ */
610
+ private createAdapter;
611
+ /**
612
+ * Clear all cached adapters.
613
+ * Useful when configuration changes and adapters need to be recreated.
614
+ */
615
+ clearCache(): void;
616
+ /**
617
+ * Reset the registry to uninitialized state.
618
+ * Used during cleanup or testing.
619
+ */
620
+ reset(): void;
621
+ /**
622
+ * Dispose all adapters and clean up resources.
623
+ * Called when the DataLayerProvider unmounts.
624
+ */
625
+ dispose(): void;
626
+ /**
627
+ * Get debug information about the registry state
628
+ */
629
+ getDebugInfo(): {
630
+ isInitialized: boolean;
631
+ hasPowerSync: boolean;
632
+ hasSupabase: boolean;
633
+ hasCached: boolean;
634
+ cachedAdapterCount: number;
635
+ configuredTableCount: number;
636
+ powerSyncTables: string[];
637
+ hasAutoDetector: boolean;
638
+ lastDetectionResult: AutoDetectionResult | null;
639
+ };
640
+ }
641
+ /**
642
+ * Create a new adapter registry
643
+ *
644
+ * @param config - Data layer configuration
645
+ * @returns A new AdapterRegistry instance
646
+ *
647
+ * @example
648
+ * ```typescript
649
+ * const config: DataLayerConfig = {
650
+ * schema: databaseSchema,
651
+ * connections: { ... },
652
+ * tables: {
653
+ * Project: { strategy: "powersync", syncScope: "activeProject" },
654
+ * AuditLog: { strategy: "supabase" },
655
+ * Report: { strategy: "cached", cacheTime: 60000 },
656
+ * },
657
+ * scopes: { ... },
658
+ * defaults: { syncMode: "live" },
659
+ * };
660
+ *
661
+ * const registry = createAdapterRegistry(config);
662
+ *
663
+ * // In provider:
664
+ * registry.setPowerSyncAdapter(new PowerSyncAdapter(db, schema));
665
+ * registry.setSupabaseAdapter(new SupabaseAdapter(supabase));
666
+ *
667
+ * // In hooks:
668
+ * const adapter = registry.getAdapter("Project"); // Returns PowerSyncAdapter
669
+ * ```
670
+ */
671
+ declare function createAdapterRegistry(config: DataLayerConfig): AdapterRegistry;
672
+
673
+ /**
674
+ * Status of the data layer initialization
675
+ */
676
+ interface DataLayerStatus {
677
+ /** Whether the data layer is fully initialized */
678
+ isInitialized: boolean;
679
+ /** Current active backend */
680
+ currentBackend: "powersync" | "supabase" | null;
681
+ /** PowerSync connection status */
682
+ powerSyncStatus: BackendStatus;
683
+ /** Whether device is online */
684
+ isOnline: boolean;
685
+ /** Last auto-detection result */
686
+ lastDetection: AutoDetectionResult | null;
687
+ /** Initialization error if any */
688
+ error: Error | null;
689
+ }
690
+ /**
691
+ * Context value for the data layer
692
+ */
693
+ interface DataLayerContextValue {
694
+ /** Adapter registry for getting table adapters */
695
+ registry: AdapterRegistry;
696
+ /** Get adapter for a specific table */
697
+ getAdapter: (table: string) => TableDataAdapter;
698
+ /** PowerSync database instance (null when not available) */
699
+ powerSync: PowerSyncDatabase | null;
700
+ /** Supabase client (always available) */
701
+ supabase: SupabaseClient;
702
+ /** React Query client */
703
+ queryClient: QueryClient;
704
+ /** Database schema */
705
+ schema: DatabaseSchema;
706
+ /** Current status */
707
+ status: DataLayerStatus;
708
+ /** Sync status (for PowerSync, no-op for Supabase-only) */
709
+ syncStatus: SyncStatus;
710
+ /** Sync controls (for PowerSync, no-op for Supabase-only) */
711
+ syncControl: SyncControl;
712
+ }
713
+ /**
714
+ * Data layer context
715
+ *
716
+ * Provides access to the V3 data layer throughout the React component tree.
717
+ * Must be accessed via the useDataLayer hook or similar consumer.
718
+ */
719
+ declare const DataLayerContext: react.Context<DataLayerContextValue>;
720
+
721
+ /**
722
+ * V3 Data Layer Hook
723
+ *
724
+ * Provides access to the V3 data layer context for components.
725
+ * This hook is the primary entry point for accessing adapters,
726
+ * status information, and core data layer functionality.
727
+ */
728
+
729
+ /**
730
+ * Hook to access the V3 data layer context
731
+ *
732
+ * Provides access to:
733
+ * - registry: Adapter registry for getting table adapters
734
+ * - getAdapter: Function to get adapter for a specific table
735
+ * - powerSync: PowerSync database instance (null when not available)
736
+ * - supabase: Supabase client (always available)
737
+ * - queryClient: React Query client
738
+ * - schema: Database schema
739
+ * - status: Current initialization and connection status
740
+ * - syncStatus: Sync status for PowerSync
741
+ * - syncControl: Sync controls for PowerSync
742
+ *
743
+ * @throws Error if used outside of DataLayerProvider
744
+ *
745
+ * @example
746
+ * const { getAdapter, status } = useDataLayer();
747
+ *
748
+ * if (status.isInitialized) {
749
+ * const adapter = getAdapter("Task");
750
+ * // Use adapter...
751
+ * }
752
+ */
753
+ declare function useDataLayer(): DataLayerContextValue;
754
+ /**
755
+ * Hook to safely access data layer context (returns null if not in provider)
756
+ *
757
+ * Use this when you need to check if the data layer is available
758
+ * without throwing an error. Useful for conditional rendering or
759
+ * components that may be rendered outside the provider context.
760
+ *
761
+ * @example
762
+ * const dataLayer = useDataLayerOptional();
763
+ *
764
+ * if (dataLayer) {
765
+ * // Safe to use data layer
766
+ * } else {
767
+ * // Render fallback UI
768
+ * }
769
+ */
770
+ declare function useDataLayerOptional(): DataLayerContextValue | null;
771
+
772
+ /**
773
+ * V3 useDbQuery Hook
774
+ *
775
+ * React hook for querying multiple records from a table.
776
+ * Works identically whether PowerSync or Supabase is the backend.
777
+ * Uses React Query for state management and caching.
778
+ *
779
+ * Types are automatically inferred from table names when you augment
780
+ * the DatabaseTypes interface with your app's Database type.
781
+ *
782
+ * @example
783
+ * // In your app's types/db.d.ts:
784
+ * declare module "@pol-studios/db" {
785
+ * interface DatabaseTypes {
786
+ * database: import("@/database.types").Database;
787
+ * }
788
+ * }
789
+ *
790
+ * // Then usage auto-infers types:
791
+ * const { data } = useDbQuery("EquipmentFixtureUnit", { ... });
792
+ * // data is typed as Tables<"EquipmentFixtureUnit">[]
793
+ */
794
+
795
+ /**
796
+ * Augment this interface in your app to enable automatic type inference.
797
+ *
798
+ * @example
799
+ * // In types/db.d.ts
800
+ * declare module "@pol-studios/db" {
801
+ * interface DatabaseTypes {
802
+ * database: import("@/database.types").Database;
803
+ * }
804
+ * }
805
+ */
806
+ interface DatabaseTypes$1 {
807
+ }
808
+ /**
809
+ * The configured Database type, or a generic fallback
810
+ */
811
+ type ConfiguredDatabase$1 = DatabaseTypes$1 extends {
812
+ database: infer DB;
813
+ } ? DB : GenericSchema$1;
814
+ /**
815
+ * Generic schema structure for fallback
816
+ */
817
+ type GenericSchema$1 = {
818
+ public: {
819
+ Tables: Record<string, {
820
+ Row: Record<string, unknown>;
821
+ }>;
822
+ Views: Record<string, {
823
+ Row: Record<string, unknown>;
824
+ }>;
825
+ };
826
+ [schema: string]: {
827
+ Tables: Record<string, {
828
+ Row: Record<string, unknown>;
829
+ }>;
830
+ Views?: Record<string, {
831
+ Row: Record<string, unknown>;
832
+ }>;
833
+ };
834
+ };
835
+ /**
836
+ * Default schema from Database (usually "public")
837
+ */
838
+ type DefaultSchema$1 = ConfiguredDatabase$1 extends {
839
+ public: infer S;
840
+ } ? S : never;
841
+ /**
842
+ * Extract all valid table names from the default schema
843
+ */
844
+ type PublicTableNames$1 = DefaultSchema$1 extends {
845
+ Tables: infer T;
846
+ } ? keyof T & string : string;
847
+ /**
848
+ * Extract all valid schema names
849
+ */
850
+ type SchemaNames$1 = keyof ConfiguredDatabase$1 & string;
851
+ /**
852
+ * Extract table names for a specific schema
853
+ */
854
+ type SchemaTableNames$1<S extends string> = ConfiguredDatabase$1 extends {
855
+ [K in S]: {
856
+ Tables: infer T;
857
+ };
858
+ } ? keyof T & string : string;
859
+ /**
860
+ * Build dot notation strings for all schema.table combinations
861
+ */
862
+ type SchemaDotTable$1 = {
863
+ [S in SchemaNames$1]: S extends "public" ? never : `${S}.${SchemaTableNames$1<S>}`;
864
+ }[SchemaNames$1];
865
+ /**
866
+ * Table identifier - provides autocomplete for valid table names
867
+ *
868
+ * Supports:
869
+ * - "TableName" - public schema tables
870
+ * - "schema.TableName" - dot notation for other schemas
871
+ * - { schema, table } - object format for other schemas
872
+ */
873
+ type TableIdentifier$1 = PublicTableNames$1 | SchemaDotTable$1 | {
874
+ [S in Exclude<SchemaNames$1, "public">]: {
875
+ schema: S;
876
+ table: SchemaTableNames$1<S>;
877
+ };
878
+ }[Exclude<SchemaNames$1, "public">];
879
+ /**
880
+ * Resolve row type from a table identifier
881
+ *
882
+ * Supports:
883
+ * - "TableName" → public schema
884
+ * - "schema.TableName" → specified schema (dot notation)
885
+ * - { schema: "schema", table: "TableName" } → specified schema (object)
886
+ */
887
+ type ResolveRowType$1<T extends TableIdentifier$1> = T extends string ? T extends `${infer Schema}.${infer Table}` ? ConfiguredDatabase$1 extends {
888
+ [K in Schema]: {
889
+ Tables: {
890
+ [K2 in Table]: {
891
+ Row: infer R;
892
+ };
893
+ };
894
+ };
895
+ } ? R : Record<string, unknown> : DefaultSchema$1 extends {
896
+ Tables: {
897
+ [K in T]: {
898
+ Row: infer R;
899
+ };
900
+ };
901
+ } ? R : DefaultSchema$1 extends {
902
+ Views: {
903
+ [K in T]: {
904
+ Row: infer R;
905
+ };
906
+ };
907
+ } ? R : Record<string, unknown> : T extends {
908
+ schema: infer S;
909
+ table: infer TN;
910
+ } ? S extends string ? TN extends string ? ConfiguredDatabase$1 extends {
911
+ [K in S]: {
912
+ Tables: {
913
+ [K2 in TN]: {
914
+ Row: infer R;
915
+ };
916
+ };
917
+ };
918
+ } ? R : Record<string, unknown> : Record<string, unknown> : Record<string, unknown> : Record<string, unknown>;
919
+ /**
920
+ * Options for useDbQuery hook
921
+ */
922
+ interface UseDbQueryOptions extends Omit<QueryOptions, "enabled"> {
923
+ /** Whether the query is enabled (default: true) */
924
+ enabled?: boolean;
925
+ /**
926
+ * React Query stale time in ms
927
+ * Default depends on backend:
928
+ * - PowerSync (offline): 0 - always refetch from SQLite (disk is fast)
929
+ * - Supabase (online): 30000 - use normal caching
930
+ */
931
+ staleTime?: number;
932
+ /** React Query gcTime (cache time) in ms (default: 300000 - 5 minutes) */
933
+ gcTime?: number;
934
+ /** Whether to refetch on window focus (default: true) */
935
+ refetchOnWindowFocus?: boolean;
936
+ /**
937
+ * Whether to refetch on mount
938
+ * Default depends on backend:
939
+ * - PowerSync (offline): "always" - always query SQLite
940
+ * - Supabase (online): true - refetch if stale
941
+ */
942
+ refetchOnMount?: boolean | "always";
943
+ /** Whether to enable real-time subscriptions (if adapter supports) */
944
+ realtime?: boolean;
945
+ /** If true, returns single item instead of array (for compatibility with V2) */
946
+ single?: boolean;
947
+ }
948
+ /**
949
+ * Result from useDbQuery hook
950
+ */
951
+ interface UseDbQueryResult<T> {
952
+ /** Query data */
953
+ data: T[] | undefined;
954
+ /** Whether query is loading (initial load) */
955
+ isLoading: boolean;
956
+ /** Whether query is in pending state */
957
+ isPending: boolean;
958
+ /** Whether query is currently fetching (including refetch) */
959
+ isFetching: boolean;
960
+ /** Whether query is currently refetching (alias for isFetching for V2 compatibility) */
961
+ isRefetching: boolean;
962
+ /** Whether query completed successfully */
963
+ isSuccess: boolean;
964
+ /** Whether query errored */
965
+ isError: boolean;
966
+ /** Query error if any */
967
+ error: Error | null;
968
+ /** Refetch the query */
969
+ refetch: () => Promise<void>;
970
+ /** Total count (if pagination is used) */
971
+ count?: number;
972
+ /** Whether data is stale */
973
+ isStale: boolean;
974
+ /** Timestamp of last data update */
975
+ dataUpdatedAt: number | null;
976
+ }
977
+ /**
978
+ * Hook for querying multiple records from a table
979
+ *
980
+ * This hook provides a unified interface for querying data that works
981
+ * identically whether the backend is PowerSync (offline-first) or
982
+ * Supabase (online-only). It uses React Query for caching and state management.
983
+ *
984
+ * Features:
985
+ * - Automatic type inference from table names (when DatabaseTypes is augmented)
986
+ * - Automatic backend selection based on DataLayerProvider configuration
987
+ * - React Query integration for caching, deduplication, and background updates
988
+ * - Optional real-time subscriptions (when adapter supports it)
989
+ * - Pagination support with count
990
+ *
991
+ * @param table - Table name (string) or { schema, table } object
992
+ * @param options - Query options (select, where, orderBy, limit, offset, etc.)
993
+ * @returns Query result with data, loading states, error, and refetch function
994
+ *
995
+ * @example
996
+ * // Basic query - types auto-inferred from table name
997
+ * const { data } = useDbQuery("EquipmentFixtureUnit");
998
+ * // data is typed as Tables<"EquipmentFixtureUnit">[]
999
+ *
1000
+ * @example
1001
+ * // Query from non-public schema
1002
+ * const { data } = useDbQuery({ schema: "core", table: "Profile" });
1003
+ * // data is typed as Tables<{ schema: "core" }, "Profile">[]
1004
+ *
1005
+ * @example
1006
+ * // Query with filters and sorting
1007
+ * const { data } = useDbQuery("Task", {
1008
+ * select: "*, Project(*)",
1009
+ * where: { status: "active" },
1010
+ * orderBy: [{ field: "createdAt", direction: "desc" }],
1011
+ * limit: 10,
1012
+ * });
1013
+ */
1014
+ /**
1015
+ * Main hook signature with auto-inferred types from table identifiers
1016
+ */
1017
+ declare function useDbQuery<T extends TableIdentifier$1>(table: T, options?: UseDbQueryOptions): UseDbQueryResult<ResolveRowType$1<T>>;
1018
+ /**
1019
+ * Overload for explicit type parameter when table name is a string literal
1020
+ */
1021
+ declare function useDbQuery<T>(table: string, options?: UseDbQueryOptions): UseDbQueryResult<T>;
1022
+
1023
+ /**
1024
+ * V3 useDbQueryById Hook
1025
+ *
1026
+ * React hook for querying a single record by ID from a table.
1027
+ * Works identically whether PowerSync or Supabase is the backend.
1028
+ * Uses React Query for state management and caching.
1029
+ */
1030
+ /**
1031
+ * Options for useDbQueryById hook
1032
+ */
1033
+ interface UseDbQueryByIdOptions {
1034
+ /** Columns to select (Supabase-style select string) */
1035
+ select?: string;
1036
+ /** Whether the query is enabled (default: true if id is provided) */
1037
+ enabled?: boolean;
1038
+ /** React Query stale time in ms (default: 30000) */
1039
+ staleTime?: number;
1040
+ }
1041
+ /**
1042
+ * Result from useDbQueryById hook
1043
+ */
1044
+ interface UseDbQueryByIdResult<T> {
1045
+ /** Query data (undefined while loading, null if not found) */
1046
+ data: T | null | undefined;
1047
+ /** Whether query is loading (initial load) */
1048
+ isLoading: boolean;
1049
+ /** Whether query is in pending state */
1050
+ isPending: boolean;
1051
+ /** Whether query is currently fetching (including refetch) */
1052
+ isFetching: boolean;
1053
+ /** Query error if any */
1054
+ error: Error | null;
1055
+ /** Refetch the query */
1056
+ refetch: () => Promise<void>;
1057
+ }
1058
+ /**
1059
+ * Hook for querying a single record by ID
1060
+ *
1061
+ * This hook provides a unified interface for fetching a single record that works
1062
+ * identically whether the backend is PowerSync (offline-first) or
1063
+ * Supabase (online-only). It uses React Query for caching and state management.
1064
+ *
1065
+ * Features:
1066
+ * - Automatic backend selection based on DataLayerProvider configuration
1067
+ * - React Query integration for caching, deduplication, and background updates
1068
+ * - Automatic disabling when ID is null/undefined
1069
+ * - Fallback to query with where clause if adapter doesn't support queryById
1070
+ * - Type-safe with generic type parameter
1071
+ *
1072
+ * @param table - The table name to query
1073
+ * @param id - The record ID (query is disabled if null/undefined)
1074
+ * @param options - Query options (select, enabled, staleTime)
1075
+ * @returns Query result with data, loading states, error, and refetch function
1076
+ *
1077
+ * @example
1078
+ * // Basic query by ID
1079
+ * const { data, isLoading, error } = useDbQueryById<Task>("Task", taskId);
1080
+ *
1081
+ * @example
1082
+ * // Query with relations
1083
+ * const { data, isLoading, error } = useDbQueryById<Task>("Task", taskId, {
1084
+ * select: "*, Project(*), AssignedUser:User(*)",
1085
+ * });
1086
+ *
1087
+ * @example
1088
+ * // Conditional query based on other state
1089
+ * const { data } = useDbQueryById<Project>("Project", selectedProjectId, {
1090
+ * enabled: hasPermission && !!selectedProjectId,
1091
+ * });
1092
+ *
1093
+ * @example
1094
+ * // With custom stale time
1095
+ * const { data } = useDbQueryById<User>("User", userId, {
1096
+ * staleTime: 60000, // 1 minute
1097
+ * });
1098
+ */
1099
+ declare function useDbQueryById<T = Record<string, unknown>>(table: string, id: string | number | null | undefined, options?: UseDbQueryByIdOptions): UseDbQueryByIdResult<T>;
1100
+
1101
+ /**
1102
+ * V3 useAdvanceQuery Hook
1103
+ *
1104
+ * Hybrid query hook that combines PowerSync (local SQLite) with edge function filtering.
1105
+ * - When NO filters active: Uses PowerSync for fast local queries that stay in sync
1106
+ * - When filters active: Uses edge function for complex filtering
1107
+ *
1108
+ * This provides the best of both worlds:
1109
+ * - Fast, reactive local queries via PowerSync
1110
+ * - Complex filtering, natural language queries, and aggregations via edge function
1111
+ *
1112
+ * @example
1113
+ * const [result, filters, setFilters] = useAdvanceQuery<Equipment[]>(
1114
+ * "EquipmentFixtureUnit",
1115
+ * {
1116
+ * select: "*, EquipmentFixtureUnitControl(*)",
1117
+ * where: { projectDatabaseId: 123 },
1118
+ * orderBy: [{ field: "unitNumber", direction: "asc" }],
1119
+ * filterKey: "equipment-filters",
1120
+ * }
1121
+ * );
1122
+ */
1123
+
1124
+ type FilterOperator = "=" | ">" | ">=" | "<" | "<=" | "contains" | "ilike" | "is" | "in" | "ai_search";
1125
+ interface Filter {
1126
+ id: string;
1127
+ field: string;
1128
+ op: FilterOperator;
1129
+ value: string | number | string[] | number[] | boolean | null;
1130
+ not?: boolean;
1131
+ similarity?: number;
1132
+ where?: string;
1133
+ display?: string;
1134
+ }
1135
+ interface FilterGroup {
1136
+ id: string;
1137
+ op: "AND" | "OR";
1138
+ filters: Array<Filter | FilterGroup>;
1139
+ not?: boolean;
1140
+ }
1141
+ interface Pagination {
1142
+ offset?: number;
1143
+ limit?: number;
1144
+ }
1145
+ interface Sort {
1146
+ field: string;
1147
+ direction: "asc" | "desc";
1148
+ }
1149
+ interface QueryState extends FilterGroup {
1150
+ pagination?: Pagination;
1151
+ sort?: Sort[];
1152
+ distinctOn?: string[];
1153
+ naturalLanguageQuery?: string;
1154
+ isReady: boolean;
1155
+ }
1156
+ interface ClarificationQuestion {
1157
+ question: string;
1158
+ suggestions: Array<{
1159
+ interpretation: string;
1160
+ field_path: string;
1161
+ example: string;
1162
+ confidence: number;
1163
+ }>;
1164
+ }
1165
+ interface UseAdvanceQueryOptions extends Omit<UseDbQueryOptions, "realtime"> {
1166
+ /** Key for persisting filter state (required for filter state persistence) */
1167
+ filterKey: string;
1168
+ /** Initial filter state */
1169
+ initialFilters?: QueryState;
1170
+ /** Timeout for edge function requests in ms (default: 15000) */
1171
+ timeout?: number;
1172
+ /** Count mode: "exact" | "estimated" | "" (default: "exact") */
1173
+ count?: "exact" | "estimated" | "";
1174
+ /**
1175
+ * Whether to enable real-time subscriptions
1176
+ * - PowerSync path: Uses watch() for reactive updates (default: true when PowerSync)
1177
+ * - Edge function path: Uses Supabase realtime to invalidate query on changes
1178
+ */
1179
+ realtime?: boolean;
1180
+ }
1181
+ interface UseAdvanceQueryResult<T> {
1182
+ data: T[] | undefined;
1183
+ isLoading: boolean;
1184
+ isPending: boolean;
1185
+ isFetching: boolean;
1186
+ isRefetching: boolean;
1187
+ isSuccess: boolean;
1188
+ isError: boolean;
1189
+ error: Error | null;
1190
+ refetch: () => Promise<void>;
1191
+ count?: number;
1192
+ clarification?: ClarificationQuestion;
1193
+ }
1194
+ /**
1195
+ * Hybrid advance query hook
1196
+ *
1197
+ * Uses PowerSync (local SQLite) when no filters are active for fast, reactive queries.
1198
+ * Falls back to edge function when filters are active for complex filtering.
1199
+ */
1200
+ declare function useAdvanceQuery<T extends TableIdentifier$1>(table: T, options: UseAdvanceQueryOptions): [
1201
+ UseAdvanceQueryResult<ResolveRowType$1<T>>,
1202
+ QueryState,
1203
+ Dispatch<SetStateAction<QueryState>>
1204
+ ];
1205
+ declare function useAdvanceQuery<T>(table: string, options: UseAdvanceQueryOptions): [
1206
+ UseAdvanceQueryResult<T>,
1207
+ QueryState,
1208
+ Dispatch<SetStateAction<QueryState>>
1209
+ ];
1210
+
1211
+ /**
1212
+ * V3 useDbInsert Hook
1213
+ *
1214
+ * React hook for inserting records into a table using the V3 adapter pattern.
1215
+ * Integrates with React Query for mutation management and cache invalidation.
1216
+ */
1217
+ /**
1218
+ * Options for useDbInsert hook
1219
+ */
1220
+ interface UseDbInsertOptions<T> {
1221
+ /** Callback when insert succeeds */
1222
+ onSuccess?: (data: T) => void;
1223
+ /** Callback when insert fails */
1224
+ onError?: (error: Error) => void;
1225
+ /** Tables to invalidate after successful insert */
1226
+ invalidateTables?: string[];
1227
+ }
1228
+ /**
1229
+ * Result from useDbInsert hook
1230
+ */
1231
+ interface UseDbInsertResult<T> {
1232
+ /** Trigger insert (fire and forget) */
1233
+ mutate: (data: Partial<T>) => void;
1234
+ /** Trigger insert and await result */
1235
+ mutateAsync: (data: Partial<T>) => Promise<T>;
1236
+ /** Whether mutation is in progress */
1237
+ isPending: boolean;
1238
+ /** Mutation error if any */
1239
+ error: Error | null;
1240
+ /** Reset mutation state */
1241
+ reset: () => void;
1242
+ /** Last successful data */
1243
+ data: T | undefined;
1244
+ }
1245
+ /**
1246
+ * Hook for inserting records into a table
1247
+ *
1248
+ * Uses the V3 adapter pattern to route inserts to the appropriate backend
1249
+ * (PowerSync, Supabase, or Cached) based on table configuration.
1250
+ *
1251
+ * @param table - The table name to insert into
1252
+ * @param options - Optional configuration for callbacks and cache invalidation
1253
+ * @returns Mutation result with mutate/mutateAsync functions
1254
+ *
1255
+ * @example
1256
+ * ```typescript
1257
+ * const { mutateAsync, isPending } = useDbInsert<Task>("Task");
1258
+ * const newTask = await mutateAsync({ title: "New Task", status: "pending" });
1259
+ * ```
1260
+ *
1261
+ * @example
1262
+ * ```typescript
1263
+ * // With options
1264
+ * const { mutate } = useDbInsert<Project>("Project", {
1265
+ * onSuccess: (data) => console.log("Created:", data),
1266
+ * onError: (error) => console.error("Failed:", error),
1267
+ * invalidateTables: ["Project", "ProjectSummary"],
1268
+ * });
1269
+ * ```
1270
+ */
1271
+ declare function useDbInsert<T = Record<string, unknown>>(table: string, options?: UseDbInsertOptions<T>): UseDbInsertResult<T>;
1272
+
1273
+ /**
1274
+ * V3 useDbUpdate Hook
1275
+ *
1276
+ * React hook for updating records in a table using the V3 adapter pattern.
1277
+ * Integrates with React Query for mutation management, cache invalidation,
1278
+ * and optional optimistic updates.
1279
+ */
1280
+ /**
1281
+ * Options for useDbUpdate hook
1282
+ */
1283
+ interface UseDbUpdateOptions<T> {
1284
+ /** Callback when update succeeds */
1285
+ onSuccess?: (data: T) => void;
1286
+ /** Callback when update fails */
1287
+ onError?: (error: Error) => void;
1288
+ /** Tables to invalidate after successful update */
1289
+ invalidateTables?: string[];
1290
+ /** Enable optimistic updates */
1291
+ optimistic?: boolean;
1292
+ }
1293
+ /**
1294
+ * Result from useDbUpdate hook
1295
+ */
1296
+ interface UseDbUpdateResult<T> {
1297
+ /** Trigger update (fire and forget) */
1298
+ mutate: (params: {
1299
+ id: string;
1300
+ data: Partial<T>;
1301
+ }) => void;
1302
+ /** Trigger update and await result */
1303
+ mutateAsync: (params: {
1304
+ id: string;
1305
+ data: Partial<T>;
1306
+ }) => Promise<T>;
1307
+ /** Whether mutation is in progress */
1308
+ isPending: boolean;
1309
+ /** Mutation error if any */
1310
+ error: Error | null;
1311
+ /** Reset mutation state */
1312
+ reset: () => void;
1313
+ /** Last successful data */
1314
+ data: T | undefined;
1315
+ }
1316
+ /**
1317
+ * Hook for updating records in a table
1318
+ *
1319
+ * Uses the V3 adapter pattern to route updates to the appropriate backend
1320
+ * (PowerSync, Supabase, or Cached) based on table configuration.
1321
+ *
1322
+ * @param table - The table name to update records in
1323
+ * @param options - Optional configuration for callbacks, cache invalidation, and optimistic updates
1324
+ * @returns Mutation result with mutate/mutateAsync functions
1325
+ *
1326
+ * @example
1327
+ * ```typescript
1328
+ * const { mutateAsync, isPending } = useDbUpdate<Task>("Task");
1329
+ * const updated = await mutateAsync({ id: taskId, data: { status: "completed" } });
1330
+ * ```
1331
+ *
1332
+ * @example
1333
+ * ```typescript
1334
+ * // With optimistic updates
1335
+ * const { mutate } = useDbUpdate<Project>("Project", {
1336
+ * optimistic: true,
1337
+ * onSuccess: (data) => console.log("Updated:", data),
1338
+ * onError: (error) => console.error("Failed:", error),
1339
+ * });
1340
+ * ```
1341
+ */
1342
+ declare function useDbUpdate<T = Record<string, unknown>>(table: string, options?: UseDbUpdateOptions<T>): UseDbUpdateResult<T>;
1343
+
1344
+ /**
1345
+ * V3 useDbUpsert Hook
1346
+ *
1347
+ * React hook for upserting (insert or update) records in a table using the V3 adapter pattern.
1348
+ * Integrates with React Query for mutation management and cache invalidation.
1349
+ */
1350
+ /**
1351
+ * Options for useDbUpsert hook
1352
+ */
1353
+ interface UseDbUpsertOptions<T> {
1354
+ /** Callback when upsert succeeds */
1355
+ onSuccess?: (data: T) => void;
1356
+ /** Callback when upsert fails */
1357
+ onError?: (error: Error) => void;
1358
+ /** Tables to invalidate after successful upsert */
1359
+ invalidateTables?: string[];
1360
+ }
1361
+ /**
1362
+ * Result from useDbUpsert hook
1363
+ */
1364
+ interface UseDbUpsertResult<T> {
1365
+ /** Trigger upsert (fire and forget) */
1366
+ mutate: (data: Partial<T>) => void;
1367
+ /** Trigger upsert and await result */
1368
+ mutateAsync: (data: Partial<T>) => Promise<T>;
1369
+ /** Whether mutation is in progress */
1370
+ isPending: boolean;
1371
+ /** Mutation error if any */
1372
+ error: Error | null;
1373
+ /** Reset mutation state */
1374
+ reset: () => void;
1375
+ /** Last successful data */
1376
+ data: T | undefined;
1377
+ }
1378
+ /**
1379
+ * Hook for upserting (insert or update) records in a table
1380
+ *
1381
+ * Uses the V3 adapter pattern to route upserts to the appropriate backend
1382
+ * (PowerSync, Supabase, or Cached) based on table configuration.
1383
+ *
1384
+ * If the record has an ID and exists, it will be updated.
1385
+ * Otherwise, a new record will be inserted.
1386
+ *
1387
+ * @param table - The table name to upsert into
1388
+ * @param options - Optional configuration for callbacks and cache invalidation
1389
+ * @returns Mutation result with mutate/mutateAsync functions
1390
+ *
1391
+ * @example
1392
+ * ```typescript
1393
+ * const { mutateAsync, isPending } = useDbUpsert<Task>("Task");
1394
+ * const task = await mutateAsync({ id: existingId, title: "Updated Title" });
1395
+ * ```
1396
+ *
1397
+ * @example
1398
+ * ```typescript
1399
+ * // Insert if no ID, update if ID exists
1400
+ * const { mutate } = useDbUpsert<Setting>("Setting", {
1401
+ * onSuccess: (data) => console.log("Upserted:", data),
1402
+ * invalidateTables: ["Setting", "UserPreferences"],
1403
+ * });
1404
+ *
1405
+ * // This will insert (no id)
1406
+ * mutate({ key: "theme", value: "dark" });
1407
+ *
1408
+ * // This will update (has id)
1409
+ * mutate({ id: "setting-123", key: "theme", value: "light" });
1410
+ * ```
1411
+ */
1412
+ declare function useDbUpsert<T = Record<string, unknown>>(table: string, options?: UseDbUpsertOptions<T>): UseDbUpsertResult<T>;
1413
+
1414
+ /**
1415
+ * V3 useDbDelete Hook
1416
+ *
1417
+ * React hook for deleting records from a table using the V3 adapter pattern.
1418
+ * Integrates with React Query for mutation management, cache invalidation,
1419
+ * and optional optimistic deletes.
1420
+ */
1421
+ /**
1422
+ * Options for useDbDelete hook
1423
+ */
1424
+ interface UseDbDeleteOptions {
1425
+ /** Callback when delete succeeds */
1426
+ onSuccess?: () => void;
1427
+ /** Callback when delete fails */
1428
+ onError?: (error: Error) => void;
1429
+ /** Tables to invalidate after successful delete */
1430
+ invalidateTables?: string[];
1431
+ /** Enable optimistic delete */
1432
+ optimistic?: boolean;
1433
+ }
1434
+ /**
1435
+ * Result from useDbDelete hook
1436
+ */
1437
+ interface UseDbDeleteResult {
1438
+ /** Trigger delete (fire and forget) */
1439
+ mutate: (id: string) => void;
1440
+ /** Trigger delete and await completion */
1441
+ mutateAsync: (id: string) => Promise<void>;
1442
+ /** Whether mutation is in progress */
1443
+ isPending: boolean;
1444
+ /** Mutation error if any */
1445
+ error: Error | null;
1446
+ /** Reset mutation state */
1447
+ reset: () => void;
1448
+ }
1449
+ /**
1450
+ * Hook for deleting records from a table
1451
+ *
1452
+ * Uses the V3 adapter pattern to route deletes to the appropriate backend
1453
+ * (PowerSync, Supabase, or Cached) based on table configuration.
1454
+ *
1455
+ * @param table - The table name to delete from
1456
+ * @param options - Optional configuration for callbacks, cache invalidation, and optimistic deletes
1457
+ * @returns Mutation result with mutate/mutateAsync functions
1458
+ *
1459
+ * @example
1460
+ * ```typescript
1461
+ * const { mutateAsync, isPending } = useDbDelete("Task");
1462
+ * await mutateAsync(taskId);
1463
+ * ```
1464
+ *
1465
+ * @example
1466
+ * ```typescript
1467
+ * // With optimistic delete for instant UI feedback
1468
+ * const { mutate } = useDbDelete("Comment", {
1469
+ * optimistic: true,
1470
+ * onSuccess: () => console.log("Deleted successfully"),
1471
+ * onError: (error) => console.error("Delete failed:", error),
1472
+ * invalidateTables: ["Comment", "Post"],
1473
+ * });
1474
+ *
1475
+ * // Immediately removes from UI, rolls back on failure
1476
+ * mutate(commentId);
1477
+ * ```
1478
+ */
1479
+ declare function useDbDelete(table: string, options?: UseDbDeleteOptions): UseDbDeleteResult;
1480
+
1481
+ /**
1482
+ * V3 useDbInfiniteQuery Hook
1483
+ *
1484
+ * React hook for querying records with infinite scroll pagination.
1485
+ * Works identically whether PowerSync or Supabase is the backend.
1486
+ * Uses React Query's useInfiniteQuery for state management and caching.
1487
+ *
1488
+ * Types are automatically inferred from table names when you augment
1489
+ * the DatabaseTypes interface with your app's Database type.
1490
+ *
1491
+ * @example
1492
+ * // In your app's types/db.d.ts:
1493
+ * declare module "@pol-studios/db" {
1494
+ * interface DatabaseTypes {
1495
+ * database: import("@/database.types").Database;
1496
+ * }
1497
+ * }
1498
+ *
1499
+ * // Then usage auto-infers types:
1500
+ * const { data, fetchNextPage, hasNextPage } = useDbInfiniteQuery("EquipmentFixtureUnit", {
1501
+ * pageSize: 20,
1502
+ * orderBy: [{ field: "createdAt", direction: "desc" }],
1503
+ * });
1504
+ */
1505
+
1506
+ /**
1507
+ * Augment this interface in your app to enable automatic type inference.
1508
+ */
1509
+ interface DatabaseTypes {
1510
+ }
1511
+ /**
1512
+ * The configured Database type, or a generic fallback
1513
+ */
1514
+ type ConfiguredDatabase = DatabaseTypes extends {
1515
+ database: infer DB;
1516
+ } ? DB : GenericSchema;
1517
+ /**
1518
+ * Generic schema structure for fallback
1519
+ */
1520
+ type GenericSchema = {
1521
+ public: {
1522
+ Tables: Record<string, {
1523
+ Row: Record<string, unknown>;
1524
+ }>;
1525
+ Views: Record<string, {
1526
+ Row: Record<string, unknown>;
1527
+ }>;
1528
+ };
1529
+ [schema: string]: {
1530
+ Tables: Record<string, {
1531
+ Row: Record<string, unknown>;
1532
+ }>;
1533
+ Views?: Record<string, {
1534
+ Row: Record<string, unknown>;
1535
+ }>;
1536
+ };
1537
+ };
1538
+ /**
1539
+ * Default schema from Database (usually "public")
1540
+ */
1541
+ type DefaultSchema = ConfiguredDatabase extends {
1542
+ public: infer S;
1543
+ } ? S : never;
1544
+ /**
1545
+ * Extract all valid table names from the default schema
1546
+ */
1547
+ type PublicTableNames = DefaultSchema extends {
1548
+ Tables: infer T;
1549
+ } ? keyof T & string : string;
1550
+ /**
1551
+ * Extract all valid schema names
1552
+ */
1553
+ type SchemaNames = keyof ConfiguredDatabase & string;
1554
+ /**
1555
+ * Extract table names for a specific schema
1556
+ */
1557
+ type SchemaTableNames<S extends string> = ConfiguredDatabase extends {
1558
+ [K in S]: {
1559
+ Tables: infer T;
1560
+ };
1561
+ } ? keyof T & string : string;
1562
+ /**
1563
+ * Build dot notation strings for all schema.table combinations
1564
+ */
1565
+ type SchemaDotTable = {
1566
+ [S in SchemaNames]: S extends "public" ? never : `${S}.${SchemaTableNames<S>}`;
1567
+ }[SchemaNames];
1568
+ /**
1569
+ * Table identifier - provides autocomplete for valid table names
1570
+ */
1571
+ type TableIdentifier = PublicTableNames | SchemaDotTable | {
1572
+ [S in Exclude<SchemaNames, "public">]: {
1573
+ schema: S;
1574
+ table: SchemaTableNames<S>;
1575
+ };
1576
+ }[Exclude<SchemaNames, "public">];
1577
+ /**
1578
+ * Resolve row type from a table identifier
1579
+ */
1580
+ type ResolveRowType<T extends TableIdentifier> = T extends string ? T extends `${infer Schema}.${infer Table}` ? ConfiguredDatabase extends {
1581
+ [K in Schema]: {
1582
+ Tables: {
1583
+ [K2 in Table]: {
1584
+ Row: infer R;
1585
+ };
1586
+ };
1587
+ };
1588
+ } ? R : Record<string, unknown> : DefaultSchema extends {
1589
+ Tables: {
1590
+ [K in T]: {
1591
+ Row: infer R;
1592
+ };
1593
+ };
1594
+ } ? R : DefaultSchema extends {
1595
+ Views: {
1596
+ [K in T]: {
1597
+ Row: infer R;
1598
+ };
1599
+ };
1600
+ } ? R : Record<string, unknown> : T extends {
1601
+ schema: infer S;
1602
+ table: infer TN;
1603
+ } ? S extends string ? TN extends string ? ConfiguredDatabase extends {
1604
+ [K in S]: {
1605
+ Tables: {
1606
+ [K2 in TN]: {
1607
+ Row: infer R;
1608
+ };
1609
+ };
1610
+ };
1611
+ } ? R : Record<string, unknown> : Record<string, unknown> : Record<string, unknown> : Record<string, unknown>;
1612
+ /**
1613
+ * Options for useDbInfiniteQuery hook
1614
+ */
1615
+ interface UseDbInfiniteQueryOptions extends Omit<QueryOptions, "limit" | "offset" | "enabled"> {
1616
+ /** Whether the query is enabled (default: true) */
1617
+ enabled?: boolean;
1618
+ /** React Query stale time in ms (default: 30000) */
1619
+ staleTime?: number;
1620
+ /** Whether to refetch on window focus (default: true) */
1621
+ refetchOnWindowFocus?: boolean;
1622
+ /** Number of items per page (default: 50) */
1623
+ pageSize?: number;
1624
+ /** Text to search for */
1625
+ searchText?: string;
1626
+ /** Fields to search in when searchText is provided */
1627
+ searchFields?: string[];
1628
+ }
1629
+ /**
1630
+ * Result from useDbInfiniteQuery hook
1631
+ */
1632
+ interface UseDbInfiniteQueryResult<T> {
1633
+ /** Flattened array of all loaded data */
1634
+ data: T[] | undefined;
1635
+ /** Whether query is loading (initial load) */
1636
+ isLoading: boolean;
1637
+ /** Whether query is in pending state */
1638
+ isPending: boolean;
1639
+ /** Whether query is currently fetching (including refetch) */
1640
+ isFetching: boolean;
1641
+ /** Query error if any */
1642
+ error: Error | null;
1643
+ /** Function to fetch the next page */
1644
+ fetchNextPage: () => Promise<void>;
1645
+ /** Whether there are more pages to load */
1646
+ hasNextPage: boolean;
1647
+ /** Whether currently fetching the next page */
1648
+ isFetchingNextPage: boolean;
1649
+ /** Total count of items (if available) */
1650
+ count?: number;
1651
+ /** Refetch all pages */
1652
+ refetch: () => Promise<void>;
1653
+ }
1654
+ /**
1655
+ * Hook for querying records with infinite scroll pagination
1656
+ *
1657
+ * @param table - Table name (string) or { schema, table } object
1658
+ * @param options - Query options (select, where, orderBy, pageSize, searchText, etc.)
1659
+ * @returns Query result with data, loading states, pagination controls, and refetch function
1660
+ *
1661
+ * @example
1662
+ * // Basic infinite query - types auto-inferred from table name
1663
+ * const { data, fetchNextPage, hasNextPage } = useDbInfiniteQuery("EquipmentFixtureUnit");
1664
+ *
1665
+ * @example
1666
+ * // With search and pagination
1667
+ * const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useDbInfiniteQuery("Task", {
1668
+ * pageSize: 20,
1669
+ * searchText: searchQuery,
1670
+ * searchFields: ["name", "description"],
1671
+ * orderBy: [{ field: "createdAt", direction: "desc" }],
1672
+ * });
1673
+ *
1674
+ * @example
1675
+ * // In a FlatList or similar
1676
+ * <FlatList
1677
+ * data={data}
1678
+ * onEndReached={() => hasNextPage && fetchNextPage()}
1679
+ * ListFooterComponent={isFetchingNextPage ? <Spinner /> : null}
1680
+ * />
1681
+ */
1682
+ declare function useDbInfiniteQuery<T extends TableIdentifier>(table: T, options?: UseDbInfiniteQueryOptions): UseDbInfiniteQueryResult<ResolveRowType<T>>;
1683
+ /**
1684
+ * Overload for explicit type parameter (backwards compatibility)
1685
+ */
1686
+ declare function useDbInfiniteQuery<T>(table: string, options?: UseDbInfiniteQueryOptions): UseDbInfiniteQueryResult<T>;
1687
+
1688
+ /**
1689
+ * V3 useDbCount Hook
1690
+ *
1691
+ * React hook for counting records in a table.
1692
+ * Works with the data layer using either PowerSync or Supabase backend.
1693
+ */
1694
+
1695
+ /**
1696
+ * Options for useDbCount hook
1697
+ */
1698
+ interface UseDbCountOptions {
1699
+ /** Filter conditions */
1700
+ where?: WhereClause;
1701
+ /** Whether the query is enabled (default: true) */
1702
+ enabled?: boolean;
1703
+ /** React Query stale time in ms (default: 30000) */
1704
+ staleTime?: number;
1705
+ }
1706
+ /**
1707
+ * Result from useDbCount hook
1708
+ */
1709
+ interface UseDbCountResult {
1710
+ /** The count value */
1711
+ count: number | undefined;
1712
+ /** Whether query is loading */
1713
+ isLoading: boolean;
1714
+ /** Whether query is fetching */
1715
+ isFetching: boolean;
1716
+ /** Query error if any */
1717
+ error: Error | null;
1718
+ /** Refetch the count */
1719
+ refetch: () => Promise<void>;
1720
+ }
1721
+ /**
1722
+ * Hook for counting records in a table
1723
+ *
1724
+ * @param table - The table name to count
1725
+ * @param options - Count options (where filter, enabled)
1726
+ * @returns Count result with loading states
1727
+ *
1728
+ * @example
1729
+ * // Simple count
1730
+ * const { count, isLoading } = useDbCount("EquipmentFixtureUnit");
1731
+ *
1732
+ * @example
1733
+ * // Count with filter
1734
+ * const { count } = useDbCount("EquipmentFixtureUnit", {
1735
+ * where: { projectDatabaseId: 123 },
1736
+ * });
1737
+ */
1738
+ declare function useDbCount(table: string, options?: UseDbCountOptions): UseDbCountResult;
1739
+
1740
+ export { type UseDbDeleteResult as $, type AdapterQueryResult as A, BackendStatus as B, type CapableDataAdapter as C, type DataLayerContextValue as D, type Pagination as E, type Filter as F, type Sort as G, type ClarificationQuestion as H, type UseAdvanceQueryOptions as I, type UseAdvanceQueryResult as J, useDbInsert as K, type UseDbInsertOptions as L, type UseDbInsertResult as M, useDbUpdate as N, type UseDbUpdateOptions as O, type PublicTableNames$1 as P, type QueryState as Q, type ResolveRowType$1 as R, type SchemaNames$1 as S, type TableDataAdapter as T, type UseDbQueryOptions as U, type UseDbUpdateResult as V, useDbUpsert as W, type UseDbUpsertOptions as X, type UseDbUpsertResult as Y, useDbDelete as Z, type UseDbDeleteOptions as _, type AdapterConfig as a, useDbInfiniteQuery as a0, type UseDbInfiniteQueryOptions as a1, type UseDbInfiniteQueryResult as a2, useDbCount as a3, type UseDbCountOptions as a4, type UseDbCountResult as a5, DataLayerContext as a6, type DataLayerStatus as a7, type AdapterFactory as b, type AdapterCapabilities as c, type AdapterDependencies as d, type AdapterStrategyType as e, ADAPTER_STRATEGIES as f, AdapterRegistry as g, createAdapterRegistry as h, AdapterAutoDetector as i, createAdapterAutoDetector as j, type AutoDetectionResult as k, type AutoDetectorOptions as l, type BackendChangeListener as m, useDataLayerOptional as n, useDbQuery as o, type DatabaseTypes$1 as p, type SchemaTableNames$1 as q, type TableIdentifier$1 as r, type UseDbQueryResult as s, useDbQueryById as t, useDataLayer as u, type UseDbQueryByIdOptions as v, type UseDbQueryByIdResult as w, useAdvanceQuery as x, type FilterGroup as y, type FilterOperator as z };