@pol-studios/db 1.0.31 → 1.0.34

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 (107) hide show
  1. package/dist/{DataLayerContext-Dc7nF2IG.d.ts → DataLayerContext-BwMk4VpG.d.ts} +92 -8
  2. package/dist/UserMetadataContext-QLIv-mfF.d.ts +171 -0
  3. package/dist/{UserMetadataContext-B8gVWGMl.d.ts → UserMetadataContext-pQb3A8_Q.d.ts} +1 -1
  4. package/dist/auth/context.d.ts +53 -5
  5. package/dist/auth/context.js +30 -8
  6. package/dist/auth/guards.d.ts +9 -9
  7. package/dist/auth/guards.js +2 -3
  8. package/dist/auth/hooks.d.ts +108 -4
  9. package/dist/auth/hooks.js +13 -9
  10. package/dist/auth/index.d.ts +6 -6
  11. package/dist/auth/index.js +45 -17
  12. package/dist/chunk-5HJLTYRA.js +355 -0
  13. package/dist/chunk-5HJLTYRA.js.map +1 -0
  14. package/dist/{chunk-WX4ABYIF.js → chunk-67HMVGV7.js} +292 -94
  15. package/dist/chunk-67HMVGV7.js.map +1 -0
  16. package/dist/chunk-6KN7KLEG.js +1 -0
  17. package/dist/{chunk-FZF26ZRB.js → chunk-7BGDQT5X.js} +29 -16
  18. package/dist/{chunk-FZF26ZRB.js.map → chunk-7BGDQT5X.js.map} +1 -1
  19. package/dist/{chunk-P4UZ7IXC.js → chunk-7D4SUZUM.js} +1 -5
  20. package/dist/{chunk-3PJTNH2L.js → chunk-AKIRHA4Q.js} +2 -2
  21. package/dist/{chunk-OQ7U6EQ3.js → chunk-AML2TLXJ.js} +3801 -3424
  22. package/dist/chunk-AML2TLXJ.js.map +1 -0
  23. package/dist/{chunk-5EFDS7SR.js → chunk-DMVUEJG2.js} +7 -2
  24. package/dist/chunk-DMVUEJG2.js.map +1 -0
  25. package/dist/{chunk-ADD5MIMK.js → chunk-FESQS4S5.js} +15 -15
  26. package/dist/{chunk-ADD5MIMK.js.map → chunk-FESQS4S5.js.map} +1 -1
  27. package/dist/{chunk-U5UNPBKB.js → chunk-FI6JAD5G.js} +3 -3
  28. package/dist/{chunk-TKWR5AAY.js → chunk-JOULSXOI.js} +2 -2
  29. package/dist/{chunk-HTJ2FQW5.js → chunk-LF3V3ERS.js} +13 -15
  30. package/dist/{chunk-HTJ2FQW5.js.map → chunk-LF3V3ERS.js.map} +1 -1
  31. package/dist/{chunk-5BLKZUKM.js → chunk-MREERKQU.js} +45 -14
  32. package/dist/chunk-MREERKQU.js.map +1 -0
  33. package/dist/{chunk-VGEMLNNM.js → chunk-NP34C3O3.js} +306 -704
  34. package/dist/chunk-NP34C3O3.js.map +1 -0
  35. package/dist/{chunk-CNIGRBRE.js → chunk-QJZUIAHA.js} +43 -19
  36. package/dist/{chunk-CNIGRBRE.js.map → chunk-QJZUIAHA.js.map} +1 -1
  37. package/dist/{chunk-HAWJTZCK.js → chunk-RT4O5H2E.js} +5 -7
  38. package/dist/chunk-RT4O5H2E.js.map +1 -0
  39. package/dist/{chunk-2NVSXZKQ.js → chunk-TN7QINPK.js} +74 -309
  40. package/dist/chunk-TN7QINPK.js.map +1 -0
  41. package/dist/chunk-UBHORKBS.js +215 -0
  42. package/dist/chunk-UBHORKBS.js.map +1 -0
  43. package/dist/{chunk-WVF7RUW5.js → chunk-WM25QE7E.js} +3 -3
  44. package/dist/{chunk-H6365JPC.js → chunk-YUX6RGLZ.js} +3 -3
  45. package/dist/{chunk-H6365JPC.js.map → chunk-YUX6RGLZ.js.map} +1 -1
  46. package/dist/{chunk-H3LNH2NT.js → chunk-Z456IHCB.js} +5 -9
  47. package/dist/{chunk-H3LNH2NT.js.map → chunk-Z456IHCB.js.map} +1 -1
  48. package/dist/{chunk-JAATANS3.js → chunk-ZCOFRJQD.js} +3 -3
  49. package/dist/{chunk-JAATANS3.js.map → chunk-ZCOFRJQD.js.map} +1 -1
  50. package/dist/client/index.d.ts +1 -1
  51. package/dist/client/index.js +2 -2
  52. package/dist/core/index.d.ts +54 -31
  53. package/dist/{executor-Br27YZvl.d.ts → executor-YJw4m7Q7.d.ts} +9 -1
  54. package/dist/gen/index.js +1 -1
  55. package/dist/hooks/index.d.ts +3 -22
  56. package/dist/hooks/index.js +12 -9
  57. package/dist/{index-CYFdO0iB.d.ts → index-lveh8qb0.d.ts} +1 -1
  58. package/dist/index.d.ts +38 -10
  59. package/dist/index.js +57 -36
  60. package/dist/index.native.d.ts +19 -13
  61. package/dist/index.native.js +64 -35
  62. package/dist/index.web.d.ts +18 -45
  63. package/dist/index.web.js +58 -49
  64. package/dist/index.web.js.map +1 -1
  65. package/dist/mutation/index.d.ts +2 -2
  66. package/dist/mutation/index.js +5 -5
  67. package/dist/parser/index.js +4 -4
  68. package/dist/powersync-bridge/index.d.ts +18 -3
  69. package/dist/powersync-bridge/index.js +2 -2
  70. package/dist/query/index.d.ts +1 -1
  71. package/dist/query/index.js +7 -8
  72. package/dist/realtime/index.js +7 -9
  73. package/dist/realtime/index.js.map +1 -1
  74. package/dist/types/index.d.ts +3 -3
  75. package/dist/types/index.js +6 -7
  76. package/dist/{useBatchUpsert-9OYjibLh.d.ts → useBatchUpsert-DAkiCNo3.d.ts} +1 -1
  77. package/dist/{useDbCount-Dk0yCKlT.d.ts → useDbCount-DWfYB2iu.d.ts} +16 -2
  78. package/dist/{useResolveFeedback-C1KucfdQ.d.ts → useResolveFeedback-CxLccZKK.d.ts} +197 -93
  79. package/dist/{useSupabase-DvWVuHHE.d.ts → useSupabase-DSZNeXnF.d.ts} +1 -1
  80. package/dist/with-auth/index.d.ts +2 -2
  81. package/dist/with-auth/index.js +46 -33
  82. package/dist/with-auth/index.js.map +1 -1
  83. package/package.json +18 -8
  84. package/dist/UserMetadataContext-DntmpK41.d.ts +0 -33
  85. package/dist/canvas-C4TBBDUL.node +0 -0
  86. package/dist/canvas-ZQNCL7JL.js +0 -1541
  87. package/dist/canvas-ZQNCL7JL.js.map +0 -1
  88. package/dist/chunk-2NVSXZKQ.js.map +0 -1
  89. package/dist/chunk-5BLKZUKM.js.map +0 -1
  90. package/dist/chunk-5EFDS7SR.js.map +0 -1
  91. package/dist/chunk-HAWJTZCK.js.map +0 -1
  92. package/dist/chunk-NSIAAYW3.js +0 -1
  93. package/dist/chunk-O7SETNGD.js +0 -3391
  94. package/dist/chunk-O7SETNGD.js.map +0 -1
  95. package/dist/chunk-OQ7U6EQ3.js.map +0 -1
  96. package/dist/chunk-VGEMLNNM.js.map +0 -1
  97. package/dist/chunk-WX4ABYIF.js.map +0 -1
  98. package/dist/dist-NDNRSNOG.js +0 -521
  99. package/dist/dist-NDNRSNOG.js.map +0 -1
  100. package/dist/pdf-PHXP7RHD.js +0 -20336
  101. package/dist/pdf-PHXP7RHD.js.map +0 -1
  102. /package/dist/{chunk-NSIAAYW3.js.map → chunk-6KN7KLEG.js.map} +0 -0
  103. /package/dist/{chunk-P4UZ7IXC.js.map → chunk-7D4SUZUM.js.map} +0 -0
  104. /package/dist/{chunk-3PJTNH2L.js.map → chunk-AKIRHA4Q.js.map} +0 -0
  105. /package/dist/{chunk-U5UNPBKB.js.map → chunk-FI6JAD5G.js.map} +0 -0
  106. /package/dist/{chunk-TKWR5AAY.js.map → chunk-JOULSXOI.js.map} +0 -0
  107. /package/dist/{chunk-WVF7RUW5.js.map → chunk-WM25QE7E.js.map} +0 -0
