@pol-studios/db 1.0.9 → 1.0.10

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 (80) hide show
  1. package/dist/auth/context.js +21 -12786
  2. package/dist/auth/context.js.map +1 -1
  3. package/dist/auth/guards.js +12 -7640
  4. package/dist/auth/guards.js.map +1 -1
  5. package/dist/auth/hooks.js +25 -10591
  6. package/dist/auth/hooks.js.map +1 -1
  7. package/dist/auth/index.js +43 -13008
  8. package/dist/auth/index.js.map +1 -1
  9. package/dist/canvas-75Y7XMF3.js +1541 -0
  10. package/dist/canvas-75Y7XMF3.js.map +1 -0
  11. package/dist/chunk-2IFGILT3.js +532 -0
  12. package/dist/chunk-2IFGILT3.js.map +1 -0
  13. package/dist/chunk-3M2U6TXH.js +928 -0
  14. package/dist/chunk-3M2U6TXH.js.map +1 -0
  15. package/dist/chunk-3PJTNH2L.js +2778 -0
  16. package/dist/chunk-3PJTNH2L.js.map +1 -0
  17. package/dist/chunk-5ZYAEGCJ.js +416 -0
  18. package/dist/chunk-5ZYAEGCJ.js.map +1 -0
  19. package/dist/chunk-7HG6G25H.js +710 -0
  20. package/dist/chunk-7HG6G25H.js.map +1 -0
  21. package/dist/chunk-7XT7K4QT.js +2687 -0
  22. package/dist/chunk-7XT7K4QT.js.map +1 -0
  23. package/dist/chunk-AWFMICFV.js +158 -0
  24. package/dist/chunk-AWFMICFV.js.map +1 -0
  25. package/dist/chunk-BRTW7CO5.js +1467 -0
  26. package/dist/chunk-BRTW7CO5.js.map +1 -0
  27. package/dist/chunk-EL45Z26M.js +4194 -0
  28. package/dist/chunk-EL45Z26M.js.map +1 -0
  29. package/dist/chunk-ERGF2FCE.js +903 -0
  30. package/dist/chunk-ERGF2FCE.js.map +1 -0
  31. package/dist/chunk-GK7B66LY.js +135 -0
  32. package/dist/chunk-GK7B66LY.js.map +1 -0
  33. package/dist/chunk-GQI6WJGI.js +172 -0
  34. package/dist/chunk-GQI6WJGI.js.map +1 -0
  35. package/dist/chunk-H6365JPC.js +1858 -0
  36. package/dist/chunk-H6365JPC.js.map +1 -0
  37. package/dist/chunk-J4ZVCXZ4.js +1 -0
  38. package/dist/chunk-J4ZVCXZ4.js.map +1 -0
  39. package/dist/chunk-JUVE3DWY.js +433 -0
  40. package/dist/chunk-JUVE3DWY.js.map +1 -0
  41. package/dist/chunk-O3K7R32P.js +7555 -0
  42. package/dist/chunk-O3K7R32P.js.map +1 -0
  43. package/dist/chunk-P4UZ7IXC.js +42 -0
  44. package/dist/chunk-P4UZ7IXC.js.map +1 -0
  45. package/dist/chunk-SEY5UO2T.js +89 -0
  46. package/dist/chunk-SEY5UO2T.js.map +1 -0
  47. package/dist/chunk-USJYMRUO.js +86 -0
  48. package/dist/chunk-USJYMRUO.js.map +1 -0
  49. package/dist/chunk-XX3IWSPM.js +189 -0
  50. package/dist/chunk-XX3IWSPM.js.map +1 -0
  51. package/dist/chunk-Y3INY2CS.js +14 -0
  52. package/dist/chunk-Y3INY2CS.js.map +1 -0
  53. package/dist/chunk-ZTSBF536.js +1927 -0
  54. package/dist/chunk-ZTSBF536.js.map +1 -0
  55. package/dist/client/index.js +13 -141
  56. package/dist/client/index.js.map +1 -1
  57. package/dist/dist-NDNRSNOG.js +521 -0
  58. package/dist/dist-NDNRSNOG.js.map +1 -0
  59. package/dist/gen/index.js +186 -1280
  60. package/dist/gen/index.js.map +1 -1
  61. package/dist/hooks/index.js +21 -8694
  62. package/dist/hooks/index.js.map +1 -1
  63. package/dist/index.js +403 -47848
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.native.js +400 -25048
  66. package/dist/index.native.js.map +1 -1
  67. package/dist/index.web.js +576 -43769
  68. package/dist/index.web.js.map +1 -1
  69. package/dist/mutation/index.js +44 -4675
  70. package/dist/mutation/index.js.map +1 -1
  71. package/dist/parser/index.js +45 -3697
  72. package/dist/parser/index.js.map +1 -1
  73. package/dist/pdf-3TIGQRLA.js +20336 -0
  74. package/dist/pdf-3TIGQRLA.js.map +1 -0
  75. package/dist/query/index.js +31 -13175
  76. package/dist/query/index.js.map +1 -1
  77. package/dist/realtime/index.js +45 -12431
  78. package/dist/realtime/index.js.map +1 -1
  79. package/dist/types/index.js +9 -0
  80. package/package.json +3 -3
