@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.
- package/README.md +434 -0
- package/dist/EntityPermissions-DwFt4tUd.d.ts +35 -0
- package/dist/FilterConfig-Bt2Ek74z.d.ts +99 -0
- package/dist/UserMetadataContext-BYYqA6LI.d.ts +89 -0
- package/dist/auth/context.d.ts +47 -0
- package/dist/auth/context.js +12791 -0
- package/dist/auth/context.js.map +1 -0
- package/dist/auth/guards.d.ts +180 -0
- package/dist/auth/guards.js +7651 -0
- package/dist/auth/guards.js.map +1 -0
- package/dist/auth/hooks.d.ts +312 -0
- package/dist/auth/hooks.js +10600 -0
- package/dist/auth/hooks.js.map +1 -0
- package/dist/auth/index.d.ts +10 -0
- package/dist/auth/index.js +13035 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/client/index.d.ts +16 -0
- package/dist/core/index.d.ts +508 -0
- package/dist/executor-CB4KHyYG.d.ts +507 -0
- package/dist/gen/index.d.ts +1099 -0
- package/dist/hooks/index.d.ts +83 -0
- package/dist/index-DNrSptau.d.ts +8780 -0
- package/dist/index.d.ts +338 -0
- package/dist/index.js +10320 -7124
- package/dist/index.js.map +1 -1
- package/dist/index.web.d.ts +318 -0
- package/dist/index.web.js +56795 -0
- package/dist/index.web.js.map +1 -0
- package/dist/mutation/index.d.ts +58 -0
- package/dist/mutation/index.js +4581 -76
- package/dist/mutation/index.js.map +1 -1
- package/dist/parser/index.d.ts +366 -0
- package/dist/parser/index.js +26 -26
- package/dist/parser/index.js.map +1 -1
- package/dist/query/index.d.ts +723 -0
- package/dist/query/index.js +13124 -10324
- package/dist/query/index.js.map +1 -1
- package/dist/realtime/index.d.ts +44 -0
- package/dist/realtime/index.js +13217 -9297
- package/dist/realtime/index.js.map +1 -1
- package/dist/select-query-parser-CLkOKHzc.d.ts +352 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types-CKsWM8T3.d.ts +62 -0
- package/dist/useBatchUpsert-ooLlpJMg.d.ts +24 -0
- package/dist/useDbCount-B5-Va9sg.d.ts +1740 -0
- package/dist/useDbQuery-C-TL8jY1.d.ts +19 -0
- package/dist/useResolveFeedback-DuGP4Tgb.d.ts +1165 -0
- package/dist/useSupabase-pPhUZHcl.d.ts +27 -0
- package/package.json +31 -7
package/README.md
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
# @pol-studios/db
|
|
2
|
+
|
|
3
|
+
> Database layer for React applications with Supabase and PowerSync support
|
|
4
|
+
|
|
5
|
+
A comprehensive database abstraction layer supporting both Supabase (V2 hooks) and PowerSync (V3 hooks) for offline-first applications. Provides React Query integration, realtime subscriptions, mutation hooks, and storage utilities.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @pol-studios/db
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Peer Dependencies
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Required
|
|
17
|
+
pnpm add react @supabase/supabase-js @tanstack/react-query @pol-studios/auth @pol-studios/hooks
|
|
18
|
+
|
|
19
|
+
# Optional (for React Native / offline-first)
|
|
20
|
+
pnpm add @powersync/react-native @react-native-community/netinfo react-native
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { SupabaseProvider, useDbQuery, useDbInsert, useDbUpdate, useDbDelete } from "@pol-studios/db";
|
|
27
|
+
|
|
28
|
+
// Wrap your app with the provider
|
|
29
|
+
function App() {
|
|
30
|
+
return (
|
|
31
|
+
<SupabaseProvider url={SUPABASE_URL} anonKey={SUPABASE_ANON_KEY}>
|
|
32
|
+
<QueryClientProvider client={queryClient}>
|
|
33
|
+
<MyApp />
|
|
34
|
+
</QueryClientProvider>
|
|
35
|
+
</SupabaseProvider>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Query data
|
|
40
|
+
function ProjectList() {
|
|
41
|
+
const { data, isLoading } = useDbQuery("projects", {
|
|
42
|
+
select: "*",
|
|
43
|
+
order: { column: "created_at", ascending: false },
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (isLoading) return <Loading />;
|
|
47
|
+
return <List items={data} />;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Mutations
|
|
51
|
+
function CreateProject() {
|
|
52
|
+
const insert = useDbInsert("projects");
|
|
53
|
+
const update = useDbUpdate("projects");
|
|
54
|
+
const remove = useDbDelete("projects");
|
|
55
|
+
|
|
56
|
+
const handleCreate = () => {
|
|
57
|
+
insert.mutate({ name: "New Project", status: "active" });
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleUpdate = (id, data) => {
|
|
61
|
+
update.mutate({ id, ...data });
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const handleDelete = (id) => {
|
|
65
|
+
remove.mutate({ id });
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Subpath Exports
|
|
71
|
+
|
|
72
|
+
| Path | Description |
|
|
73
|
+
|------|-------------|
|
|
74
|
+
| `@pol-studios/db` | All exports combined |
|
|
75
|
+
| `@pol-studios/db/client` | Supabase client utilities |
|
|
76
|
+
| `@pol-studios/db/core` | Core types and configuration |
|
|
77
|
+
| `@pol-studios/db/query` | Query system utilities |
|
|
78
|
+
| `@pol-studios/db/mutation` | Mutation hooks (batch operations) |
|
|
79
|
+
| `@pol-studios/db/realtime` | Realtime subscription utilities |
|
|
80
|
+
| `@pol-studios/db/parser` | Query parser utilities |
|
|
81
|
+
| `@pol-studios/db/hooks` | V3 hooks (PowerSync) |
|
|
82
|
+
| `@pol-studios/db/types` | TypeScript type definitions |
|
|
83
|
+
| `@pol-studios/db/gen` | Generated entity configurations |
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
86
|
+
|
|
87
|
+
### V2 Hooks (Supabase-based)
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
import {
|
|
91
|
+
// Query hooks
|
|
92
|
+
useDbQuery,
|
|
93
|
+
useDbInfiniteQuery,
|
|
94
|
+
useDbAdvanceQuery,
|
|
95
|
+
useDbPartialQuery,
|
|
96
|
+
useDbRealtimeQuery,
|
|
97
|
+
|
|
98
|
+
// Mutation hooks
|
|
99
|
+
useDbInsert,
|
|
100
|
+
useDbUpdate,
|
|
101
|
+
useDbDelete,
|
|
102
|
+
useDbUpsert,
|
|
103
|
+
useDbMultiUpsert,
|
|
104
|
+
useDbMultiDelete,
|
|
105
|
+
|
|
106
|
+
// Batch mutations
|
|
107
|
+
useBatchUpsert,
|
|
108
|
+
useBatchDelete,
|
|
109
|
+
} from "@pol-studios/db";
|
|
110
|
+
|
|
111
|
+
// Basic query
|
|
112
|
+
const { data } = useDbQuery("projects", {
|
|
113
|
+
select: "id, name, status",
|
|
114
|
+
filter: { status: "active" },
|
|
115
|
+
order: { column: "name" },
|
|
116
|
+
limit: 10,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Infinite scroll query
|
|
120
|
+
const { data, fetchNextPage, hasNextPage } = useDbInfiniteQuery("projects", {
|
|
121
|
+
select: "*",
|
|
122
|
+
pageSize: 20,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Advanced query with joins
|
|
126
|
+
const { data } = useDbAdvanceQuery("projects", {
|
|
127
|
+
select: "*, tasks(*), owner:profiles(*)",
|
|
128
|
+
filter: { archived: false },
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Realtime query (auto-updates on changes)
|
|
132
|
+
const { data } = useDbRealtimeQuery("projects", {
|
|
133
|
+
select: "*",
|
|
134
|
+
filter: { team_id: teamId },
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Insert with automatic cache invalidation
|
|
138
|
+
const { mutate: insert } = useDbInsert("projects");
|
|
139
|
+
insert({ name: "New Project" });
|
|
140
|
+
|
|
141
|
+
// Update
|
|
142
|
+
const { mutate: update } = useDbUpdate("projects");
|
|
143
|
+
update({ id: projectId, name: "Updated Name" });
|
|
144
|
+
|
|
145
|
+
// Upsert
|
|
146
|
+
const { mutate: upsert } = useDbUpsert("projects");
|
|
147
|
+
upsert({ id: projectId, name: "Name" }); // Insert or update
|
|
148
|
+
|
|
149
|
+
// Batch operations
|
|
150
|
+
const { mutate: batchUpsert } = useBatchUpsert("projects");
|
|
151
|
+
batchUpsert(projectsArray);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### V3 Hooks (PowerSync / Offline-first)
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import {
|
|
158
|
+
// V3 Query hooks
|
|
159
|
+
useDbQueryV3,
|
|
160
|
+
useDbQueryById,
|
|
161
|
+
useDbInfiniteQueryV3,
|
|
162
|
+
useDbCountV3,
|
|
163
|
+
useAdvanceQuery,
|
|
164
|
+
|
|
165
|
+
// V3 Mutation hooks
|
|
166
|
+
useDbInsertV3,
|
|
167
|
+
useDbUpdateV3,
|
|
168
|
+
useDbDeleteV3,
|
|
169
|
+
useDbUpsertV3,
|
|
170
|
+
|
|
171
|
+
// Sync utilities
|
|
172
|
+
useSyncStatus,
|
|
173
|
+
useSyncControl,
|
|
174
|
+
useOnlineStatus,
|
|
175
|
+
useDataLayer,
|
|
176
|
+
} from "@pol-studios/db";
|
|
177
|
+
|
|
178
|
+
// V3 queries work offline with PowerSync
|
|
179
|
+
const { data } = useDbQueryV3("projects", {
|
|
180
|
+
where: { status: "active" },
|
|
181
|
+
orderBy: { created_at: "desc" },
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Get single item by ID
|
|
185
|
+
const { data: project } = useDbQueryById("projects", projectId);
|
|
186
|
+
|
|
187
|
+
// Count query
|
|
188
|
+
const { data: count } = useDbCountV3("projects", {
|
|
189
|
+
where: { status: "active" },
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Sync status
|
|
193
|
+
const { isSyncing, lastSyncTime, pendingChanges } = useSyncStatus();
|
|
194
|
+
|
|
195
|
+
// Control sync
|
|
196
|
+
const { startSync, stopSync, forceSync } = useSyncControl();
|
|
197
|
+
|
|
198
|
+
// Online status
|
|
199
|
+
const isOnline = useOnlineStatus();
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Supabase Client
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
import {
|
|
206
|
+
useSupabase,
|
|
207
|
+
SupabaseProvider,
|
|
208
|
+
createNewSupabaseClient,
|
|
209
|
+
typedSupabase,
|
|
210
|
+
onSupabaseInitialized,
|
|
211
|
+
setDefaultOptions,
|
|
212
|
+
} from "@pol-studios/db";
|
|
213
|
+
|
|
214
|
+
// Get typed Supabase client
|
|
215
|
+
const supabase = useSupabase();
|
|
216
|
+
|
|
217
|
+
// Direct client creation
|
|
218
|
+
const client = createNewSupabaseClient(url, key);
|
|
219
|
+
|
|
220
|
+
// Typed client for specific database schema
|
|
221
|
+
const typed = typedSupabase(client);
|
|
222
|
+
|
|
223
|
+
// Initialize callback
|
|
224
|
+
onSupabaseInitialized((client) => {
|
|
225
|
+
console.log("Supabase ready");
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Realtime Subscriptions
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
import { useDbRealtime, useLiveChangesIndicator, useLiveChangeTracking } from "@pol-studios/db";
|
|
233
|
+
|
|
234
|
+
// Subscribe to table changes
|
|
235
|
+
useDbRealtime("projects", {
|
|
236
|
+
event: "INSERT",
|
|
237
|
+
filter: `team_id=eq.${teamId}`,
|
|
238
|
+
callback: (payload) => {
|
|
239
|
+
console.log("New project:", payload.new);
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Track live changes indicator
|
|
244
|
+
const { hasChanges, changeCount } = useLiveChangesIndicator("projects");
|
|
245
|
+
|
|
246
|
+
// Track specific changes
|
|
247
|
+
const { changes, clearChanges } = useLiveChangeTracking("projects", projectId);
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Storage
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
import {
|
|
254
|
+
useStorageUrl,
|
|
255
|
+
useStoragePath,
|
|
256
|
+
useStorageUpload,
|
|
257
|
+
useStorageUploadWithEntity,
|
|
258
|
+
useDbUpload,
|
|
259
|
+
} from "@pol-studios/db";
|
|
260
|
+
|
|
261
|
+
// Get public URL for storage path
|
|
262
|
+
const url = useStorageUrl("avatars", "user-123.png");
|
|
263
|
+
|
|
264
|
+
// Generate storage path
|
|
265
|
+
const path = useStoragePath("documents", { entityId, fileName });
|
|
266
|
+
|
|
267
|
+
// Upload file
|
|
268
|
+
const { upload, isUploading, progress } = useStorageUpload("documents");
|
|
269
|
+
await upload(file);
|
|
270
|
+
|
|
271
|
+
// Upload with entity association
|
|
272
|
+
const { upload } = useStorageUploadWithEntity("attachments", {
|
|
273
|
+
entityType: "project",
|
|
274
|
+
entityId: projectId,
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Utility Hooks
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
import {
|
|
282
|
+
useAI,
|
|
283
|
+
useReceiptAI,
|
|
284
|
+
useServerAvailability,
|
|
285
|
+
useSearchQuery,
|
|
286
|
+
useAutosaveState,
|
|
287
|
+
useBackgroundTask,
|
|
288
|
+
useToastError,
|
|
289
|
+
useLatestOperationLog,
|
|
290
|
+
useConsent,
|
|
291
|
+
useAccountDeletion,
|
|
292
|
+
useUserStatus,
|
|
293
|
+
useDataExport,
|
|
294
|
+
} from "@pol-studios/db";
|
|
295
|
+
|
|
296
|
+
// AI integration
|
|
297
|
+
const { generate, isLoading } = useAI();
|
|
298
|
+
|
|
299
|
+
// Receipt AI processing
|
|
300
|
+
const { processReceipt } = useReceiptAI();
|
|
301
|
+
|
|
302
|
+
// Server availability check
|
|
303
|
+
const isAvailable = useServerAvailability();
|
|
304
|
+
|
|
305
|
+
// Search with debounce
|
|
306
|
+
const { results, search } = useSearchQuery("projects", { debounce: 300 });
|
|
307
|
+
|
|
308
|
+
// Autosave state
|
|
309
|
+
const [value, setValue, { isDirty, isSaving }] = useAutosaveState(initial, saveFn);
|
|
310
|
+
|
|
311
|
+
// Background task
|
|
312
|
+
const { run, isRunning, progress } = useBackgroundTask(asyncFn);
|
|
313
|
+
|
|
314
|
+
// Error toast integration
|
|
315
|
+
const showError = useToastError();
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Edge Functions
|
|
319
|
+
|
|
320
|
+
```tsx
|
|
321
|
+
import { useSupabaseFunction } from "@pol-studios/db";
|
|
322
|
+
|
|
323
|
+
// Call Supabase Edge Functions
|
|
324
|
+
const { invoke, isLoading, data, error } = useSupabaseFunction("process-data");
|
|
325
|
+
await invoke({ input: "value" });
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Data Layer Provider (V3)
|
|
329
|
+
|
|
330
|
+
```tsx
|
|
331
|
+
import { DataLayerProvider, useDataLayer } from "@pol-studios/db";
|
|
332
|
+
|
|
333
|
+
// Wrap app for offline-first support
|
|
334
|
+
<DataLayerProvider config={dataLayerConfig}>
|
|
335
|
+
<App />
|
|
336
|
+
</DataLayerProvider>
|
|
337
|
+
|
|
338
|
+
// Access data layer
|
|
339
|
+
const { adapter, isReady, syncStatus } = useDataLayer();
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## TypeScript Types
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
import type {
|
|
346
|
+
// Database types
|
|
347
|
+
DatabaseTypes,
|
|
348
|
+
TableNames,
|
|
349
|
+
PublicTableNames,
|
|
350
|
+
SchemaNames,
|
|
351
|
+
SchemaTableNames,
|
|
352
|
+
|
|
353
|
+
// Query types
|
|
354
|
+
QueryOptions,
|
|
355
|
+
QueryResult,
|
|
356
|
+
QuerySingleResult,
|
|
357
|
+
WhereClause,
|
|
358
|
+
WhereOperators,
|
|
359
|
+
OrderBy,
|
|
360
|
+
|
|
361
|
+
// Mutation types
|
|
362
|
+
MutationResult,
|
|
363
|
+
MutationHookResult,
|
|
364
|
+
DeleteMutationResult,
|
|
365
|
+
ExtractRow,
|
|
366
|
+
ExtractInsert,
|
|
367
|
+
ExtractUpdate,
|
|
368
|
+
|
|
369
|
+
// V3 types
|
|
370
|
+
DataLayerConfig,
|
|
371
|
+
DataAdapter,
|
|
372
|
+
SyncStatus,
|
|
373
|
+
SyncMode,
|
|
374
|
+
SyncScope,
|
|
375
|
+
SyncControl,
|
|
376
|
+
ConnectionConfig,
|
|
377
|
+
|
|
378
|
+
// Strategy types
|
|
379
|
+
SupabaseStrategy,
|
|
380
|
+
PowerSyncStrategy,
|
|
381
|
+
HybridStrategy,
|
|
382
|
+
CachedStrategy,
|
|
383
|
+
AutoStrategy,
|
|
384
|
+
TableStrategy,
|
|
385
|
+
|
|
386
|
+
// Schema types
|
|
387
|
+
DatabaseSchema,
|
|
388
|
+
TableSchema,
|
|
389
|
+
ColumnInfo,
|
|
390
|
+
ColumnType,
|
|
391
|
+
RelationshipInfo,
|
|
392
|
+
RelationshipType,
|
|
393
|
+
|
|
394
|
+
// Supabase types
|
|
395
|
+
TypedSupabaseClient,
|
|
396
|
+
SupabaseDatabaseTypes,
|
|
397
|
+
UserSessionId,
|
|
398
|
+
} from "@pol-studios/db";
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## Network Utilities
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
import {
|
|
405
|
+
getOnlineStatus,
|
|
406
|
+
getOnlineStatusSync,
|
|
407
|
+
initializeNetworkMonitoring,
|
|
408
|
+
subscribeToNetworkChanges,
|
|
409
|
+
isReactNative,
|
|
410
|
+
} from "@pol-studios/db";
|
|
411
|
+
|
|
412
|
+
// Check online status
|
|
413
|
+
const isOnline = await getOnlineStatus();
|
|
414
|
+
const isOnlineSync = getOnlineStatusSync();
|
|
415
|
+
|
|
416
|
+
// Initialize network monitoring
|
|
417
|
+
initializeNetworkMonitoring();
|
|
418
|
+
|
|
419
|
+
// Subscribe to network changes
|
|
420
|
+
const unsubscribe = subscribeToNetworkChanges((isOnline) => {
|
|
421
|
+
console.log("Network:", isOnline ? "online" : "offline");
|
|
422
|
+
});
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Related Packages
|
|
426
|
+
|
|
427
|
+
- [@pol-studios/auth](../auth) - Authentication (required peer dependency)
|
|
428
|
+
- [@pol-studios/hooks](../hooks) - React hooks (required peer dependency)
|
|
429
|
+
- [@pol-studios/utils](../utils) - Utility functions
|
|
430
|
+
- [@pol-studios/features](../features) - Feature modules (uses db)
|
|
431
|
+
|
|
432
|
+
## License
|
|
433
|
+
|
|
434
|
+
UNLICENSED
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
type EntityType = 'Project' | 'Client' | 'ProjectDatabase';
|
|
2
|
+
type EntityPermissionLevel = 'ReadOnly' | 'AdminReadOnly' | 'ReadWrite' | 'Admin';
|
|
3
|
+
type PermissionEffect = 'allow' | 'deny';
|
|
4
|
+
type EntityAction = 'view' | 'adminView' | 'edit' | 'create' | 'delete' | 'share';
|
|
5
|
+
interface EntityPermissionCheck {
|
|
6
|
+
canView: boolean;
|
|
7
|
+
canAdminView: boolean;
|
|
8
|
+
canEdit: boolean;
|
|
9
|
+
canCreate: boolean;
|
|
10
|
+
canDelete: boolean;
|
|
11
|
+
canShare: boolean;
|
|
12
|
+
permissionLevel: EntityPermissionLevel | null;
|
|
13
|
+
isLoading: boolean;
|
|
14
|
+
/** Whether access was explicitly denied */
|
|
15
|
+
isDenied?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface EntityAccessRecord {
|
|
18
|
+
id: number;
|
|
19
|
+
userId: string;
|
|
20
|
+
entityType: EntityType;
|
|
21
|
+
entityId: number;
|
|
22
|
+
permission: EntityPermissionLevel;
|
|
23
|
+
/** Permission effect - 'allow' grants access, 'deny' explicitly blocks */
|
|
24
|
+
effect: PermissionEffect;
|
|
25
|
+
inheritedFromClientId?: number | null;
|
|
26
|
+
inheritFromProject?: boolean;
|
|
27
|
+
/** User ID who granted this permission */
|
|
28
|
+
grantedBy?: string | null;
|
|
29
|
+
/** ISO timestamp when permission was granted */
|
|
30
|
+
grantedAt?: string;
|
|
31
|
+
/** ISO timestamp when permission expires, null for never */
|
|
32
|
+
expiresAt?: string | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type { EntityAccessRecord as E, PermissionEffect as P, EntityAction as a, EntityPermissionCheck as b, EntityPermissionLevel as c, EntityType as d };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Filter Configuration Type
|
|
3
|
+
*
|
|
4
|
+
* This is the canonical type for filter configuration across the codebase.
|
|
5
|
+
* Replaces both ValueOption and SimpleFilterConfig.
|
|
6
|
+
*/
|
|
7
|
+
type PropertyType = "string" | "number" | "boolean" | "date";
|
|
8
|
+
type ValueForPropertyType<T extends PropertyType> = T extends "string" ? string : T extends "number" ? number : T extends "boolean" ? boolean : T extends "date" ? Date : never;
|
|
9
|
+
interface TableInfo {
|
|
10
|
+
tableName: string;
|
|
11
|
+
schemaName?: string;
|
|
12
|
+
outputProperty?: string;
|
|
13
|
+
innerProperty: string;
|
|
14
|
+
innerCast?: string;
|
|
15
|
+
}
|
|
16
|
+
interface SortConfig {
|
|
17
|
+
isSortable?: boolean;
|
|
18
|
+
properties?: string[];
|
|
19
|
+
}
|
|
20
|
+
interface FilterConfigOption<PT extends PropertyType = PropertyType> {
|
|
21
|
+
display: string;
|
|
22
|
+
value: ValueForPropertyType<PT>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Simple filter clause for WHERE conditions
|
|
26
|
+
* Used in edge function query building
|
|
27
|
+
*/
|
|
28
|
+
interface WhereFilter {
|
|
29
|
+
id: string;
|
|
30
|
+
field: string;
|
|
31
|
+
op: string;
|
|
32
|
+
value: string | number | string[] | number[] | boolean | null;
|
|
33
|
+
not?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* WhereClause can be either:
|
|
37
|
+
* - string: For edge function format like "tagId.eq.5"
|
|
38
|
+
* - WhereFilter: For complex filter objects
|
|
39
|
+
*/
|
|
40
|
+
type WhereClause = string | WhereFilter;
|
|
41
|
+
/**
|
|
42
|
+
* Unified FilterConfig - the canonical filter configuration type
|
|
43
|
+
*
|
|
44
|
+
* Uses `field` with dot notation for relationships.
|
|
45
|
+
* Examples: "name", "locationId.name", "locationId.tags.value"
|
|
46
|
+
*/
|
|
47
|
+
interface FilterConfig<EntityType = unknown, PT extends PropertyType = PropertyType> {
|
|
48
|
+
/**
|
|
49
|
+
* Field path using dot notation for relationships
|
|
50
|
+
* Examples: "name", "locationId.name", "locationId.tags.value"
|
|
51
|
+
*/
|
|
52
|
+
field?: string;
|
|
53
|
+
/** The property name on the entity */
|
|
54
|
+
property?: keyof EntityType | string;
|
|
55
|
+
/** Display label shown in UI */
|
|
56
|
+
display: string;
|
|
57
|
+
/**
|
|
58
|
+
* Data type of the field. Can be inferred from schema when using `field`.
|
|
59
|
+
*/
|
|
60
|
+
propertyType?: PT;
|
|
61
|
+
/** Whether this field is searchable via text search (default: true for strings) */
|
|
62
|
+
searchable?: boolean;
|
|
63
|
+
/** Additional WHERE clause for relationship filtering */
|
|
64
|
+
where?: WhereClause;
|
|
65
|
+
/** Relationship configuration for many-to-one joins */
|
|
66
|
+
manyToOneTableInfo?: TableInfo & {
|
|
67
|
+
innerTable?: TableInfo[];
|
|
68
|
+
};
|
|
69
|
+
/** Predefined dropdown options */
|
|
70
|
+
options?: FilterConfigOption<PT>[];
|
|
71
|
+
/** Sort configuration for this field */
|
|
72
|
+
sortOptions?: SortConfig;
|
|
73
|
+
/** Mark as metadata field (custom columns) */
|
|
74
|
+
isMetadata?: boolean;
|
|
75
|
+
/** Hide behind "Show More Filters" button */
|
|
76
|
+
advanced?: boolean;
|
|
77
|
+
/** Show in "Recommended" section */
|
|
78
|
+
recommended?: boolean;
|
|
79
|
+
/** Custom render function for display in filter dropdown */
|
|
80
|
+
renderOption?: (option: FilterConfig<EntityType, PT>) => string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Group of filter configs for organizing filters in UI
|
|
84
|
+
* Note: Named "Group" to avoid conflict with FilterGroup (AND/OR query groups)
|
|
85
|
+
*/
|
|
86
|
+
interface Group {
|
|
87
|
+
/** Title displayed for the group (used as 'label' in some contexts) */
|
|
88
|
+
title: string;
|
|
89
|
+
/** Optional nesting level for UI rendering */
|
|
90
|
+
level?: number;
|
|
91
|
+
/** Hide entire group by default behind "Show More Filters" button */
|
|
92
|
+
advanced?: boolean;
|
|
93
|
+
/** Show this group in the "Recommended" section at the top of the filter dropdown */
|
|
94
|
+
recommended?: boolean;
|
|
95
|
+
/** Child filter configs or nested groups */
|
|
96
|
+
children: (FilterConfig | Group)[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type { FilterConfigOption as F, Group as G, PropertyType as P, SortConfig as S, TableInfo as T, ValueForPropertyType as V, WhereFilter as W, FilterConfig as a, WhereClause as b };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
import { User, SignUpWithPasswordCredentials, AuthTokenResponsePassword } from '@supabase/supabase-js';
|
|
5
|
+
import { D as Database } from './useSupabase-pPhUZHcl.js';
|
|
6
|
+
|
|
7
|
+
type ProfileStatus = "active" | "archived" | "suspended";
|
|
8
|
+
interface SetupAuthContext {
|
|
9
|
+
user?: User | null | undefined;
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
profile: Profile | null | undefined;
|
|
12
|
+
access: string[];
|
|
13
|
+
/** Whether the profile is archived */
|
|
14
|
+
isArchived: boolean;
|
|
15
|
+
/** Whether the profile is suspended */
|
|
16
|
+
isSuspended: boolean;
|
|
17
|
+
/** The profile status (active, archived, suspended) */
|
|
18
|
+
profileStatus: ProfileStatus | undefined;
|
|
19
|
+
registerAsync: (register: SignUpWithPasswordCredentials) => Promise<any>;
|
|
20
|
+
signInAsync: (username: string, password: string) => Promise<AuthTokenResponsePassword>;
|
|
21
|
+
signOutAsync: () => Promise<any>;
|
|
22
|
+
refreshAsync: () => Promise<void>;
|
|
23
|
+
onSignOut: (action: () => any) => string;
|
|
24
|
+
removeOnSignOut: (id: string) => any;
|
|
25
|
+
hasAccess?: (key: string) => boolean;
|
|
26
|
+
}
|
|
27
|
+
interface Profile {
|
|
28
|
+
id: string;
|
|
29
|
+
email?: string;
|
|
30
|
+
fullName?: string;
|
|
31
|
+
status?: ProfileStatus;
|
|
32
|
+
UserAccess?: Array<{
|
|
33
|
+
accessKey: string;
|
|
34
|
+
}>;
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
}
|
|
37
|
+
declare const setupAuthContext: react.Context<SetupAuthContext>;
|
|
38
|
+
/**
|
|
39
|
+
* Props for SetupAuthContextProvider
|
|
40
|
+
* A simpler provider that takes pre-computed auth state
|
|
41
|
+
*/
|
|
42
|
+
interface SetupAuthContextProviderProps {
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
auth: SetupAuthContext;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Simple provider that takes auth state and provides it via context.
|
|
48
|
+
* Use this when you already have the auth state and just need to provide it to children.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* const auth = useSetupAuth();
|
|
53
|
+
* return (
|
|
54
|
+
* <SetupAuthContextProvider auth={auth}>
|
|
55
|
+
* <MyComponent />
|
|
56
|
+
* </SetupAuthContextProvider>
|
|
57
|
+
* );
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function SetupAuthContextProvider({ children, auth, }: SetupAuthContextProviderProps): react_jsx_runtime.JSX.Element;
|
|
61
|
+
|
|
62
|
+
type UserMetadataRow = Database["core"]["Tables"]["UserMetadata"]["Row"];
|
|
63
|
+
type UserMetadataInsert = Database["core"]["Tables"]["UserMetadata"]["Insert"];
|
|
64
|
+
type UserMetadataUpdate = Database["core"]["Tables"]["UserMetadata"]["Update"];
|
|
65
|
+
interface UserMetadataContextType {
|
|
66
|
+
metadata: Record<string, string>;
|
|
67
|
+
isLoading: boolean;
|
|
68
|
+
error: Error | null;
|
|
69
|
+
setMetadata: (key: string, value: string) => Promise<void>;
|
|
70
|
+
getMetadata: (key: string) => string | undefined;
|
|
71
|
+
removeMetadata: (key: string) => Promise<void>;
|
|
72
|
+
refreshMetadata: () => Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
declare const userMetadataContext: react.Context<UserMetadataContextType>;
|
|
75
|
+
declare function UserMetadataProvider({ children }: {
|
|
76
|
+
children: ReactNode;
|
|
77
|
+
}): react_jsx_runtime.JSX.Element;
|
|
78
|
+
declare function useUserMetadata(): UserMetadataContextType;
|
|
79
|
+
declare function useUserMetadataValue(key: string): string | undefined;
|
|
80
|
+
declare function useSetUserMetadata(): {
|
|
81
|
+
setMetadata: (key: string, value: string) => Promise<void>;
|
|
82
|
+
removeMetadata: (key: string) => Promise<void>;
|
|
83
|
+
};
|
|
84
|
+
declare function useUserMetadataState<T>(key: string, defaultValue: T, options?: {
|
|
85
|
+
serialize?: (value: T) => string;
|
|
86
|
+
deserialize?: (value: string) => T;
|
|
87
|
+
}): [T, (value: T) => Promise<void>, boolean];
|
|
88
|
+
|
|
89
|
+
export { type ProfileStatus as P, SetupAuthContextProvider as S, type UserMetadataContextType as U, type SetupAuthContext as a, type SetupAuthContextProviderProps as b, type Profile as c, useUserMetadata as d, useUserMetadataState as e, useUserMetadataValue as f, userMetadataContext as g, type UserMetadataInsert as h, UserMetadataProvider as i, type UserMetadataRow as j, type UserMetadataUpdate as k, setupAuthContext as s, useSetUserMetadata as u };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export { c as Profile, P as ProfileStatus, a as SetupAuthContext, S as SetupAuthContextProvider, b as SetupAuthContextProviderProps, U as UserMetadataContextType, h as UserMetadataInsert, i as UserMetadataProvider, j as UserMetadataRow, k as UserMetadataUpdate, s as setupAuthContext, u as useSetUserMetadata, d as useUserMetadata, e as useUserMetadataState, f as useUserMetadataValue, g as userMetadataContext } from '../UserMetadataContext-BYYqA6LI.js';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import { d as EntityType, b as EntityPermissionCheck, a as EntityAction } from '../EntityPermissions-DwFt4tUd.js';
|
|
6
|
+
import '@supabase/supabase-js';
|
|
7
|
+
import '../useSupabase-pPhUZHcl.js';
|
|
8
|
+
import '@supabase/supabase-js/dist/module/lib/types.js';
|
|
9
|
+
|
|
10
|
+
interface AuthProviderProps {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Enable entity-level permissions system (Project, Client, ProjectDatabase access control).
|
|
14
|
+
* When enabled, wraps children with PermissionProvider.
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
enableEntityPermissions?: boolean;
|
|
18
|
+
}
|
|
19
|
+
declare function AuthProvider({ children, enableEntityPermissions, }: AuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
20
|
+
|
|
21
|
+
interface EntityIdentifier {
|
|
22
|
+
entityType: EntityType;
|
|
23
|
+
entityId: number;
|
|
24
|
+
}
|
|
25
|
+
interface PermissionContextValue {
|
|
26
|
+
getPermission: (entityType: EntityType, entityId: number) => EntityPermissionCheck;
|
|
27
|
+
checkPermission: (entityType: EntityType, entityId: number, action: EntityAction) => boolean;
|
|
28
|
+
prefetchPermissions: (entities: EntityIdentifier[]) => Promise<void>;
|
|
29
|
+
invalidatePermission: (entityType: EntityType, entityId: number) => void;
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Use permissionContext instead
|
|
34
|
+
*/
|
|
35
|
+
interface EntityPermissionContextValue extends PermissionContextValue {
|
|
36
|
+
}
|
|
37
|
+
declare const permissionContext: react.Context<PermissionContextValue>;
|
|
38
|
+
/**
|
|
39
|
+
* @deprecated Use permissionContext instead
|
|
40
|
+
*/
|
|
41
|
+
declare const entityPermissionContext: react.Context<PermissionContextValue>;
|
|
42
|
+
declare function PermissionProvider({ children }: {
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
}): react_jsx_runtime.JSX.Element;
|
|
45
|
+
declare function usePermissions(): PermissionContextValue;
|
|
46
|
+
|
|
47
|
+
export { AuthProvider, type AuthProviderProps, type EntityPermissionContextValue, type PermissionContextValue, PermissionProvider, entityPermissionContext, permissionContext, usePermissions };
|