@taruvi/refine-providers 1.0.6 → 1.0.7

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 CHANGED
@@ -20,7 +20,6 @@ import {
20
20
  accessControlProvider,
21
21
  } from "@taruvi/refine-providers";
22
22
 
23
- // Initialize the Taruvi client
24
23
  const client = new Client({
25
24
  apiKey: "your-api-key",
26
25
  appSlug: "your-app-slug",
@@ -44,17 +43,47 @@ function App() {
44
43
  }
45
44
  ```
46
45
 
47
- ## Data Providers
46
+ ---
47
+
48
+ ## Exports
49
+
50
+ ```typescript
51
+ // Data Providers
52
+ import { dataProvider } from "@taruvi/refine-providers"; // Database CRUD
53
+ import { storageDataProvider } from "@taruvi/refine-providers"; // File storage
54
+ import { functionsDataProvider } from "@taruvi/refine-providers"; // Edge functions
55
+ import { appDataProvider } from "@taruvi/refine-providers"; // App data (roles)
56
+ import { analyticsDataProvider } from "@taruvi/refine-providers"; // Analytics queries
57
+
58
+ // Auth Providers
59
+ import { authProvider } from "@taruvi/refine-providers"; // Authentication
60
+ import { accessControlProvider } from "@taruvi/refine-providers"; // Cerbos permissions
61
+
62
+ // Types
63
+ import type {
64
+ TaruviMeta,
65
+ TaruviListResponse,
66
+ TaruviUser,
67
+ StorageUploadVariables,
68
+ FunctionMeta,
69
+ AnalyticsMeta,
70
+ } from "@taruvi/refine-providers";
71
+
72
+ // SDK re-exports
73
+ import { Client, Auth, Policy, Functions, App, Analytics } from "@taruvi/refine-providers";
74
+ ```
75
+
76
+ ---
48
77
 
49
- This package includes multiple specialized data providers:
78
+ ## Data Providers Overview
50
79
 
51
- | Provider | Purpose | SDK Class |
52
- |----------|---------|-----------|
53
- | `dataProvider` | Database CRUD operations | `Database` |
54
- | `storageDataProvider` | File storage operations | `Storage` |
55
- | `functionsDataProvider` | Edge function execution | `Functions` |
56
- | `appDataProvider` | App-level data (roles) | `App` |
57
- | `analyticsDataProvider` | Analytics queries | `Analytics` |
80
+ | Provider | Purpose | Hook | Resource Parameter |
81
+ |----------|---------|------|-------------------|
82
+ | `dataProvider` | Database CRUD | `useList`, `useOne`, `useCreate`, `useUpdate`, `useDelete` | Table name |
83
+ | `storageDataProvider` | File storage | `useList`, `useCreate`, `useDelete` | Bucket name |
84
+ | `functionsDataProvider` | Edge functions | `useCustom` | Function slug |
85
+ | `appDataProvider` | App roles | `useList` | `"roles"` |
86
+ | `analyticsDataProvider` | Analytics queries | `useCustom` | Query slug |
58
87
 
59
88
  ---
60
89
 
@@ -62,130 +91,229 @@ This package includes multiple specialized data providers:
62
91
 
63
92
  The main data provider for CRUD operations on database tables.
64
93
 
65
- ### Basic Usage
94
+ ### Setup
66
95
 
67
- ```tsx
96
+ ```typescript
68
97
  import { dataProvider, Client } from "@taruvi/refine-providers";
69
98
 
70
99
  const client = new Client({ apiKey, appSlug, baseUrl });
71
100
 
72
- <Refine
73
- dataProvider={dataProvider(client)}
74
- resources={[{ name: "posts" }]}
75
- />
101
+ <Refine dataProvider={dataProvider(client)} />
76
102
  ```
77
103
 
78
- ### Supported Operations
104
+ ### Operations
79
105
 
80
- All standard Refine CRUD operations are supported:
106
+ | Method | HTTP | Endpoint |
107
+ |--------|------|----------|
108
+ | `getList` | GET | `/api/apps/{app}/datatables/{table}/data/` |
109
+ | `getOne` | GET | `/api/apps/{app}/datatables/{table}/data/{id}/` |
110
+ | `getMany` | GET | `/api/apps/{app}/datatables/{table}/data/?id__in=1,2,3` |
111
+ | `create` | POST | `/api/apps/{app}/datatables/{table}/data/` |
112
+ | `update` | PATCH | `/api/apps/{app}/datatables/{table}/data/{id}/` |
113
+ | `deleteOne` | DELETE | `/api/apps/{app}/datatables/{table}/data/{id}/` |
81
114
 
82
- ```tsx
83
- // List records
84
- const { data } = useList({ resource: "posts" });
115
+ ### Usage Examples
85
116
 
86
- // Get single record
87
- const { data } = useOne({ resource: "posts", id: 1 });
117
+ #### List Records
88
118
 
89
- // Get multiple records
90
- const { data } = useMany({ resource: "posts", ids: [1, 2, 3] });
119
+ ```typescript
120
+ import { useList } from "@refinedev/core";
91
121
 
92
- // Create record
93
- const { mutate } = useCreate();
94
- mutate({ resource: "posts", values: { title: "Hello" } });
122
+ const { data, isLoading } = useList({
123
+ resource: "users",
124
+ pagination: { currentPage: 1, pageSize: 10 },
125
+ filters: [
126
+ { field: "status", operator: "eq", value: "active" },
127
+ { field: "age", operator: "gte", value: 18 },
128
+ ],
129
+ sorters: [
130
+ { field: "created_at", order: "desc" },
131
+ ],
132
+ meta: {
133
+ populate: ["department", "manager"],
134
+ },
135
+ });
95
136
 
96
- // Update record
97
- const { mutate } = useUpdate();
98
- mutate({ resource: "posts", id: 1, values: { title: "Updated" } });
137
+ // Returns: { data: User[], total: number }
138
+ ```
99
139
 
100
- // Delete record
101
- const { mutate } = useDelete();
102
- mutate({ resource: "posts", id: 1 });
140
+ #### Get Single Record
141
+
142
+ ```typescript
143
+ import { useOne } from "@refinedev/core";
144
+
145
+ const { data } = useOne({
146
+ resource: "users",
147
+ id: 123,
148
+ meta: {
149
+ populate: ["department"],
150
+ },
151
+ });
152
+
153
+ // Returns: { data: User }
103
154
  ```
104
155
 
105
- ### Filtering
156
+ #### Get Multiple Records
106
157
 
107
- Full support for Refine filter operators:
158
+ ```typescript
159
+ import { useMany } from "@refinedev/core";
108
160
 
109
- ```tsx
110
- const { data } = useList({
111
- resource: "posts",
112
- filters: [
113
- { field: "status", operator: "eq", value: "published" },
114
- { field: "views", operator: "gte", value: 100 },
115
- { field: "title", operator: "contains", value: "refine" },
116
- { field: "category", operator: "in", value: ["tech", "news"] },
117
- ],
161
+ const { data } = useMany({
162
+ resource: "users",
163
+ ids: [1, 2, 3],
118
164
  });
165
+
166
+ // Returns: { data: User[] }
119
167
  ```
120
168
 
121
- **Supported Operators:**
169
+ #### Create Record
122
170
 
123
- | Operator | Description | Example |
124
- |----------|-------------|---------|
125
- | `eq` | Equal | `status = "active"` |
126
- | `ne` | Not equal | `status != "deleted"` |
127
- | `lt`, `gt`, `lte`, `gte` | Comparison | `age >= 18` |
128
- | `contains`, `ncontains` | Contains (case-sensitive) | `title contains "hello"` |
129
- | `containss`, `ncontainss` | Contains (case-insensitive) | `title icontains "hello"` |
130
- | `startswith`, `endswith` | String matching | `email endswith "@gmail.com"` |
131
- | `in`, `nin` | Array membership | `status in ["active", "pending"]` |
132
- | `null`, `nnull` | Null checks | `deleted_at is null` |
133
- | `between`, `nbetween` | Range | `price between [10, 100]` |
171
+ ```typescript
172
+ import { useCreate } from "@refinedev/core";
134
173
 
135
- ### Sorting & Pagination
174
+ const { mutate } = useCreate();
136
175
 
137
- ```tsx
138
- const { data } = useList({
139
- resource: "posts",
140
- sorters: [
141
- { field: "created_at", order: "desc" },
142
- { field: "title", order: "asc" },
143
- ],
144
- pagination: {
145
- currentPage: 1,
146
- pageSize: 20,
176
+ mutate({
177
+ resource: "users",
178
+ values: {
179
+ name: "John Doe",
180
+ email: "john@example.com",
147
181
  },
148
182
  });
149
183
  ```
150
184
 
151
- ### Meta Options
185
+ #### Update Record
152
186
 
153
- Use the `meta` parameter for Taruvi-specific features:
187
+ ```typescript
188
+ import { useUpdate } from "@refinedev/core";
154
189
 
155
- ```tsx
156
- const { data } = useList({
190
+ const { mutate } = useUpdate();
191
+
192
+ mutate({
193
+ resource: "users",
194
+ id: 123,
195
+ values: {
196
+ name: "Jane Doe",
197
+ },
198
+ });
199
+ ```
200
+
201
+ #### Delete Record
202
+
203
+ ```typescript
204
+ import { useDelete } from "@refinedev/core";
205
+
206
+ const { mutate } = useDelete();
207
+
208
+ mutate({
209
+ resource: "users",
210
+ id: 123,
211
+ });
212
+ ```
213
+
214
+ ### Meta Options
215
+
216
+ ```typescript
217
+ useList({
157
218
  resource: "posts",
158
219
  meta: {
159
- // Override table name (when resource differs from table)
160
- tableName: "blog_posts",
220
+ tableName: "blog_posts", // Override table name
221
+ populate: ["author", "comments.user"], // FK population (array or string)
222
+ select: ["id", "title", "status"], // Field selection
223
+ idColumnName: "post_id", // Custom ID column
224
+ aggregate: ["sum(views)", "count(*)"], // Aggregations
225
+ groupBy: ["category"], // Group by
226
+ having: [{ field: "sum(views)", operator: "gte", value: 100 }],
227
+ },
228
+ });
229
+ ```
230
+
231
+ ### Filtering
232
+
233
+ All Refine filter operators are supported:
234
+
235
+ | Operator | Query Parameter | Example |
236
+ |----------|-----------------|---------|
237
+ | `eq` | `field=value` | `status=active` |
238
+ | `ne` | `field__ne=value` | `status__ne=deleted` |
239
+ | `lt`, `gt`, `lte`, `gte` | `field__lt=value` | `age__gte=18` |
240
+ | `contains` | `field__contains=value` | `name__contains=john` |
241
+ | `containss` | `field__icontains=value` | `name__icontains=John` (case-insensitive) |
242
+ | `startswith` | `field__startswith=value` | `code__startswith=PRE` |
243
+ | `endswith` | `field__endswith=value` | `email__endswith=@gmail.com` |
244
+ | `in` | `field__in=a,b,c` | `status__in=active,pending` |
245
+ | `nin` | `field__nin=a,b` | `status__nin=deleted` |
246
+ | `null` | `field__null=true` | `deleted_at__null=true` |
247
+ | `nnull` | `field__nnull=true` | `email__nnull=true` |
248
+ | `between` | `field__between=min,max` | `price__between=10,100` |
249
+
250
+ ```typescript
251
+ useList({
252
+ resource: "products",
253
+ filters: [
254
+ { field: "status", operator: "eq", value: "active" },
255
+ { field: "price", operator: "between", value: [10, 100] },
256
+ { field: "category_id", operator: "in", value: [1, 2, 3] },
257
+ { field: "name", operator: "containss", value: "phone" },
258
+ { field: "deleted_at", operator: "null", value: true },
259
+ ],
260
+ });
261
+ ```
262
+
263
+ ### Sorting
161
264
 
162
- // Populate foreign key relations
163
- populate: ["author", "category"],
164
- // or populate all: populate: "*"
265
+ ```typescript
266
+ useList({
267
+ resource: "posts",
268
+ sorters: [
269
+ { field: "created_at", order: "desc" }, // -created_at
270
+ { field: "title", order: "asc" }, // title
271
+ ],
272
+ });
273
+ // Query: ?ordering=-created_at,title
274
+ ```
165
275
 
166
- // Select specific fields
167
- select: ["id", "title", "status"],
276
+ ### Pagination
168
277
 
169
- // Custom ID column
170
- idColumnName: "post_id",
278
+ ```typescript
279
+ useList({
280
+ resource: "users",
281
+ pagination: {
282
+ currentPage: 2,
283
+ pageSize: 25,
171
284
  },
172
285
  });
286
+ // Query: ?page=2&page_size=25
287
+
288
+ // Disable pagination
289
+ useList({
290
+ resource: "users",
291
+ pagination: { mode: "off" },
292
+ });
173
293
  ```
174
294
 
175
- ### Aggregations
295
+ ### Populate (Foreign Key Relations)
176
296
 
177
- Support for aggregate queries with grouping:
297
+ Populate uses the SDK's `.populate()` method:
178
298
 
179
- ```tsx
180
- const { data } = useList({
181
- resource: "orders",
182
- meta: {
183
- aggregate: ["sum(total)", "count(*)", "avg(quantity)"],
184
- groupBy: ["status", "category"],
185
- having: [
186
- { field: "sum(total)", operator: "gte", value: 1000 },
187
- ],
188
- },
299
+ ```typescript
300
+ // Array format
301
+ useList({
302
+ resource: "posts",
303
+ meta: { populate: ["author", "category"] },
304
+ });
305
+
306
+ // Nested relations
307
+ useList({
308
+ resource: "posts",
309
+ meta: { populate: ["author", "comments.user"] },
310
+ });
311
+
312
+ // String format
313
+ useOne({
314
+ resource: "posts",
315
+ id: 1,
316
+ meta: { populate: "author,comments.user" },
189
317
  });
190
318
  ```
191
319
 
@@ -197,10 +325,8 @@ For file upload, download, and management operations.
197
325
 
198
326
  ### Setup
199
327
 
200
- ```tsx
201
- import { storageDataProvider, Client } from "@taruvi/refine-providers";
202
-
203
- const client = new Client({ apiKey, appSlug, baseUrl });
328
+ ```typescript
329
+ import { storageDataProvider } from "@taruvi/refine-providers";
204
330
 
205
331
  <Refine
206
332
  dataProvider={{
@@ -210,24 +336,30 @@ const client = new Client({ apiKey, appSlug, baseUrl });
210
336
  />
211
337
  ```
212
338
 
339
+ **Note:** In storage operations, `resource` = bucket name, `id` = file path.
340
+
213
341
  ### List Files
214
342
 
215
- ```tsx
343
+ ```typescript
216
344
  const { data } = useList({
217
- resource: "documents", // bucket name
345
+ resource: "documents", // bucket name
218
346
  dataProviderName: "storage",
347
+ filters: [
348
+ { field: "mimetype_category", operator: "eq", value: "image" },
349
+ { field: "size", operator: "lte", value: 5242880 }, // 5MB
350
+ ],
219
351
  });
220
352
  ```
221
353
 
222
354
  ### Upload Files
223
355
 
224
- ```tsx
356
+ ```typescript
225
357
  import { useCreate } from "@refinedev/core";
226
358
  import type { StorageUploadVariables } from "@taruvi/refine-providers";
227
359
 
228
360
  const { mutate } = useCreate<any, any, StorageUploadVariables>();
229
361
 
230
- // Single file upload
362
+ // Single file
231
363
  mutate({
232
364
  resource: "documents",
233
365
  dataProviderName: "storage",
@@ -250,33 +382,38 @@ mutate({
250
382
  });
251
383
  ```
252
384
 
385
+ ### Download/Get File
386
+
387
+ ```typescript
388
+ const { data } = useOne({
389
+ resource: "documents",
390
+ dataProviderName: "storage",
391
+ id: "folder/myfile.pdf", // file path
392
+ });
393
+ ```
394
+
253
395
  ### Delete Files
254
396
 
255
- ```tsx
397
+ ```typescript
398
+ import { useDeleteMany } from "@refinedev/core";
399
+
256
400
  const { mutate } = useDeleteMany();
257
401
 
258
402
  mutate({
259
403
  resource: "documents",
260
404
  dataProviderName: "storage",
261
- ids: ["path/to/file1.pdf", "path/to/file2.pdf"],
405
+ ids: ["file1.pdf", "folder/file2.pdf"],
262
406
  });
263
407
  ```
264
408
 
265
- ### Filter Files
409
+ ### StorageUploadVariables Interface
266
410
 
267
- ```tsx
268
- const { data } = useList({
269
- resource: "documents",
270
- dataProviderName: "storage",
271
- filters: [
272
- { field: "mimetype_category", operator: "eq", value: "image" },
273
- { field: "size", operator: "lte", value: 5242880 }, // 5MB
274
- { field: "visibility", operator: "eq", value: "public" },
275
- ],
276
- meta: {
277
- bucketName: "uploads", // Override bucket name
278
- },
279
- });
411
+ ```typescript
412
+ interface StorageUploadVariables {
413
+ files: File[]; // Required: File objects
414
+ paths?: string[]; // Optional: Custom paths (defaults to file.name)
415
+ metadatas?: Record<string, unknown>[]; // Optional: Metadata for each file
416
+ }
280
417
  ```
281
418
 
282
419
  ---
@@ -287,8 +424,8 @@ For executing Taruvi edge functions.
287
424
 
288
425
  ### Setup
289
426
 
290
- ```tsx
291
- import { functionsDataProvider, Client } from "@taruvi/refine-providers";
427
+ ```typescript
428
+ import { functionsDataProvider } from "@taruvi/refine-providers";
292
429
 
293
430
  <Refine
294
431
  dataProvider={{
@@ -300,23 +437,77 @@ import { functionsDataProvider, Client } from "@taruvi/refine-providers";
300
437
 
301
438
  ### Execute Function
302
439
 
303
- ```tsx
440
+ Use `useCustom` with the function slug as the URL:
441
+
442
+ ```typescript
304
443
  import { useCustom } from "@refinedev/core";
305
444
 
306
- const { data } = useCustom({
445
+ // Query style (immediate execution)
446
+ const { data, isLoading } = useCustom({
307
447
  dataProviderName: "functions",
308
- url: "my-function-slug",
448
+ url: "process-order", // function slug
309
449
  method: "post",
310
450
  config: {
311
451
  payload: {
312
- param1: "value1",
313
- param2: 123,
452
+ orderId: 123,
453
+ action: "confirm",
314
454
  },
315
455
  },
316
456
  meta: {
317
- async: false, // Set to true for async execution
457
+ async: false, // Set to true for async execution
318
458
  },
319
459
  });
460
+
461
+ if (isLoading) {
462
+ console.log("Executing function...");
463
+ }
464
+ ```
465
+
466
+ ### Mutation Style
467
+
468
+ ```typescript
469
+ import { useCustomMutation } from "@refinedev/core";
470
+
471
+ const { mutate, isLoading } = useCustomMutation();
472
+
473
+ mutate({
474
+ dataProviderName: "functions",
475
+ url: "send-notification",
476
+ method: "post",
477
+ values: { userId: 456, message: "Hello" },
478
+ });
479
+ ```
480
+
481
+ ### With Callbacks
482
+
483
+ ```typescript
484
+ mutate(
485
+ {
486
+ dataProviderName: "functions",
487
+ url: "send-notification",
488
+ method: "post",
489
+ values: { userId: 456, message: "Hello" },
490
+ },
491
+ {
492
+ onSuccess: (data) => console.log("Result:", data),
493
+ onError: (error) => console.error("Failed:", error),
494
+ }
495
+ );
496
+ ```
497
+
498
+ ### Async Execution
499
+
500
+ ```typescript
501
+ // Long-running task - returns immediately with job ID
502
+ const { data } = useCustom({
503
+ dataProviderName: "functions",
504
+ url: "long-running-task",
505
+ method: "post",
506
+ config: {
507
+ payload: { taskId: 789 },
508
+ },
509
+ meta: { async: true },
510
+ });
320
511
  ```
321
512
 
322
513
  ---
@@ -327,8 +518,8 @@ For fetching app-level data like roles.
327
518
 
328
519
  ### Setup
329
520
 
330
- ```tsx
331
- import { appDataProvider, Client } from "@taruvi/refine-providers";
521
+ ```typescript
522
+ import { appDataProvider } from "@taruvi/refine-providers";
332
523
 
333
524
  <Refine
334
525
  dataProvider={{
@@ -340,10 +531,12 @@ import { appDataProvider, Client } from "@taruvi/refine-providers";
340
531
 
341
532
  ### Fetch Roles
342
533
 
343
- ```tsx
534
+ ```typescript
535
+ import { useList } from "@refinedev/core";
536
+
344
537
  const { data } = useList({
345
- resource: "roles",
346
538
  dataProviderName: "app",
539
+ resource: "roles",
347
540
  });
348
541
 
349
542
  // Returns: { data: [{ id, name, permissions, ... }], total: number }
@@ -357,8 +550,8 @@ For executing predefined analytics queries.
357
550
 
358
551
  ### Setup
359
552
 
360
- ```tsx
361
- import { analyticsDataProvider, Client } from "@taruvi/refine-providers";
553
+ ```typescript
554
+ import { analyticsDataProvider } from "@taruvi/refine-providers";
362
555
 
363
556
  <Refine
364
557
  dataProvider={{
@@ -368,14 +561,17 @@ import { analyticsDataProvider, Client } from "@taruvi/refine-providers";
368
561
  />
369
562
  ```
370
563
 
371
- ### Execute Analytics Query
564
+ ### Execute Query
372
565
 
373
- ```tsx
566
+ Use `useCustom` with the query slug as the URL:
567
+
568
+ ```typescript
374
569
  import { useCustom } from "@refinedev/core";
375
570
 
376
- const { data } = useCustom({
571
+ // Query style (immediate execution)
572
+ const { data, isLoading } = useCustom({
377
573
  dataProviderName: "analytics",
378
- url: "monthly-sales-report", // query slug
574
+ url: "monthly-sales-report", // query slug
379
575
  method: "post",
380
576
  config: {
381
577
  payload: {
@@ -385,6 +581,42 @@ const { data } = useCustom({
385
581
  },
386
582
  },
387
583
  });
584
+
585
+ if (isLoading) {
586
+ console.log("Running query...");
587
+ }
588
+ ```
589
+
590
+ ### Mutation Style
591
+
592
+ ```typescript
593
+ import { useCustomMutation } from "@refinedev/core";
594
+
595
+ const { mutate, isLoading } = useCustomMutation();
596
+
597
+ mutate({
598
+ dataProviderName: "analytics",
599
+ url: "dashboard-metrics",
600
+ method: "post",
601
+ values: { period: "last_30_days" },
602
+ });
603
+ ```
604
+
605
+ ### With Callbacks
606
+
607
+ ```typescript
608
+ mutate(
609
+ {
610
+ dataProviderName: "analytics",
611
+ url: "dashboard-metrics",
612
+ method: "post",
613
+ values: { period: "last_30_days" },
614
+ },
615
+ {
616
+ onSuccess: (data) => console.log("Result:", data),
617
+ onError: (error) => console.error("Failed:", error),
618
+ }
619
+ );
388
620
  ```
389
621
 
390
622
  ---
@@ -395,19 +627,15 @@ Redirect-based authentication using Taruvi's Web UI Flow.
395
627
 
396
628
  ### Setup
397
629
 
398
- ```tsx
399
- import { authProvider, Client } from "@taruvi/refine-providers";
400
-
401
- const client = new Client({ apiKey, appSlug, baseUrl });
630
+ ```typescript
631
+ import { authProvider } from "@taruvi/refine-providers";
402
632
 
403
- <Refine
404
- authProvider={authProvider(client)}
405
- />
633
+ <Refine authProvider={authProvider(client)} />
406
634
  ```
407
635
 
408
636
  ### Login
409
637
 
410
- ```tsx
638
+ ```typescript
411
639
  import { useLogin } from "@refinedev/core";
412
640
 
413
641
  const { mutate: login } = useLogin();
@@ -418,7 +646,7 @@ login({ callbackUrl: "/dashboard" });
418
646
 
419
647
  ### Logout
420
648
 
421
- ```tsx
649
+ ```typescript
422
650
  import { useLogout } from "@refinedev/core";
423
651
 
424
652
  const { mutate: logout } = useLogout();
@@ -426,9 +654,9 @@ const { mutate: logout } = useLogout();
426
654
  logout({ callbackUrl: "/login" });
427
655
  ```
428
656
 
429
- ### Register/Signup
657
+ ### Register
430
658
 
431
- ```tsx
659
+ ```typescript
432
660
  import { useRegister } from "@refinedev/core";
433
661
 
434
662
  const { mutate: register } = useRegister();
@@ -438,7 +666,7 @@ register({ callbackUrl: "/welcome" });
438
666
 
439
667
  ### Get Current User
440
668
 
441
- ```tsx
669
+ ```typescript
442
670
  import { useGetIdentity } from "@refinedev/core";
443
671
  import type { TaruviUser } from "@taruvi/refine-providers";
444
672
 
@@ -448,9 +676,21 @@ console.log(user?.username);
448
676
  console.log(user?.email);
449
677
  ```
450
678
 
451
- ### Check Permissions
679
+ ### Check Authentication
452
680
 
453
- ```tsx
681
+ ```typescript
682
+ import { useIsAuthenticated } from "@refinedev/core";
683
+
684
+ const { data } = useIsAuthenticated();
685
+
686
+ if (data?.authenticated) {
687
+ // User is logged in
688
+ }
689
+ ```
690
+
691
+ ### Get Permissions
692
+
693
+ ```typescript
454
694
  import { usePermissions } from "@refinedev/core";
455
695
 
456
696
  const { data: permissions } = usePermissions();
@@ -459,6 +699,19 @@ console.log(permissions?.roles);
459
699
  console.log(permissions?.is_staff);
460
700
  ```
461
701
 
702
+ ### TaruviUser Interface
703
+
704
+ ```typescript
705
+ interface TaruviUser {
706
+ user_id: number;
707
+ username: string;
708
+ email?: string;
709
+ exp?: number; // Token expiration
710
+ iat?: number; // Token issued at
711
+ [key: string]: unknown;
712
+ }
713
+ ```
714
+
462
715
  ---
463
716
 
464
717
  ## Access Control Provider
@@ -467,8 +720,8 @@ Resource-based authorization using Cerbos policies.
467
720
 
468
721
  ### Setup
469
722
 
470
- ```tsx
471
- import { accessControlProvider, Client } from "@taruvi/refine-providers";
723
+ ```typescript
724
+ import { accessControlProvider } from "@taruvi/refine-providers";
472
725
 
473
726
  <Refine
474
727
  authProvider={authProvider(client)}
@@ -478,7 +731,7 @@ import { accessControlProvider, Client } from "@taruvi/refine-providers";
478
731
 
479
732
  ### Check Permissions
480
733
 
481
- ```tsx
734
+ ```typescript
482
735
  import { useCan } from "@refinedev/core";
483
736
 
484
737
  const { data } = useCan({
@@ -500,6 +753,15 @@ import { CanAccess } from "@refinedev/core";
500
753
  <CanAccess resource="posts" action="delete" params={{ id: 1 }}>
501
754
  <DeleteButton />
502
755
  </CanAccess>
756
+
757
+ // With fallback
758
+ <CanAccess
759
+ resource="admin"
760
+ action="view"
761
+ fallback={<p>Access denied</p>}
762
+ >
763
+ <AdminPanel />
764
+ </CanAccess>
503
765
  ```
504
766
 
505
767
  ### Define Entity Type
@@ -512,7 +774,7 @@ For Cerbos, specify the entity type in resource meta:
512
774
  {
513
775
  name: "posts",
514
776
  meta: {
515
- entityType: "blog", // Used in Cerbos policy
777
+ entityType: "blog", // Used in Cerbos policy
516
778
  },
517
779
  },
518
780
  ]}
@@ -523,7 +785,7 @@ For Cerbos, specify the entity type in resource meta:
523
785
 
524
786
  ## Multiple Data Providers
525
787
 
526
- Use multiple providers together:
788
+ Use all providers together:
527
789
 
528
790
  ```tsx
529
791
  import {
@@ -533,6 +795,8 @@ import {
533
795
  functionsDataProvider,
534
796
  appDataProvider,
535
797
  analyticsDataProvider,
798
+ authProvider,
799
+ accessControlProvider,
536
800
  } from "@taruvi/refine-providers";
537
801
 
538
802
  const client = new Client({ apiKey, appSlug, baseUrl });
@@ -545,27 +809,42 @@ const client = new Client({ apiKey, appSlug, baseUrl });
545
809
  app: appDataProvider(client),
546
810
  analytics: analyticsDataProvider(client),
547
811
  }}
812
+ authProvider={authProvider(client)}
813
+ accessControlProvider={accessControlProvider(client)}
548
814
  />
549
815
 
550
- // Then specify which provider to use:
551
- useList({ resource: "posts" }); // Uses default
552
- useList({ resource: "images", dataProviderName: "storage" });
553
- useCustom({ url: "process", dataProviderName: "functions", method: "post" });
816
+ // Usage:
817
+ useList({ resource: "posts" }); // default
818
+ useList({ resource: "images", dataProviderName: "storage" }); // storage
819
+ useList({ resource: "roles", dataProviderName: "app" }); // app
820
+
821
+ // Functions and Analytics use useCustom
822
+ const { data: funcResult } = useCustom({
823
+ dataProviderName: "functions",
824
+ url: "my-func",
825
+ method: "post",
826
+ config: { payload: { key: "value" } },
827
+ });
828
+
829
+ const { data: analyticsResult } = useCustom({
830
+ dataProviderName: "analytics",
831
+ url: "my-query",
832
+ method: "post",
833
+ config: { payload: { period: "last_30_days" } },
834
+ });
554
835
  ```
555
836
 
556
837
  ---
557
838
 
558
839
  ## TypeScript Types
559
840
 
560
- All types are exported for TypeScript users:
561
-
562
- ```tsx
841
+ ```typescript
563
842
  import type {
564
843
  // Meta types
565
844
  TaruviMeta,
566
845
  TaruviListResponse,
567
- AnalyticsMeta,
568
846
  FunctionMeta,
847
+ AnalyticsMeta,
569
848
  StorageUploadVariables,
570
849
 
571
850
  // Auth types
@@ -582,13 +861,26 @@ import type {
582
861
  } from "@taruvi/refine-providers";
583
862
  ```
584
863
 
864
+ ### TaruviMeta Interface
865
+
866
+ ```typescript
867
+ interface TaruviMeta {
868
+ tableName?: string; // Override table name
869
+ bucketName?: string; // Override bucket name
870
+ populate?: string | string[]; // FK population
871
+ select?: string | string[]; // Field selection
872
+ idColumnName?: string; // Custom ID column
873
+ aggregate?: string[]; // Aggregation expressions
874
+ groupBy?: string[]; // Group by fields
875
+ having?: CrudFilter[]; // Having clause
876
+ }
877
+ ```
878
+
585
879
  ---
586
880
 
587
881
  ## SDK Re-exports
588
882
 
589
- For convenience, SDK classes are re-exported:
590
-
591
- ```tsx
883
+ ```typescript
592
884
  import {
593
885
  Client,
594
886
  Auth,
@@ -607,9 +899,7 @@ const isLoggedIn = auth.isUserAuthenticated();
607
899
 
608
900
  ## Utility Functions
609
901
 
610
- Advanced users can access utility functions:
611
-
612
- ```tsx
902
+ ```typescript
613
903
  import {
614
904
  REFINE_OPERATOR_MAP,
615
905
  convertRefineFilters,
@@ -619,6 +909,70 @@ import {
619
909
  buildQueryString,
620
910
  handleError,
621
911
  } from "@taruvi/refine-providers";
912
+
913
+ // Convert filters to query params
914
+ const params = convertRefineFilters([
915
+ { field: "status", operator: "eq", value: "active" },
916
+ ]);
917
+ // Result: { status: "active" }
918
+
919
+ // Convert sorters
920
+ const ordering = convertRefineSorters([
921
+ { field: "created_at", order: "desc" },
922
+ ]);
923
+ // Result: "-created_at"
924
+ ```
925
+
926
+ ---
927
+
928
+ ## Error Handling
929
+
930
+ ```typescript
931
+ const { data, error, isError } = useList({ resource: "users" });
932
+
933
+ if (isError) {
934
+ console.error(error.message);
935
+ }
936
+ ```
937
+
938
+ Auth errors are handled by `authProvider.onError`:
939
+ - **401**: Attempts token refresh, then redirects to login
940
+ - **403**: Returns error (user authenticated but not authorized)
941
+
942
+ ---
943
+
944
+ ## Architecture
945
+
946
+ ```
947
+ ┌─────────────────────────────────────────────────────────────┐
948
+ │ React Application │
949
+ │ (using Refine hooks/components) │
950
+ └─────────────────────────────────────────────────────────────┘
951
+
952
+
953
+ ┌─────────────────────────────────────────────────────────────┐
954
+ │ @refinedev/core │
955
+ │ (useList, useCreate, useLogin, CanAccess, etc.) │
956
+ └─────────────────────────────────────────────────────────────┘
957
+
958
+
959
+ ┌─────────────────────────────────────────────────────────────┐
960
+ │ @taruvi/refine-providers │
961
+ │ Data: dataProvider, storageDataProvider, functionsData- │
962
+ │ Provider, appDataProvider, analyticsDataProvider │
963
+ │ Auth: authProvider, accessControlProvider │
964
+ └─────────────────────────────────────────────────────────────┘
965
+
966
+
967
+ ┌─────────────────────────────────────────────────────────────┐
968
+ │ @taruvi/sdk │
969
+ │ Database, Storage, Functions, App, Analytics, Auth, Policy │
970
+ └─────────────────────────────────────────────────────────────┘
971
+
972
+
973
+ ┌─────────────────────────────────────────────────────────────┐
974
+ │ Taruvi Backend API │
975
+ └─────────────────────────────────────────────────────────────┘
622
976
  ```
623
977
 
624
978
  ---