@@ -0,0 +1,928 @@
1
+ import {
2
+ getSupabaseUrl
3
+ } from "./chunk-Y3INY2CS.js";
4
+ import {
5
+ omit
6
+ } from "./chunk-O3K7R32P.js";
7
+ import {
8
+ useSupabase
9
+ } from "./chunk-AWFMICFV.js";
10
+
11
+ // src/providers/DataLayerContext.ts
12
+ import { createContext } from "react";
13
+ var DataLayerContext = createContext(null);
14
+ DataLayerContext.displayName = "DataLayerContext";
15
+
16
+ // src/hooks/useDataLayer.ts
17
+ import { useContext } from "react";
18
+ function useDataLayer() {
19
+ const context = useContext(DataLayerContext);
20
+ if (!context) {
21
+ throw new Error(
22
+ "useDataLayer must be used within a DataLayerProvider. Make sure you have wrapped your app with <DataLayerProvider>."
23
+ );
24
+ }
25
+ return context;
26
+ }
27
+ function useDataLayerOptional() {
28
+ return useContext(DataLayerContext);
29
+ }
30
+
31
+ // src/hooks/useDbQuery.ts
32
+ import { useMemo, useEffect, useCallback } from "react";
33
+ import { useQuery } from "@tanstack/react-query";
34
+ function buildQueryKey(table, options, isInitialized, backend) {
35
+ return [
36
+ "v3",
37
+ "query",
38
+ table,
39
+ isInitialized,
40
+ backend,
41
+ options.select ?? "*",
42
+ JSON.stringify(options.where ?? {}),
43
+ JSON.stringify(options.orderBy ?? []),
44
+ options.limit,
45
+ options.offset
46
+ ];
47
+ }
48
+ function serializeQueryOptions(options) {
49
+ return JSON.stringify({
50
+ select: options.select,
51
+ where: options.where,
52
+ orderBy: options.orderBy,
53
+ limit: options.limit,
54
+ offset: options.offset
55
+ });
56
+ }
57
+ function resolveTableName(table) {
58
+ if (typeof table === "string") {
59
+ return table;
60
+ }
61
+ return `${table.schema}.${table.table}`;
62
+ }
63
+ function useDbQuery(table, options = {}) {
64
+ const tableName = typeof table === "string" ? table : resolveTableName(table);
65
+ const { registry, status, queryClient } = useDataLayer();
66
+ const isPowerSync = status.currentBackend === "powersync";
67
+ const {
68
+ enabled = true,
69
+ staleTime = isPowerSync ? 0 : 3e4,
70
+ gcTime = 3e5,
71
+ // 5 minutes - keep in memory for instant display while refetching
72
+ refetchOnWindowFocus = true,
73
+ refetchOnMount = isPowerSync ? "always" : true,
74
+ realtime = isPowerSync,
75
+ // Enable real-time subscriptions by default for PowerSync
76
+ ...queryOptions
77
+ } = options;
78
+ const adapter = useMemo(() => {
79
+ if (!status.isInitialized) return null;
80
+ try {
81
+ return registry.getAdapter(tableName);
82
+ } catch {
83
+ return null;
84
+ }
85
+ }, [registry, tableName, status.isInitialized, status.currentBackend]);
86
+ const queryKey = useMemo(
87
+ () => buildQueryKey(tableName, options, status.isInitialized, status.currentBackend),
88
+ [tableName, serializeQueryOptions(options), status.isInitialized, status.currentBackend]
89
+ );
90
+ const memoizedQueryOptions = useMemo(
91
+ () => ({
92
+ select: queryOptions.select,
93
+ where: queryOptions.where,
94
+ orderBy: queryOptions.orderBy,
95
+ limit: queryOptions.limit,
96
+ offset: queryOptions.offset
97
+ }),
98
+ [serializeQueryOptions(queryOptions)]
99
+ );
100
+ const queryFn = useCallback(async () => {
101
+ if (!adapter) {
102
+ throw new Error(`Adapter not available for table: ${tableName}`);
103
+ }
104
+ const result = await adapter.query(tableName, memoizedQueryOptions);
105
+ return result;
106
+ }, [adapter, tableName, memoizedQueryOptions]);
107
+ const query = useQuery({
108
+ queryKey,
109
+ queryFn,
110
+ enabled: enabled && status.isInitialized && adapter !== null,
111
+ staleTime,
112
+ gcTime,
113
+ refetchOnWindowFocus,
114
+ refetchOnMount
115
+ });
116
+ useEffect(() => {
117
+ if (!realtime || !adapter?.subscribe || !status.isInitialized) {
118
+ return;
119
+ }
120
+ const unsubscribe = adapter.subscribe(
121
+ tableName,
122
+ memoizedQueryOptions,
123
+ (data) => {
124
+ queryClient.setQueryData(queryKey, { data, count: data.length });
125
+ }
126
+ );
127
+ return () => {
128
+ unsubscribe();
129
+ };
130
+ }, [
131
+ realtime,
132
+ adapter,
133
+ tableName,
134
+ memoizedQueryOptions,
135
+ queryClient,
136
+ queryKey,
137
+ status.isInitialized
138
+ ]);
139
+ const refetch = useCallback(async () => {
140
+ await query.refetch();
141
+ }, [query]);
142
+ return {
143
+ data: query.data?.data,
144
+ isLoading: query.isLoading,
145
+ isPending: query.isPending,
146
+ isFetching: query.isFetching,
147
+ isRefetching: query.isFetching,
148
+ // Alias for V2 compatibility
149
+ isSuccess: query.isSuccess,
150
+ isError: query.isError,
151
+ error: query.error,
152
+ refetch,
153
+ count: query.data?.count,
154
+ isStale: query.isStale,
155
+ dataUpdatedAt: query.dataUpdatedAt ?? null
156
+ };
157
+ }
158
+
159
+ // src/hooks/useDbQueryById.ts
160
+ import { useMemo as useMemo2, useCallback as useCallback2 } from "react";
161
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
162
+ function buildQueryKey2(table, id, select) {
163
+ return ["v3", "queryById", table, id, select ?? "*"];
164
+ }
165
+ function useDbQueryById(table, id, options = {}) {
166
+ const { registry, status } = useDataLayer();
167
+ const { select, enabled = id != null, staleTime = 3e4 } = options;
168
+ const adapter = useMemo2(() => {
169
+ if (!status.isInitialized) return null;
170
+ try {
171
+ return registry.getAdapter(table);
172
+ } catch {
173
+ return null;
174
+ }
175
+ }, [registry, table, status.isInitialized, status.currentBackend]);
176
+ const queryKey = useMemo2(
177
+ () => buildQueryKey2(table, id, select),
178
+ [table, id, select]
179
+ );
180
+ const queryFn = useCallback2(async () => {
181
+ if (!adapter) {
182
+ throw new Error(`Adapter not available for table: ${table}`);
183
+ }
184
+ if (id == null) {
185
+ return null;
186
+ }
187
+ if (adapter.queryById) {
188
+ return adapter.queryById(table, String(id), { select });
189
+ }
190
+ const result = await adapter.query(table, {
191
+ select,
192
+ where: { id },
193
+ limit: 1
194
+ });
195
+ return result.data[0] ?? null;
196
+ }, [adapter, table, id, select]);
197
+ const query = useQuery2({
198
+ queryKey,
199
+ queryFn,
200
+ enabled: enabled && status.isInitialized && adapter !== null && id != null,
201
+ staleTime
202
+ });
203
+ const refetch = useCallback2(async () => {
204
+ await query.refetch();
205
+ }, [query]);
206
+ return {
207
+ data: query.data,
208
+ isLoading: query.isLoading,
209
+ isPending: query.isPending,
210
+ isFetching: query.isFetching,
211
+ error: query.error,
212
+ refetch
213
+ };
214
+ }
215
+
216
+ // src/hooks/useAdvanceQuery.ts
217
+ import {
218
+ useCallback as useCallback3,
219
+ useMemo as useMemo3,
220
+ useState,
221
+ useEffect as useEffect2
222
+ } from "react";
223
+ import { useQuery as useQuery3 } from "@tanstack/react-query";
224
+ import { useSessionStorageState } from "@pol-studios/hooks/storage";
225
+ var createDefaultFilterState = () => ({
226
+ id: "root",
227
+ op: "AND",
228
+ filters: [],
229
+ pagination: void 0,
230
+ sort: [],
231
+ isReady: true
232
+ });
233
+ function useAdvanceQuery(table, options) {
234
+ const tableName = typeof table === "string" ? table : `${table.schema}.${table.table}`;
235
+ const { registry, status, queryClient } = useDataLayer();
236
+ const supabase = useSupabase();
237
+ const {
238
+ filterKey,
239
+ initialFilters,
240
+ enabled = true,
241
+ timeout = 15e3,
242
+ count = "exact",
243
+ realtime,
244
+ select,
245
+ where,
246
+ orderBy,
247
+ limit,
248
+ offset,
249
+ ...restOptions
250
+ } = options;
251
+ const isPowerSync = status.currentBackend === "powersync";
252
+ const realtimeEnabled = realtime ?? isPowerSync;
253
+ const defaultFilterState = useMemo3(
254
+ () => initialFilters ?? createDefaultFilterState(),
255
+ // eslint-disable-next-line react-hooks/exhaustive-deps
256
+ []
257
+ // Only compute once
258
+ );
259
+ const [filtersRaw, setFiltersRaw] = useSessionStorageState(
260
+ filterKey,
261
+ defaultFilterState
262
+ );
263
+ const filters = filtersRaw ?? defaultFilterState;
264
+ const setFilters = useCallback3(
265
+ (action) => {
266
+ if (typeof action === "function") {
267
+ setFiltersRaw((prev) => action(prev ?? defaultFilterState));
268
+ } else {
269
+ setFiltersRaw(action);
270
+ }
271
+ },
272
+ [setFiltersRaw, defaultFilterState]
273
+ );
274
+ const hasAdvancedFilters = useMemo3(
275
+ () => (filters?.filters?.length ?? 0) > 0 || !!filters?.naturalLanguageQuery,
276
+ [filters?.filters?.length, filters?.naturalLanguageQuery]
277
+ );
278
+ const usePowerSyncPath = !hasAdvancedFilters && isPowerSync;
279
+ const powerSyncOrderBy = useMemo3(() => {
280
+ if (filters?.sort && filters.sort.length > 0) {
281
+ return filters.sort.map((s) => ({
282
+ field: s.field,
283
+ direction: s.direction
284
+ }));
285
+ }
286
+ return orderBy;
287
+ }, [filters?.sort, orderBy]);
288
+ const powerSyncResult = useDbQuery(table, {
289
+ select,
290
+ where,
291
+ orderBy: powerSyncOrderBy,
292
+ limit: filters?.pagination?.limit ?? limit,
293
+ offset: filters?.pagination?.offset ?? offset,
294
+ enabled: enabled && usePowerSyncPath && filters?.isReady !== false,
295
+ realtime: realtimeEnabled
296
+ // Enable watch() subscriptions for reactive updates
297
+ });
298
+ const [extraData, setExtraData] = useState({});
299
+ const edgeFunctionQueryKey = useMemo3(
300
+ () => [
301
+ "v3",
302
+ "advance-query",
303
+ tableName,
304
+ select,
305
+ JSON.stringify(where),
306
+ JSON.stringify(filters),
307
+ status.currentBackend
308
+ ],
309
+ [tableName, select, where, filters, status.currentBackend]
310
+ );
311
+ const edgeFunctionResult = useQuery3({
312
+ queryKey: edgeFunctionQueryKey,
313
+ queryFn: async ({ signal }) => {
314
+ const { data: { session } } = await supabase.auth.getSession();
315
+ if (!session?.access_token) {
316
+ throw new Error("No active session");
317
+ }
318
+ const controller = new AbortController();
319
+ signal.addEventListener("abort", () => controller.abort());
320
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
321
+ try {
322
+ const filterBody = {
323
+ id: filters.id || "root",
324
+ op: filters.op || "AND",
325
+ not: filters.not,
326
+ filters: filters.filters || []
327
+ };
328
+ const baseFilters = [];
329
+ if (where) {
330
+ Object.entries(where).forEach(([field, value]) => {
331
+ if (value !== void 0 && value !== null) {
332
+ if (typeof value === "object" && "in" in value) {
333
+ baseFilters.push({
334
+ id: `base-${field}`,
335
+ field,
336
+ op: "in",
337
+ value: value.in
338
+ });
339
+ } else {
340
+ baseFilters.push({
341
+ id: `base-${field}`,
342
+ field,
343
+ op: "=",
344
+ value
345
+ });
346
+ }
347
+ }
348
+ });
349
+ }
350
+ const combinedFilters = [...baseFilters, ...filterBody.filters];
351
+ const currentKey = `${tableName}${select}${JSON.stringify(omit(filters, ["pagination", "isReady"]))}`;
352
+ const res = await fetch(
353
+ `${getSupabaseUrl()}/functions/v1/query?forceDenoVersion=2`,
354
+ {
355
+ method: "POST",
356
+ headers: {
357
+ "Content-Type": "application/json",
358
+ Authorization: `Bearer ${session.access_token}`
359
+ },
360
+ body: JSON.stringify({
361
+ table: tableName,
362
+ schema: "public",
363
+ select: select ?? "*",
364
+ filters: {
365
+ id: filterBody.id,
366
+ op: filterBody.op,
367
+ not: filterBody.not,
368
+ filters: combinedFilters
369
+ },
370
+ pagination: filters.pagination,
371
+ sort: filters.sort || orderBy?.map((o) => ({
372
+ field: o.field,
373
+ direction: o.direction
374
+ })),
375
+ distinctOn: filters.distinctOn,
376
+ naturalLanguageQuery: filters.naturalLanguageQuery,
377
+ count: currentKey === extraData.key ? "" : count
378
+ }),
379
+ signal: controller.signal
380
+ }
381
+ );
382
+ if (!res.ok) {
383
+ const errorData = await res.json();
384
+ const errorMessage = typeof errorData?.error === "string" ? errorData.error : errorData?.error?.message || errorData?.message || "Query failed";
385
+ throw new Error(errorMessage);
386
+ }
387
+ const result2 = await res.json();
388
+ if (result2.clarification) {
389
+ return {
390
+ data: [],
391
+ count: 0,
392
+ clarification: result2.clarification
393
+ };
394
+ }
395
+ setExtraData((prev) => ({
396
+ count: prev.key === currentKey ? prev.count : result2.count,
397
+ key: currentKey
398
+ }));
399
+ return {
400
+ data: result2.data,
401
+ count: result2.count
402
+ };
403
+ } finally {
404
+ clearTimeout(timeoutId);
405
+ }
406
+ },
407
+ enabled: enabled && !usePowerSyncPath && filters?.isReady !== false,
408
+ staleTime: 3e4,
409
+ gcTime: 3e5,
410
+ refetchOnMount: true,
411
+ refetchOnWindowFocus: false
412
+ });
413
+ useEffect2(() => {
414
+ if (!realtimeEnabled || usePowerSyncPath || !enabled) {
415
+ return;
416
+ }
417
+ const channel = supabase.channel(`advance-query-${tableName}-${filterKey}`).on(
418
+ "postgres_changes",
419
+ {
420
+ event: "*",
421
+ // Listen to INSERT, UPDATE, DELETE
422
+ schema: "public",
423
+ table: tableName
424
+ // Note: We can't easily filter by complex where clauses,
425
+ // so we invalidate on any change to the table
426
+ },
427
+ () => {
428
+ queryClient.invalidateQueries({ queryKey: edgeFunctionQueryKey });
429
+ }
430
+ ).subscribe();
431
+ return () => {
432
+ supabase.removeChannel(channel);
433
+ };
434
+ }, [
435
+ realtimeEnabled,
436
+ usePowerSyncPath,
437
+ enabled,
438
+ supabase,
439
+ tableName,
440
+ filterKey,
441
+ queryClient,
442
+ edgeFunctionQueryKey
443
+ ]);
444
+ const result = useMemo3(() => {
445
+ if (usePowerSyncPath) {
446
+ return {
447
+ data: powerSyncResult.data,
448
+ isLoading: powerSyncResult.isLoading,
449
+ isPending: powerSyncResult.isPending,
450
+ isFetching: powerSyncResult.isFetching,
451
+ isRefetching: powerSyncResult.isRefetching,
452
+ isSuccess: powerSyncResult.isSuccess,
453
+ isError: powerSyncResult.isError,
454
+ error: powerSyncResult.error,
455
+ refetch: powerSyncResult.refetch,
456
+ count: powerSyncResult.count ?? powerSyncResult.data?.length
457
+ };
458
+ }
459
+ return {
460
+ data: edgeFunctionResult.data?.data,
461
+ isLoading: edgeFunctionResult.isLoading,
462
+ isPending: edgeFunctionResult.isPending,
463
+ isFetching: edgeFunctionResult.isFetching,
464
+ isRefetching: edgeFunctionResult.isFetching,
465
+ isSuccess: edgeFunctionResult.isSuccess,
466
+ isError: edgeFunctionResult.isError,
467
+ error: edgeFunctionResult.error,
468
+ refetch: async () => {
469
+ await edgeFunctionResult.refetch();
470
+ },
471
+ count: edgeFunctionResult.data?.count ?? extraData.count,
472
+ clarification: edgeFunctionResult.data?.clarification
473
+ };
474
+ }, [
475
+ usePowerSyncPath,
476
+ powerSyncResult,
477
+ edgeFunctionResult,
478
+ extraData.count
479
+ ]);
480
+ return [result, filters, setFilters];
481
+ }
482
+
483
+ // src/hooks/useDbInsert.ts
484
+ import { useCallback as useCallback4, useMemo as useMemo4 } from "react";
485
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
486
+ function useDbInsert(table, options = {}) {
487
+ const { registry, status } = useDataLayer();
488
+ const queryClient = useQueryClient();
489
+ const { onSuccess, onError, invalidateTables = [table] } = options;
490
+ const adapter = useMemo4(() => {
491
+ if (!status.isInitialized) return null;
492
+ try {
493
+ return registry.getAdapter(table);
494
+ } catch {
495
+ return null;
496
+ }
497
+ }, [registry, table, status.isInitialized, status.currentBackend]);
498
+ const mutationFn = useCallback4(
499
+ async (data) => {
500
+ if (!adapter) {
501
+ throw new Error(`Adapter not available for table: ${table}`);
502
+ }
503
+ return adapter.insert(table, data);
504
+ },
505
+ [adapter, table]
506
+ );
507
+ const mutation = useMutation({
508
+ mutationFn,
509
+ onSuccess: (data) => {
510
+ invalidateTables.forEach((t) => {
511
+ queryClient.invalidateQueries({
512
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === t
513
+ });
514
+ });
515
+ onSuccess?.(data);
516
+ },
517
+ onError: (error) => {
518
+ onError?.(error instanceof Error ? error : new Error(String(error)));
519
+ }
520
+ });
521
+ return {
522
+ mutate: mutation.mutate,
523
+ mutateAsync: mutation.mutateAsync,
524
+ isPending: mutation.isPending,
525
+ error: mutation.error,
526
+ reset: mutation.reset,
527
+ data: mutation.data
528
+ };
529
+ }
530
+
531
+ // src/hooks/useDbUpdate.ts
532
+ import { useCallback as useCallback5, useMemo as useMemo5 } from "react";
533
+ import { useMutation as useMutation2, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
534
+ function useDbUpdate(table, options = {}) {
535
+ const { registry, status } = useDataLayer();
536
+ const queryClient = useQueryClient2();
537
+ const {
538
+ onSuccess,
539
+ onError,
540
+ invalidateTables = [table],
541
+ optimistic = false
542
+ } = options;
543
+ const adapter = useMemo5(() => {
544
+ if (!status.isInitialized) return null;
545
+ try {
546
+ return registry.getAdapter(table);
547
+ } catch {
548
+ return null;
549
+ }
550
+ }, [registry, table, status.isInitialized, status.currentBackend]);
551
+ const mutationFn = useCallback5(
552
+ async (params) => {
553
+ if (!adapter) {
554
+ throw new Error(`Adapter not available for table: ${table}`);
555
+ }
556
+ return adapter.update(table, params.id, params.data);
557
+ },
558
+ [adapter, table]
559
+ );
560
+ const mutation = useMutation2({
561
+ mutationFn,
562
+ onMutate: optimistic ? async () => {
563
+ await queryClient.cancelQueries({
564
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === table
565
+ });
566
+ const previousData = queryClient.getQueriesData({
567
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === table
568
+ });
569
+ return { previousData };
570
+ } : void 0,
571
+ onSuccess: (data) => {
572
+ invalidateTables.forEach((t) => {
573
+ queryClient.invalidateQueries({
574
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === t
575
+ });
576
+ });
577
+ onSuccess?.(data);
578
+ },
579
+ onError: (error, _variables, context) => {
580
+ if (optimistic && context?.previousData) {
581
+ context.previousData.forEach(([queryKey, data]) => {
582
+ queryClient.setQueryData(queryKey, data);
583
+ });
584
+ }
585
+ onError?.(error instanceof Error ? error : new Error(String(error)));
586
+ }
587
+ });
588
+ return {
589
+ mutate: mutation.mutate,
590
+ mutateAsync: mutation.mutateAsync,
591
+ isPending: mutation.isPending,
592
+ error: mutation.error,
593
+ reset: mutation.reset,
594
+ data: mutation.data
595
+ };
596
+ }
597
+
598
+ // src/hooks/useDbUpsert.ts
599
+ import { useCallback as useCallback6, useMemo as useMemo6 } from "react";
600
+ import { useMutation as useMutation3, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
601
+ function useDbUpsert(table, options = {}) {
602
+ const { registry, status } = useDataLayer();
603
+ const queryClient = useQueryClient3();
604
+ const { onSuccess, onError, invalidateTables = [table] } = options;
605
+ const adapter = useMemo6(() => {
606
+ if (!status.isInitialized) return null;
607
+ try {
608
+ return registry.getAdapter(table);
609
+ } catch {
610
+ return null;
611
+ }
612
+ }, [registry, table, status.isInitialized, status.currentBackend]);
613
+ const mutationFn = useCallback6(
614
+ async (data) => {
615
+ if (!adapter) {
616
+ throw new Error(`Adapter not available for table: ${table}`);
617
+ }
618
+ return adapter.upsert(table, data);
619
+ },
620
+ [adapter, table]
621
+ );
622
+ const mutation = useMutation3({
623
+ mutationFn,
624
+ onSuccess: (data) => {
625
+ invalidateTables.forEach((t) => {
626
+ queryClient.invalidateQueries({
627
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === t
628
+ });
629
+ });
630
+ onSuccess?.(data);
631
+ },
632
+ onError: (error) => {
633
+ onError?.(error instanceof Error ? error : new Error(String(error)));
634
+ }
635
+ });
636
+ return {
637
+ mutate: mutation.mutate,
638
+ mutateAsync: mutation.mutateAsync,
639
+ isPending: mutation.isPending,
640
+ error: mutation.error,
641
+ reset: mutation.reset,
642
+ data: mutation.data
643
+ };
644
+ }
645
+
646
+ // src/hooks/useDbDelete.ts
647
+ import { useCallback as useCallback7, useMemo as useMemo7 } from "react";
648
+ import { useMutation as useMutation4, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
649
+ function useDbDelete(table, options = {}) {
650
+ const { registry, status } = useDataLayer();
651
+ const queryClient = useQueryClient4();
652
+ const {
653
+ onSuccess,
654
+ onError,
655
+ invalidateTables = [table],
656
+ optimistic = false
657
+ } = options;
658
+ const adapter = useMemo7(() => {
659
+ if (!status.isInitialized) return null;
660
+ try {
661
+ return registry.getAdapter(table);
662
+ } catch {
663
+ return null;
664
+ }
665
+ }, [registry, table, status.isInitialized, status.currentBackend]);
666
+ const mutationFn = useCallback7(
667
+ async (id) => {
668
+ if (!adapter) {
669
+ throw new Error(`Adapter not available for table: ${table}`);
670
+ }
671
+ await adapter.delete(table, id);
672
+ },
673
+ [adapter, table]
674
+ );
675
+ const mutation = useMutation4({
676
+ mutationFn,
677
+ onMutate: optimistic ? async (id) => {
678
+ await queryClient.cancelQueries({
679
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === table
680
+ });
681
+ const previousData = queryClient.getQueriesData({
682
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === table
683
+ });
684
+ queryClient.setQueriesData(
685
+ {
686
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === table
687
+ },
688
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
689
+ (old) => {
690
+ if (!old?.data) return old;
691
+ return {
692
+ ...old,
693
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
694
+ data: old.data.filter((item) => item.id !== id)
695
+ };
696
+ }
697
+ );
698
+ return { previousData };
699
+ } : void 0,
700
+ onSuccess: () => {
701
+ invalidateTables.forEach((t) => {
702
+ queryClient.invalidateQueries({
703
+ predicate: (query) => query.queryKey[0] === "v3" && query.queryKey[2] === t
704
+ });
705
+ });
706
+ onSuccess?.();
707
+ },
708
+ onError: (error, _id, context) => {
709
+ if (optimistic && context?.previousData) {
710
+ context.previousData.forEach(([queryKey, data]) => {
711
+ queryClient.setQueryData(queryKey, data);
712
+ });
713
+ }
714
+ onError?.(error instanceof Error ? error : new Error(String(error)));
715
+ }
716
+ });
717
+ return {
718
+ mutate: mutation.mutate,
719
+ mutateAsync: mutation.mutateAsync,
720
+ isPending: mutation.isPending,
721
+ error: mutation.error,
722
+ reset: mutation.reset
723
+ };
724
+ }
725
+
726
+ // src/hooks/useDbInfiniteQuery.ts
727
+ import { useMemo as useMemo8, useCallback as useCallback8 } from "react";
728
+ import { useInfiniteQuery } from "@tanstack/react-query";
729
+ function buildInfiniteQueryKey(table, options) {
730
+ return [
731
+ "v3",
732
+ "infinite-query",
733
+ table,
734
+ options.select ?? "*",
735
+ JSON.stringify(options.where ?? {}),
736
+ JSON.stringify(options.orderBy ?? []),
737
+ options.pageSize ?? 50,
738
+ options.searchText ?? "",
739
+ JSON.stringify(options.searchFields ?? [])
740
+ ];
741
+ }
742
+ function serializeInfiniteQueryOptions(options) {
743
+ return JSON.stringify({
744
+ select: options.select,
745
+ where: options.where,
746
+ orderBy: options.orderBy,
747
+ pageSize: options.pageSize,
748
+ searchText: options.searchText,
749
+ searchFields: options.searchFields
750
+ });
751
+ }
752
+ function resolveTableName2(table) {
753
+ if (typeof table === "string") {
754
+ return table;
755
+ }
756
+ return `${table.schema}.${table.table}`;
757
+ }
758
+ function buildSearchWhereClause(searchText, searchFields, existingWhere) {
759
+ const searchWhere = {};
760
+ if (searchFields.length === 1) {
761
+ searchWhere[searchFields[0]] = { like: `%${searchText}%` };
762
+ } else if (searchFields.length > 1) {
763
+ searchWhere[searchFields[0]] = { like: `%${searchText}%` };
764
+ }
765
+ return {
766
+ ...existingWhere,
767
+ ...searchWhere
768
+ };
769
+ }
770
+ function useDbInfiniteQuery(table, options = {}) {
771
+ const tableName = resolveTableName2(table);
772
+ const { registry, status } = useDataLayer();
773
+ const {
774
+ enabled = true,
775
+ staleTime = 3e4,
776
+ refetchOnWindowFocus = true,
777
+ pageSize = 50,
778
+ searchText,
779
+ searchFields,
780
+ ...queryOptions
781
+ } = options;
782
+ const adapter = useMemo8(() => {
783
+ if (!status.isInitialized) return null;
784
+ try {
785
+ return registry.getAdapter(tableName);
786
+ } catch {
787
+ return null;
788
+ }
789
+ }, [registry, tableName, status.isInitialized, status.currentBackend]);
790
+ const queryKey = useMemo8(
791
+ () => buildInfiniteQueryKey(tableName, options),
792
+ [tableName, serializeInfiniteQueryOptions(options)]
793
+ );
794
+ const effectiveWhere = useMemo8(() => {
795
+ if (searchText && searchFields && searchFields.length > 0) {
796
+ return buildSearchWhereClause(searchText, searchFields, queryOptions.where);
797
+ }
798
+ return queryOptions.where;
799
+ }, [searchText, searchFields, queryOptions.where]);
800
+ const memoizedQueryOptions = useMemo8(
801
+ () => ({
802
+ select: queryOptions.select,
803
+ where: effectiveWhere,
804
+ orderBy: queryOptions.orderBy
805
+ }),
806
+ [queryOptions.select, effectiveWhere, queryOptions.orderBy]
807
+ );
808
+ const infiniteQuery = useInfiniteQuery({
809
+ queryKey,
810
+ queryFn: async ({ pageParam }) => {
811
+ if (!adapter) {
812
+ throw new Error(`Adapter not available for table: ${tableName}`);
813
+ }
814
+ const offset = (pageParam - 1) * pageSize;
815
+ const result = await adapter.query(tableName, {
816
+ ...memoizedQueryOptions,
817
+ limit: pageSize,
818
+ offset
819
+ });
820
+ return {
821
+ data: result.data ?? [],
822
+ count: result.count
823
+ };
824
+ },
825
+ initialPageParam: 1,
826
+ getNextPageParam: (lastPage, allPages) => {
827
+ const totalLoaded = allPages.reduce((sum, page) => sum + page.data.length, 0);
828
+ const totalCount = lastPage.count;
829
+ if (totalCount !== void 0 && totalLoaded >= totalCount) {
830
+ return void 0;
831
+ }
832
+ if (lastPage.data.length < pageSize) {
833
+ return void 0;
834
+ }
835
+ return allPages.length + 1;
836
+ },
837
+ enabled: enabled && status.isInitialized && adapter !== null,
838
+ staleTime,
839
+ refetchOnWindowFocus
840
+ });
841
+ const flattenedData = useMemo8(() => {
842
+ if (!infiniteQuery.data?.pages) return void 0;
843
+ return infiniteQuery.data.pages.flatMap((page) => page.data);
844
+ }, [infiniteQuery.data?.pages]);
845
+ const count = useMemo8(() => {
846
+ if (!infiniteQuery.data?.pages || infiniteQuery.data.pages.length === 0) {
847
+ return void 0;
848
+ }
849
+ return infiniteQuery.data.pages[infiniteQuery.data.pages.length - 1].count;
850
+ }, [infiniteQuery.data?.pages]);
851
+ const fetchNextPage = useCallback8(async () => {
852
+ await infiniteQuery.fetchNextPage();
853
+ }, [infiniteQuery]);
854
+ const refetch = useCallback8(async () => {
855
+ await infiniteQuery.refetch();
856
+ }, [infiniteQuery]);
857
+ return {
858
+ data: flattenedData,
859
+ isLoading: infiniteQuery.isLoading,
860
+ isPending: infiniteQuery.isPending,
861
+ isFetching: infiniteQuery.isFetching,
862
+ error: infiniteQuery.error,
863
+ fetchNextPage,
864
+ hasNextPage: infiniteQuery.hasNextPage ?? false,
865
+ isFetchingNextPage: infiniteQuery.isFetchingNextPage,
866
+ count,
867
+ refetch
868
+ };
869
+ }
870
+
871
+ // src/hooks/useDbCount.ts
872
+ import { useMemo as useMemo9, useCallback as useCallback9 } from "react";
873
+ import { useQuery as useQuery4 } from "@tanstack/react-query";
874
+ function useDbCount(table, options = {}) {
875
+ const { registry, status } = useDataLayer();
876
+ const { enabled = true, staleTime = 3e4, where } = options;
877
+ const adapter = useMemo9(() => {
878
+ if (!status.isInitialized) return null;
879
+ try {
880
+ return registry.getAdapter(table);
881
+ } catch {
882
+ return null;
883
+ }
884
+ }, [registry, table, status.isInitialized, status.currentBackend]);
885
+ const queryKey = useMemo9(
886
+ () => ["v3", "count", table, JSON.stringify(where ?? {})],
887
+ [table, where]
888
+ );
889
+ const queryFn = useCallback9(async () => {
890
+ if (!adapter) {
891
+ throw new Error(`Adapter not available for table: ${table}`);
892
+ }
893
+ const result = await adapter.query(table, { where, select: "id" });
894
+ return result.count ?? result.data.length;
895
+ }, [adapter, table, where]);
896
+ const query = useQuery4({
897
+ queryKey,
898
+ queryFn,
899
+ enabled: enabled && status.isInitialized && adapter !== null,
900
+ staleTime
901
+ });
902
+ const refetch = useCallback9(async () => {
903
+ await query.refetch();
904
+ }, [query]);
905
+ return {
906
+ count: query.data,
907
+ isLoading: query.isLoading,
908
+ isFetching: query.isFetching,
909
+ error: query.error,
910
+ refetch
911
+ };
912
+ }
913
+
914
+ export {
915
+ DataLayerContext,
916
+ useDataLayer,
917
+ useDataLayerOptional,
918
+ useDbQuery,
919
+ useDbQueryById,
920
+ useAdvanceQuery,
921
+ useDbInsert,
922
+ useDbUpdate,
923
+ useDbUpsert,
924
+ useDbDelete,
925
+ useDbInfiniteQuery,
926
+ useDbCount
927
+ };
928
+ //# sourceMappingURL=chunk-3M2U6TXH.js.map