@@ -2,7 +2,7 @@ import * as react from 'react';
2
2
  import { SupabaseClient } from '@supabase/supabase-js';
3
3
  import { QueryClient } from '@tanstack/react-query';
4
4
  import { DatabaseSchema, QueryOptions, DataLayerConfig, TableStrategy, SyncStatus, SyncControl } from './core/index.js';
5
- import { P as PowerSyncDatabase } from './executor-Br27YZvl.js';
5
+ import { P as PowerSyncDatabase } from './executor-YJw4m7Q7.js';
6
6
 
7
7
  /**
8
8
  * V3 Data Layer Adapter Types
@@ -318,6 +318,25 @@ declare class AdapterAutoDetector {
318
318
  * @returns Detection result with recommendation and reasoning
319
319
  */
320
320
  detect(): AutoDetectionResult;
321
+ /**
322
+ * Detect backend availability WITHOUT notifying listeners.
323
+ *
324
+ * This method is safe to call during React's render phase because it does not
325
+ * trigger state updates in other components. Use this method when you need to
326
+ * check backend status synchronously during render (e.g., in getAdapter()).
327
+ *
328
+ * The regular detect() method with listener notifications should only be called
329
+ * from useEffect or event handlers to avoid the React warning:
330
+ * "Cannot update a component while rendering a different component"
331
+ *
332
+ * @returns Detection result with recommendation and reasoning
333
+ */
334
+ detectSilent(): AutoDetectionResult;
335
+ /**
336
+ * Internal detection logic shared by detect() and detectSilent().
337
+ * @private
338
+ */
339
+ private performDetection;
321
340
  /**
322
341
  * Check if PowerSync is available.
323
342
  *
@@ -342,7 +361,8 @@ declare class AdapterAutoDetector {
342
361
  *
343
362
  * Prefers the sync status's isOnline property if available (from React Native NetInfo).
344
363
  * Falls back to navigator.onLine in browser environments.
345
- * Returns true by default for other environments.
364
+ * Returns false by default for non-browser environments (React Native, Node.js, etc.)
365
+ * to ensure offline-first behavior works correctly.
346
366
  *
347
367
  * @returns Whether the device has network connectivity
348
368
  */
