@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 +522 -168
- package/dist/index.cjs +210 -181
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -7
- package/dist/index.d.ts +18 -7
- package/dist/index.js +208 -183
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
-
|
|
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
|
-
|
|
78
|
+
## Data Providers Overview
|
|
50
79
|
|
|
51
|
-
| Provider | Purpose |
|
|
52
|
-
|
|
53
|
-
| `dataProvider` | Database CRUD
|
|
54
|
-
| `storageDataProvider` | File storage
|
|
55
|
-
| `functionsDataProvider` | Edge
|
|
56
|
-
| `appDataProvider` | App
|
|
57
|
-
| `analyticsDataProvider` | Analytics queries | `
|
|
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
|
-
###
|
|
94
|
+
### Setup
|
|
66
95
|
|
|
67
|
-
```
|
|
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
|
-
###
|
|
104
|
+
### Operations
|
|
79
105
|
|
|
80
|
-
|
|
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
|
-
|
|
83
|
-
// List records
|
|
84
|
-
const { data } = useList({ resource: "posts" });
|
|
115
|
+
### Usage Examples
|
|
85
116
|
|
|
86
|
-
|
|
87
|
-
const { data } = useOne({ resource: "posts", id: 1 });
|
|
117
|
+
#### List Records
|
|
88
118
|
|
|
89
|
-
|
|
90
|
-
|
|
119
|
+
```typescript
|
|
120
|
+
import { useList } from "@refinedev/core";
|
|
91
121
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
//
|
|
97
|
-
|
|
98
|
-
mutate({ resource: "posts", id: 1, values: { title: "Updated" } });
|
|
137
|
+
// Returns: { data: User[], total: number }
|
|
138
|
+
```
|
|
99
139
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
156
|
+
#### Get Multiple Records
|
|
106
157
|
|
|
107
|
-
|
|
158
|
+
```typescript
|
|
159
|
+
import { useMany } from "@refinedev/core";
|
|
108
160
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
169
|
+
#### Create Record
|
|
122
170
|
|
|
123
|
-
|
|
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
|
-
|
|
174
|
+
const { mutate } = useCreate();
|
|
136
175
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
185
|
+
#### Update Record
|
|
152
186
|
|
|
153
|
-
|
|
187
|
+
```typescript
|
|
188
|
+
import { useUpdate } from "@refinedev/core";
|
|
154
189
|
|
|
155
|
-
|
|
156
|
-
|
|
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
|
|
160
|
-
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
|
|
167
|
-
select: ["id", "title", "status"],
|
|
276
|
+
### Pagination
|
|
168
277
|
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
###
|
|
295
|
+
### Populate (Foreign Key Relations)
|
|
176
296
|
|
|
177
|
-
|
|
297
|
+
Populate uses the SDK's `.populate()` method:
|
|
178
298
|
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
```
|
|
201
|
-
import { storageDataProvider
|
|
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
|
-
```
|
|
343
|
+
```typescript
|
|
216
344
|
const { data } = useList({
|
|
217
|
-
resource: "documents",
|
|
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
|
-
```
|
|
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
|
|
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
|
-
```
|
|
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: ["
|
|
405
|
+
ids: ["file1.pdf", "folder/file2.pdf"],
|
|
262
406
|
});
|
|
263
407
|
```
|
|
264
408
|
|
|
265
|
-
###
|
|
409
|
+
### StorageUploadVariables Interface
|
|
266
410
|
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
```
|
|
291
|
-
import { functionsDataProvider
|
|
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
|
-
|
|
440
|
+
Use `useCustom` with the function slug as the URL:
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
304
443
|
import { useCustom } from "@refinedev/core";
|
|
305
444
|
|
|
306
|
-
|
|
445
|
+
// Query style (immediate execution)
|
|
446
|
+
const { data, isLoading } = useCustom({
|
|
307
447
|
dataProviderName: "functions",
|
|
308
|
-
url: "
|
|
448
|
+
url: "process-order", // function slug
|
|
309
449
|
method: "post",
|
|
310
450
|
config: {
|
|
311
451
|
payload: {
|
|
312
|
-
|
|
313
|
-
|
|
452
|
+
orderId: 123,
|
|
453
|
+
action: "confirm",
|
|
314
454
|
},
|
|
315
455
|
},
|
|
316
456
|
meta: {
|
|
317
|
-
async: false,
|
|
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
|
-
```
|
|
331
|
-
import { appDataProvider
|
|
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
|
-
```
|
|
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
|
-
```
|
|
361
|
-
import { analyticsDataProvider
|
|
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
|
|
564
|
+
### Execute Query
|
|
372
565
|
|
|
373
|
-
|
|
566
|
+
Use `useCustom` with the query slug as the URL:
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
374
569
|
import { useCustom } from "@refinedev/core";
|
|
375
570
|
|
|
376
|
-
|
|
571
|
+
// Query style (immediate execution)
|
|
572
|
+
const { data, isLoading } = useCustom({
|
|
377
573
|
dataProviderName: "analytics",
|
|
378
|
-
url: "monthly-sales-report",
|
|
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
|
-
```
|
|
399
|
-
import { authProvider
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
|
657
|
+
### Register
|
|
430
658
|
|
|
431
|
-
```
|
|
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
|
-
```
|
|
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
|
|
679
|
+
### Check Authentication
|
|
452
680
|
|
|
453
|
-
```
|
|
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
|
-
```
|
|
471
|
-
import { accessControlProvider
|
|
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
|
-
```
|
|
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",
|
|
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
|
|
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
|
-
//
|
|
551
|
-
useList({ resource: "posts" });
|
|
552
|
-
useList({ resource: "images", dataProviderName: "storage" });
|
|
553
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
---
|