@@ -431,6 +451,50 @@ declare class AdapterAutoDetector {
431
451
  */
432
452
  declare function createAdapterAutoDetector(powerSyncDb: PowerSyncDatabase | null, supabase: SupabaseClient | null, options?: AutoDetectorOptions): AdapterAutoDetector;
433
453
 
454
+ /**
455
+ * Minimal interface for sync tracking callbacks.
456
+ * Intentionally decoupled from the full SyncControl to keep
457
+ * the adapter layer independent of React context types.
458
+ */
459
+ interface SyncTracker {
460
+ addPendingMutation: (entry: {
461
+ id: string;
462
+ table: string;
463
+ op: string;
464
+ opData?: unknown;
465
+ createdAt?: Date;
466
+ }) => void;
467
+ removePendingMutation: (id: string) => void;
468
+ }
469
+ /**
470
+ * Decorator that wraps a TableDataAdapter and automatically
471
+ * tracks pending mutations via SyncTracker callbacks.
472
+ *
473
+ * Read operations (query, queryById, subscribe) are passed
474
+ * through without modification. Mutation operations (insert,
475
+ * update, upsert, delete) are wrapped with addPendingMutation
476
+ * before the write and removePendingMutation on error.
477
+ *
478
+ * NOTE: The syncTracker can be null/undefined during initialization
479
+ * due to React's useEffect timing. The adapter handles this gracefully
480
+ * by using optional chaining - mutations still work, just without tracking.
481
+ */
482
+ declare class SyncTrackingAdapter implements TableDataAdapter {
483
+ private readonly inner;
484
+ private readonly syncTracker;
485
+ readonly name: string;
486
+ constructor(inner: TableDataAdapter, syncTracker: SyncTracker | null | undefined);
487
+ query<T>(table: string, options: QueryOptions): Promise<AdapterQueryResult<T>>;
488
+ queryById<T>(table: string, id: string, options?: Pick<QueryOptions, "select">): Promise<T | null>;
489
+ subscribe<T>(table: string, options: QueryOptions, callback: (data: T[]) => void): () => void;
490
+ insert<T>(table: string, data: Partial<T>): Promise<T>;
491
+ update<T>(table: string, id: string, data: Partial<T>): Promise<T>;
492
+ upsert<T>(table: string, data: Partial<T>): Promise<T>;
493
+ delete(table: string, id: string): Promise<void>;
494
+ /** Get the underlying unwrapped adapter */
495
+ getInnerAdapter(): TableDataAdapter;
496
+ }
497
+
434
498
  /**
435
499
  * V3 Data Layer Adapter Registry
436
500
  *
@@ -489,6 +553,14 @@ declare class AdapterRegistry {
489
553
  * Auto-detector instance for automatic backend selection
490
554
  */
491
555
  private autoDetector;
556
+ /**
557
+ * Sync tracker for mutation tracking
558
+ */
559
+ private syncTracker;
560
+ /**
561
+ * Sync tracking adapter that wraps PowerSync adapter
562
+ */
563
+ private syncTrackingAdapter;
492
564
  /**
493
565
  * Listeners for backend change events
494
566
  */
@@ -520,6 +592,17 @@ declare class AdapterRegistry {
520
592
  * @param adapter - PowerSync adapter implementation
521
593
  */
522
594
  setPowerSyncAdapter(adapter: TableDataAdapter): void;
595
+ /**
596
+ * Set the sync tracker for mutation tracking.
597
+ * When set, write operations on PowerSync tables will
598
+ * automatically track pending mutations.
599
+ *
600
+ * NOTE: This also clears the adapter cache to ensure any
601
+ * previously cached adapters (which may have been created
602
+ * before the sync tracker was available) are recreated
603
+ * with the new sync tracker on next access.
604
+ */
605
+ setSyncTracker(tracker: SyncTracker): void;
523
606
  /**
524
607
  * Set the Supabase adapter instance
525
608
  *
@@ -556,10 +639,11 @@ declare class AdapterRegistry {
556
639
  * - Auto-generates PowerSync alias as "CoreProfile" if not explicitly set
557
640
  *
558
641
  * @param table - The table name (may be schema-qualified like "core.Profile")
642
+ * @param operation - The operation type: 'read' uses fallback logic during init, 'write' always uses PowerSync for powersync tables
559
643
  * @returns The appropriate adapter for the table
560
644
  * @throws Error if adapters are not initialized
561
645
  */
562
- getAdapter(table: string): TableDataAdapter;
646
+ getAdapter(table: string, operation?: 'read' | 'write'): TableDataAdapter;
563
647
  /**
564
648
  * Get the PowerSync adapter directly
565
649
  *
@@ -748,8 +832,8 @@ interface DataLayerStatus {
748
832
  interface DataLayerCoreContextValue {
749
833
  /** Adapter registry for getting table adapters */
750
834
  registry: AdapterRegistry;
751
- /** Get adapter for a specific table */
752
- getAdapter: (table: string) => TableDataAdapter;
835
+ /** Get adapter for a specific table (defaults to 'read' operation) */
836
+ getAdapter: (table: string, operation?: 'read' | 'write') => TableDataAdapter;
753
837
  /** PowerSync database instance (null when not available) */
754
838
  powerSync: PowerSyncDatabase | null;
755
839
  /** Supabase client (always available) */
@@ -782,8 +866,8 @@ interface DataLayerStatusContextValue {
782
866
  interface DataLayerContextValue {
783
867
  /** Adapter registry for getting table adapters */
784
868
  registry: AdapterRegistry;
785
- /** Get adapter for a specific table */
786
- getAdapter: (table: string) => TableDataAdapter;
869
+ /** Get adapter for a specific table (defaults to 'read' operation) */
870
+ getAdapter: (table: string, operation?: 'read' | 'write') => TableDataAdapter;
787
871
  /** PowerSync database instance (null when not available) */
788
872
  powerSync: PowerSyncDatabase | null;
789
873
  /** Supabase client (always available) */
@@ -822,4 +906,4 @@ declare const DataLayerStatusContext: react.Context<DataLayerStatusContextValue>
822
906
  */
823
907
  declare const DataLayerContext: react.Context<DataLayerContextValue>;
824
908
 
825
- export { type AdapterQueryResult as A, BackendStatus as B, type CapableDataAdapter as C, DataLayerContext as D, type SyncStatusInfo as S, type TableDataAdapter as T, type AdapterConfig as a, 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, DataLayerCoreContext as n, DataLayerStatusContext as o, type DataLayerContextValue as p, type DataLayerCoreContextValue as q, type DataLayerStatusContextValue as r, type DataLayerStatus as s };
909
+ export { type AdapterQueryResult as A, BackendStatus as B, type CapableDataAdapter as C, DataLayerContext as D, type SyncStatusInfo as S, type TableDataAdapter as T, type AdapterConfig as a, 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, SyncTrackingAdapter as n, type SyncTracker as o, DataLayerCoreContext as p, DataLayerStatusContext as q, type DataLayerContextValue as r, type DataLayerCoreContextValue as s, type DataLayerStatusContextValue as t, type DataLayerStatus as u };
@@ -0,0 +1,171 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as react from 'react';
3
+ import { ReactNode } from 'react';
4
+ import { User } from '@supabase/supabase-js';
5
+ import { D as Database } from './useSupabase-DSZNeXnF.js';
6
+
7
+ type ProfileStatus = "active" | "archived" | "suspended";
8
+ interface SimpleProfile {
9
+ id: string;
10
+ email?: string | null;
11
+ firstName?: string | null;
12
+ lastName?: string | null;
13
+ fullName?: string | null;
14
+ status?: ProfileStatus | null;
15
+ profilePath?: string | null;
16
+ [key: string]: unknown;
17
+ }
18
+ interface SimpleUserAccess {
19
+ id: string;
20
+ userId: string;
21
+ accessKey: string;
22
+ }
23
+ interface SimpleAuthContextValue {
24
+ /** Supabase user (from auth session) */
25
+ user: User | null;
26
+ /** Profile from PowerSync (local SQLite) */
27
+ profile: SimpleProfile | null;
28
+ /** Access keys from PowerSync (local SQLite) */
29
+ accessKeys: string[];
30
+ /** Whether auth data is loading */
31
+ isLoading: boolean;
32
+ /** Whether profile is archived */
33
+ isArchived: boolean;
34
+ /** Whether profile is suspended */
35
+ isSuspended: boolean;
36
+ /** Profile status */
37
+ profileStatus: ProfileStatus | undefined;
38
+ /**
39
+ * Check if user has access to a resource.
40
+ * Supports wildcards: *:*:*, project:*:read, project:123:*
41
+ *
42
+ * @example
43
+ * hasAccess("admin") // exact match
44
+ * hasAccess("project:123:read") // check specific resource
45
+ */
46
+ hasAccess: (accessKey: string) => boolean;
47
+ /** Sign out the user */
48
+ signOut: () => Promise<void>;
49
+ }
50
+ /**
51
+ * Maps permission action strings to numeric levels for comparison.
52
+ * Higher numbers grant more access.
53
+ */
54
+ declare function getPermissionLevel(action: string): number;
55
+ /**
56
+ * Check if a user has at least the required permission level for a resource.
57
+ * Checks all matching access keys and returns true if any grants sufficient access.
58
+ *
59
+ * @param accessKeys - User's access keys
60
+ * @param resourceType - e.g., "project", "client", "database"
61
+ * @param resourceId - The ID of the resource
62
+ * @param requiredAction - e.g., "read", "edit", "admin"
63
+ */
64
+ declare function hasResourceAccess(accessKeys: string[], resourceType: string, resourceId: string, requiredAction: string): boolean;
65
+ interface SimpleAuthProviderProps {
66
+ children: ReactNode;
67
+ /** Supabase user from auth session */
68
+ user: User | null;
69
+ /** Profile from PowerSync query */
70
+ profile: SimpleProfile | null;
71
+ /** User access records from PowerSync query */
72
+ userAccess: SimpleUserAccess[] | null;
73
+ /** Whether the data is loading */
74
+ isLoading?: boolean;
75
+ /** Sign out function */
76
+ onSignOut: () => Promise<void>;
77
+ }
78
+ declare function SimpleAuthProvider({ children, user, profile, userAccess, isLoading, onSignOut, }: SimpleAuthProviderProps): react_jsx_runtime.JSX.Element;
79
+ /**
80
+ * Hook to access auth state and hasAccess function.
81
+ *
82
+ * @example
83
+ * ```tsx
84
+ * function MyComponent() {
85
+ * const { user, profile, hasAccess, isLoading } = useSimpleAuth();
86
+ *
87
+ * if (isLoading) return <Loading />;
88
+ * if (!user) return <Login />;
89
+ *
90
+ * // Check simple access
91
+ * if (hasAccess("admin")) {
92
+ * return <AdminPanel />;
93
+ * }
94
+ *
95
+ * // Check resource access
96
+ * if (hasAccess("project:123:edit")) {
97
+ * return <Editor />;
98
+ * }
99
+ *
100
+ * return <ReadOnlyView />;
101
+ * }
102
+ * ```
103
+ */
104
+ declare function useSimpleAuth(): SimpleAuthContextValue;
105
+ /**
106
+ * Hook that requires authentication.
107
+ * Throws if user is not authenticated.
108
+ *
109
+ * @example
110
+ * ```tsx
111
+ * function ProtectedComponent() {
112
+ * const { user, hasAccess } = useRequireAuth();
113
+ * // user is guaranteed to be non-null here
114
+ * }
115
+ * ```
116
+ */
117
+ declare function useRequireAuth(): SimpleAuthContextValue & {
118
+ user: User;
119
+ };
120
+ /**
121
+ * Hook to check resource-level access with permission levels.
122
+ *
123
+ * @example
124
+ * ```tsx
125
+ * function ProjectEditor({ projectId }: { projectId: string }) {
126
+ * const canEdit = useResourceAccess("project", projectId, "edit");
127
+ * const canDelete = useResourceAccess("project", projectId, "admin");
128
+ *
129
+ * return (
130
+ * <div>
131
+ * <button disabled={!canEdit}>Edit</button>
132
+ * <button disabled={!canDelete}>Delete</button>
133
+ * </div>
134
+ * );
135
+ * }
136
+ * ```
137
+ */
138
+ declare function useResourceAccess(resourceType: string, resourceId: string | number | undefined, requiredAction: string): boolean;
139
+ declare function useCanView(resourceType: string, resourceId: string | number | undefined): boolean;
140
+ declare function useCanEdit(resourceType: string, resourceId: string | number | undefined): boolean;
141
+ declare function useCanDelete(resourceType: string, resourceId: string | number | undefined): boolean;
142
+ declare function useCanShare(resourceType: string, resourceId: string | number | undefined): boolean;
143
+
144
+ type UserMetadataRow = Database["core"]["Tables"]["UserMetadata"]["Row"];
145
+ type UserMetadataInsert = Database["core"]["Tables"]["UserMetadata"]["Insert"];
146
+ type UserMetadataUpdate = Database["core"]["Tables"]["UserMetadata"]["Update"];
147
+ interface UserMetadataContextType {
148
+ metadata: Record<string, string>;
149
+ isLoading: boolean;
150
+ error: Error | null;
151
+ setMetadata: (key: string, value: string) => Promise<void>;
152
+ getMetadata: (key: string) => string | undefined;
153
+ removeMetadata: (key: string) => Promise<void>;
154
+ refreshMetadata: () => Promise<void>;
155
+ }
156
+ declare const userMetadataContext: react.Context<UserMetadataContextType>;
157
+ declare function UserMetadataProvider({ children }: {
158
+ children: ReactNode;
159
+ }): react_jsx_runtime.JSX.Element;
160
+ declare function useUserMetadata(): UserMetadataContextType;
161
+ declare function useUserMetadataValue(key: string): string | undefined;
162
+ declare function useSetUserMetadata(): {
163
+ setMetadata: (key: string, value: string) => Promise<void>;
164
+ removeMetadata: (key: string) => Promise<void>;
165
+ };
166
+ declare function useUserMetadataState<T>(key: string, defaultValue: T, options?: {
167
+ serialize?: (value: T) => string;
168
+ deserialize?: (value: string) => T;
169
+ }): [T, (value: T) => Promise<void>, boolean];
170
+
171
+ export { type ProfileStatus as P, SimpleAuthProvider as S, type UserMetadataContextType as U, useRequireAuth as a, useResourceAccess as b, useCanView as c, useCanEdit as d, useCanDelete as e, useCanShare as f, getPermissionLevel as g, hasResourceAccess as h, type SimpleAuthProviderProps as i, type SimpleAuthContextValue as j, type SimpleProfile as k, type SimpleUserAccess as l, useSetUserMetadata as m, useUserMetadata as n, useUserMetadataState as o, useUserMetadataValue as p, userMetadataContext as q, type UserMetadataInsert as r, UserMetadataProvider as s, type UserMetadataRow as t, useSimpleAuth as u, type UserMetadataUpdate as v };
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode } from 'react';
4
- import { D as Database } from './useSupabase-DvWVuHHE.js';
4
+ import { D as Database } from './useSupabase-DSZNeXnF.js';
5
5
 
6
6
  declare function useLiveChangesIndicator(value: any, field: string | undefined): [boolean, string];
7
7
 
@@ -1,13 +1,61 @@
1
- export { P as Profile, a as ProfileStatus, S as SetupAuthContext, b as SetupAuthContextProviderProps, s as setupAuthContext } from '../setupAuthContext-B76nbIP6.js';
1
+ export { j as SimpleAuthContextValue, S as SimpleAuthProvider, i as SimpleAuthProviderProps, k as SimpleProfile, P as SimpleProfileStatus, l as SimpleUserAccess, U as UserMetadataContextType, r as UserMetadataInsert, s as UserMetadataProvider, t as UserMetadataRow, v as UserMetadataUpdate, g as getPermissionLevel, h as hasResourceAccess, a as useRequireAuth, b as useResourceAccess, m as useSetUserMetadata, u as useSimpleAuth, e as useSimpleCanDelete, d as useSimpleCanEdit, f as useSimpleCanShare, c as useSimpleCanView, n as useUserMetadata, o as useUserMetadataState, p as useUserMetadataValue, q as userMetadataContext } from '../UserMetadataContext-QLIv-mfF.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import * as react from 'react';
4
4
  import { ReactNode } from 'react';
5
+ import { User } from '@supabase/supabase-js';
6
+ export { P as Profile, a as ProfileStatus, S as SetupAuthContext, b as SetupAuthContextProviderProps, s as setupAuthContext } from '../setupAuthContext-B76nbIP6.js';
5
7
  import { d as EntityType, b as EntityPermissionCheck, a as EntityAction } from '../EntityPermissions-DwFt4tUd.js';
6
- export { U as UserMetadataContextType, e as UserMetadataInsert, f as UserMetadataProvider, g as UserMetadataRow, h as UserMetadataUpdate, u as useSetUserMetadata, a as useUserMetadata, b as useUserMetadataState, c as useUserMetadataValue, d as userMetadataContext } from '../UserMetadataContext-DntmpK41.js';
7
- import '@supabase/supabase-js';
8
- import '../useSupabase-DvWVuHHE.js';
8
+ import '../useSupabase-DSZNeXnF.js';
9
9
  import '@supabase/supabase-js/dist/module/lib/types.js';
10
10
 
11
+ interface PowerSyncDB {
12
+ getAll: <T>(sql: string, params?: any[]) => Promise<T[]>;
13
+ getOptional: <T>(sql: string, params?: any[]) => Promise<T | null>;
14
+ watch: (sql: string, params: any[], options: {
15
+ onResult: (result: any) => void;
16
+ }, abortOptions?: {
17
+ signal: AbortSignal;
18
+ }) => void;
19
+ }
20
+ interface SupabaseClient {
21
+ auth: {
22
+ getUser: () => Promise<{
23
+ data: {
24
+ user: User | null;
25
+ };
26
+ error: any;
27
+ }>;
28
+ getSession: () => Promise<{
29
+ data: {
30
+ session: {
31
+ user: User;
32
+ } | null;
33
+ };
34
+ error: any;
35
+ }>;
36
+ signOut: () => Promise<{
37
+ error: any;
38
+ }>;
39
+ onAuthStateChange: (callback: (event: string, session: any) => void) => {
40
+ data: {
41
+ subscription: {
42
+ unsubscribe: () => void;
43
+ };
44
+ };
45
+ };
46
+ };
47
+ }
48
+ interface OfflineAuthProviderProps {
49
+ children: ReactNode;
50
+ /** PowerSync database instance */
51
+ db: PowerSyncDB | null;
52
+ /** Supabase client for auth */
53
+ supabase: SupabaseClient;
54
+ /** Whether PowerSync is ready */
55
+ isDbReady?: boolean;
56
+ }
57
+ declare function OfflineAuthProvider({ children, db, supabase, isDbReady, }: OfflineAuthProviderProps): react_jsx_runtime.JSX.Element;
58
+
11
59
  interface AuthProviderProps {
12
60
  children: ReactNode;
13
61
  /**
@@ -45,4 +93,4 @@ declare function PermissionProvider({ children }: {
45
93
  }): react_jsx_runtime.JSX.Element;
46
94
  declare function usePermissions(): PermissionContextValue;
47
95
 
48
- export { AuthProvider, type AuthProviderProps, type EntityPermissionContextValue, type PermissionContextValue, PermissionProvider, entityPermissionContext, permissionContext, usePermissions };
96
+ export { AuthProvider, type AuthProviderProps, type EntityPermissionContextValue, OfflineAuthProvider, type OfflineAuthProviderProps, type PermissionContextValue, PermissionProvider, entityPermissionContext, permissionContext, usePermissions };
@@ -1,3 +1,16 @@
1
+ import {
2
+ OfflineAuthProvider,
3
+ SimpleAuthProvider,
4
+ getPermissionLevel,
5
+ hasResourceAccess,
6
+ useCanDelete,
7
+ useCanEdit,
8
+ useCanShare,
9
+ useCanView,
10
+ useRequireAuth,
11
+ useResourceAccess,
12
+ useSimpleAuth
13
+ } from "../chunk-5HJLTYRA.js";
1
14
  import {
2
15
  AuthProvider,
3
16
  PermissionProvider,
@@ -11,24 +24,33 @@ import {
11
24
  useUserMetadataState,
12
25
  useUserMetadataValue,
13
26
  userMetadataContext
14
- } from "../chunk-WX4ABYIF.js";
15
- import "../chunk-VGEMLNNM.js";
16
- import "../chunk-GC3TBUWE.js";
27
+ } from "../chunk-67HMVGV7.js";
28
+ import "../chunk-UBHORKBS.js";
17
29
  import "../chunk-J4ZVCXZ4.js";
18
- import "../chunk-OQ7U6EQ3.js";
19
- import "../chunk-H6365JPC.js";
20
- import "../chunk-3PJTNH2L.js";
21
- import "../chunk-5EFDS7SR.js";
22
- import "../chunk-P4UZ7IXC.js";
30
+ import "../chunk-YUX6RGLZ.js";
31
+ import "../chunk-AKIRHA4Q.js";
32
+ import "../chunk-DMVUEJG2.js";
33
+ import "../chunk-7D4SUZUM.js";
23
34
  export {
24
35
  AuthProvider,
36
+ OfflineAuthProvider,
25
37
  PermissionProvider,
38
+ SimpleAuthProvider,
26
39
  UserMetadataProvider,
27
40
  entityPermissionContext,
41
+ getPermissionLevel,
42
+ hasResourceAccess,
28
43
  permissionContext,
29
44
  setupAuthContext,
30
45
  usePermissions,
46
+ useRequireAuth,
47
+ useResourceAccess,
31
48
  useSetUserMetadata,
49
+ useSimpleAuth,
50
+ useCanDelete as useSimpleCanDelete,
51
+ useCanEdit as useSimpleCanEdit,
52
+ useCanShare as useSimpleCanShare,
53
+ useCanView as useSimpleCanView,
32
54
  useUserMetadata,
33
55
  useUserMetadataState,
34
56
  useUserMetadataValue,
@@ -2,7 +2,7 @@ import { b as EntityPermissionCheck, a as EntityAction } from '../EntityPermissi
2
2
 
3
3
  /**
4
4
  * Check if a user has access to a specific permission key.
5
- * Owners bypass all permission checks.
5
+ * Super-admin key (*:*:*) bypasses all permission checks.
6
6
  *
7
7
  * @param accessKeys - Array of access keys the user has
8
8
  * @param key - The access key to check for
@@ -17,8 +17,8 @@ import { b as EntityPermissionCheck, a as EntityAction } from '../EntityPermissi
17
17
  * const canAccess = hasAccess(['admin', 'viewer'], 'admin'); // true
18
18
  * const cannotAccess = hasAccess(['viewer'], 'admin'); // false
19
19
  *
20
- * // Owner bypasses all checks
21
- * const ownerAccess = hasAccess(['owner'], 'any-key'); // true
20
+ * // Super-admin key bypasses all checks
21
+ * const superAdminAccess = hasAccess(['*:*:*'], 'any-key'); // true
22
22
  *
23
23
  * // Empty key always returns true (no permission required)
24
24
  * const noKeyRequired = hasAccess(['viewer'], ''); // true
@@ -70,12 +70,12 @@ declare function hasAllAccess(accessKeys: string[] | undefined | null, keys: str
70
70
 
71
71
  /**
72
72
  * Check if a user has entity-level access based on permission check result.
73
- * Owners (users with 'owner' access key) bypass entity permissions entirely.
73
+ * Super-admin key (*:*:*) bypasses entity permissions entirely.
74
74
  *
75
75
  * @param permission - The permission check result from getPermission/usePermission
76
76
  * @param action - The action to check for
77
77
  * @param options - Additional options for the check
78
- * @param options.accessKeys - User's access keys (for owner check)
78
+ * @param options.accessKeys - User's access keys (for super-admin check)
79
79
  * @param options.isArchived - Whether the user is archived
80
80
  * @param options.isSuspended - Whether the user is suspended
81
81
  * @returns boolean - true if user has permission for the action
@@ -86,10 +86,10 @@ declare function hasAllAccess(accessKeys: string[] | undefined | null, keys: str
86
86
  * const permission = await getPermission('Project', 123);
87
87
  * const canEdit = hasEntityAccess(permission, 'edit');
88
88
  *
89
- * // With owner bypass
90
- * const canEditAsOwner = hasEntityAccess(permission, 'edit', {
91
- * accessKeys: ['owner'],
92
- * }); // true, owners bypass all checks
89
+ * // With super-admin bypass
90
+ * const canEditAsSuperAdmin = hasEntityAccess(permission, 'edit', {
91
+ * accessKeys: ['*:*:*'],
92
+ * }); // true, super-admin bypasses all checks
93
93
  *
94
94
  * // Check loading state
95
95
  * if (permission.isLoading) {
@@ -7,9 +7,8 @@ import {
7
7
  hasEntityAccess,
8
8
  isEntityAccessDenied,
9
9
  isPermissionLoaded
10
- } from "../chunk-HAWJTZCK.js";
11
- import "../chunk-OQ7U6EQ3.js";
12
- import "../chunk-P4UZ7IXC.js";
10
+ } from "../chunk-RT4O5H2E.js";
11
+ import "../chunk-7D4SUZUM.js";
13
12
  export {
14
13
  hasAccess,
15
14
  hasAllAccess,
@@ -1,12 +1,116 @@
1
1
  import { User } from '@supabase/supabase-js';
2
+ import { k as SimpleProfile, l as SimpleUserAccess } from '../UserMetadataContext-QLIv-mfF.js';
3
+ export { m as useSetUserMetadata, n as useUserMetadata, o as useUserMetadataState, p as useUserMetadataValue } from '../UserMetadataContext-QLIv-mfF.js';
2
4
  import { S as SetupAuthContext, E as EffectivePermission } from '../setupAuthContext-B76nbIP6.js';
3
5
  import { d as EntityType, a as EntityAction, b as EntityPermissionCheck } from '../EntityPermissions-DwFt4tUd.js';
4
- export { u as useSetUserMetadata, a as useUserMetadata, b as useUserMetadataState, c as useUserMetadataValue } from '../UserMetadataContext-DntmpK41.js';
5
- import 'react';
6
6
  import 'react/jsx-runtime';
7
- import '../useSupabase-DvWVuHHE.js';
7
+ import 'react';
8
+ import '../useSupabase-DSZNeXnF.js';
8
9
  import '@supabase/supabase-js/dist/module/lib/types.js';
9
10
 
11
+ /**
12
+ * useOfflineAuth - Hook for offline-first authentication
13
+ *
14
+ * Reads Profile and UserAccess from PowerSync (local SQLite).
15
+ * Works 100% offline once data is synced.
16
+ *
17
+ * Usage:
18
+ * ```tsx
19
+ * import { SimpleAuthProvider } from "@pol-studios/db";
20
+ * import { useOfflineAuth } from "@pol-studios/db";
21
+ *
22
+ * function AuthWrapper({ children }) {
23
+ * const authData = useOfflineAuth();
24
+ *
25
+ * return (
26
+ * <SimpleAuthProvider {...authData}>
27
+ * {children}
28
+ * </SimpleAuthProvider>
29
+ * );
30
+ * }
31
+ * ```
32
+ */
33
+
34
+ interface OfflineAuthData {
35
+ /** Supabase user from auth session */
36
+ user: User | null;
37
+ /** Profile from PowerSync */
38
+ profile: SimpleProfile | null;
39
+ /** User access records from PowerSync */
40
+ userAccess: SimpleUserAccess[] | null;
41
+ /** Whether auth data is loading */
42
+ isLoading: boolean;
43
+ /** Sign out function */
44
+ onSignOut: () => Promise<void>;
45
+ }
46
+ interface UseOfflineAuthOptions {
47
+ /** Supabase client for auth operations */
48
+ supabase: {
49
+ auth: {
50
+ getUser: () => Promise<{
51
+ data: {
52
+ user: User | null;
53
+ };
54
+ error: any;
55
+ }>;
56
+ signOut: () => Promise<{
57
+ error: any;
58
+ }>;
59
+ onAuthStateChange: (callback: (event: string, session: any) => void) => {
60
+ data: {
61
+ subscription: {
62
+ unsubscribe: () => void;
63
+ };
64
+ };
65
+ };
66
+ };
67
+ };
68
+ /** PowerSync database for local queries */
69
+ db: {
70
+ getAll: <T>(sql: string, params?: any[]) => Promise<T[]>;
71
+ getOptional: <T>(sql: string, params?: any[]) => Promise<T | null>;
72
+ } | null;
73
+ /** Whether PowerSync is ready */
74
+ isDbReady?: boolean;
75
+ }
76
+ /**
77
+ * Query keys for React Query integration
78
+ */
79
+ declare const offlineAuthQueryKeys: {
80
+ profile: (userId: string | undefined) => readonly ["profile", string];
81
+ userAccess: (userId: string | undefined) => readonly ["userAccess", string];
82
+ };
83
+ /**
84
+ * Query functions for React Query integration.
85
+ * Use these with useQuery from @tanstack/react-query.
86
+ *
87
+ * @example
88
+ * ```tsx
89
+ * import { useQuery } from "@tanstack/react-query";
90
+ * import { offlineAuthQueries, offlineAuthQueryKeys } from "@pol-studios/db";
91
+ *
92
+ * function useProfile(db, userId) {
93
+ * return useQuery({
94
+ * queryKey: offlineAuthQueryKeys.profile(userId),
95
+ * queryFn: () => offlineAuthQueries.fetchProfile(db, userId),
96
+ * enabled: !!userId && !!db,
97
+ * });
98
+ * }
99
+ * ```
100
+ */
101
+ declare const offlineAuthQueries: {
102
+ fetchProfile(db: {
103
+ getOptional: <T>(sql: string, params?: any[]) => Promise<T | null>;
104
+ }, userId: string): Promise<SimpleProfile | null>;
105
+ fetchUserAccess(db: {
106
+ getAll: <T>(sql: string, params?: any[]) => Promise<T[]>;
107
+ }, userId: string): Promise<SimpleUserAccess[]>;
108
+ };
109
+ /**
110
+ * Extract access keys from UserAccess records.
111
+ */
112
+ declare function extractAccessKeys(userAccess: SimpleUserAccess[] | null): string[];
113
+
10
114
  /**
11
115
  * Hook for authenticated users only.
12
116
  * Throws an error if the user is not authenticated.
@@ -310,4 +414,4 @@ declare function useInvalidatePermission(): (entityType: EntityType, entityId: n
310
414
  */
311
415
  declare function usePermissionLoading(): boolean;
312
416
 
313
- export { EntityAction, EntityPermissionCheck, EntityType, type EntityWithPermission, useAuth, useCanCreate, useCanDelete, useCanEdit, useCanShare, useCanView, useInvalidatePermission, usePermission, usePermissionCheck, usePermissionLoading, usePermissionsBatch, useSetupAuth };
417
+ export { EntityAction, EntityPermissionCheck, EntityType, type EntityWithPermission, type OfflineAuthData, type UseOfflineAuthOptions, extractAccessKeys, offlineAuthQueries, offlineAuthQueryKeys, useAuth, useCanCreate, useCanDelete, useCanEdit, useCanShare, useCanView, useInvalidatePermission, usePermission, usePermissionCheck, usePermissionLoading, usePermissionsBatch, useSetupAuth };