@taruvi/refine-providers 1.0.3
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/dist/index.cjs +563 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +165 -0
- package/dist/index.d.ts +165 -0
- package/dist/index.js +540 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
import { Database, Storage, Auth, Policy } from '@taruvi/sdk';
|
|
2
|
+
export { Auth, Client, Policy } from '@taruvi/sdk';
|
|
3
|
+
|
|
4
|
+
// src/dataProvider.ts
|
|
5
|
+
|
|
6
|
+
// src/utils.ts
|
|
7
|
+
var REFINE_OPERATOR_MAP = {
|
|
8
|
+
// Equality
|
|
9
|
+
eq: "",
|
|
10
|
+
// exact match (no suffix)
|
|
11
|
+
ne: "ne",
|
|
12
|
+
// Comparison
|
|
13
|
+
lt: "lt",
|
|
14
|
+
gt: "gt",
|
|
15
|
+
lte: "lte",
|
|
16
|
+
gte: "gte",
|
|
17
|
+
// String operations (case-sensitive)
|
|
18
|
+
contains: "contains",
|
|
19
|
+
ncontains: "ncontains",
|
|
20
|
+
startswith: "startswith",
|
|
21
|
+
nstartswith: "nstartswith",
|
|
22
|
+
endswith: "endswith",
|
|
23
|
+
nendswith: "nendswith",
|
|
24
|
+
// String operations (case-insensitive)
|
|
25
|
+
containss: "icontains",
|
|
26
|
+
ncontainss: "nicontains",
|
|
27
|
+
startswiths: "istartswith",
|
|
28
|
+
nstartswiths: "nistartswith",
|
|
29
|
+
endswiths: "iendswith",
|
|
30
|
+
nendswiths: "niendswith",
|
|
31
|
+
// Array operations
|
|
32
|
+
in: "in",
|
|
33
|
+
nin: "nin",
|
|
34
|
+
// Null checks
|
|
35
|
+
null: "null",
|
|
36
|
+
nnull: "nnull",
|
|
37
|
+
// Range
|
|
38
|
+
between: "between",
|
|
39
|
+
nbetween: "nbetween"
|
|
40
|
+
};
|
|
41
|
+
function convertRefineFilters(filters) {
|
|
42
|
+
if (!filters || filters.length === 0) return {};
|
|
43
|
+
const params = {};
|
|
44
|
+
for (const filter of filters) {
|
|
45
|
+
if ("operator" in filter && (filter.operator === "and" || filter.operator === "or")) {
|
|
46
|
+
if (filter.value && Array.isArray(filter.value)) {
|
|
47
|
+
const nested = convertRefineFilters(filter.value);
|
|
48
|
+
Object.assign(params, nested);
|
|
49
|
+
}
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if ("field" in filter && filter.field && filter.operator) {
|
|
53
|
+
const { field, operator, value } = filter;
|
|
54
|
+
if (value === void 0 || value === null && operator !== "null") {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const suffix = REFINE_OPERATOR_MAP[operator];
|
|
58
|
+
if (suffix === void 0) {
|
|
59
|
+
console.warn(`Unknown Refine operator: ${operator}`);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const paramKey = suffix ? `${field}__${suffix}` : String(field);
|
|
63
|
+
if (operator === "in" || operator === "nin") {
|
|
64
|
+
params[paramKey] = Array.isArray(value) ? value.join(",") : String(value);
|
|
65
|
+
} else if (operator === "between" || operator === "nbetween") {
|
|
66
|
+
params[paramKey] = Array.isArray(value) ? value.join(",") : String(value);
|
|
67
|
+
} else if (operator === "null" || operator === "nnull") {
|
|
68
|
+
params[paramKey] = "true";
|
|
69
|
+
} else {
|
|
70
|
+
params[paramKey] = String(value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return params;
|
|
75
|
+
}
|
|
76
|
+
function convertRefineSorters(sorters) {
|
|
77
|
+
if (!sorters || sorters.length === 0) return void 0;
|
|
78
|
+
return sorters.map((sort) => sort.order === "desc" ? `-${sort.field}` : sort.field).join(",");
|
|
79
|
+
}
|
|
80
|
+
function convertRefinePagination(pagination) {
|
|
81
|
+
if (!pagination) return {};
|
|
82
|
+
const { current, pageSize, mode } = pagination;
|
|
83
|
+
if (mode === "off") return {};
|
|
84
|
+
return {
|
|
85
|
+
page: current,
|
|
86
|
+
page_size: pageSize
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function buildRefineQueryParams(options) {
|
|
90
|
+
const { filters, sorters, pagination, meta } = options;
|
|
91
|
+
const params = {
|
|
92
|
+
...convertRefineFilters(filters),
|
|
93
|
+
...convertRefinePagination(pagination)
|
|
94
|
+
};
|
|
95
|
+
const ordering = convertRefineSorters(sorters);
|
|
96
|
+
if (ordering) {
|
|
97
|
+
params.ordering = ordering;
|
|
98
|
+
}
|
|
99
|
+
if (meta?.populate) {
|
|
100
|
+
params.populate = Array.isArray(meta.populate) ? meta.populate.join(",") : meta.populate;
|
|
101
|
+
}
|
|
102
|
+
return params;
|
|
103
|
+
}
|
|
104
|
+
function buildQueryString(params) {
|
|
105
|
+
if (!params || Object.keys(params).length === 0) return "";
|
|
106
|
+
const searchParams = new URLSearchParams();
|
|
107
|
+
for (const [key, value] of Object.entries(params)) {
|
|
108
|
+
if (value !== void 0 && value !== null) {
|
|
109
|
+
searchParams.append(key, String(value));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const queryString = searchParams.toString();
|
|
113
|
+
return queryString ? `?${queryString}` : "";
|
|
114
|
+
}
|
|
115
|
+
function handleError(error) {
|
|
116
|
+
if (error instanceof Error) {
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
if (typeof error === "object" && error !== null && "message" in error) {
|
|
120
|
+
throw new Error(String(error.message));
|
|
121
|
+
}
|
|
122
|
+
throw new Error("Unknown error occurred");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/dataProvider.ts
|
|
126
|
+
function dataProvider(client) {
|
|
127
|
+
const config = client.getConfig();
|
|
128
|
+
const baseApiUrl = `${config.baseUrl}/api/apps/${config.appSlug}`;
|
|
129
|
+
const getIdColumn = (meta) => meta?.idColumnName ?? "id";
|
|
130
|
+
const getTableName = (resource, meta) => meta?.tableName ?? resource;
|
|
131
|
+
const buildFilters = (params) => {
|
|
132
|
+
const filters = {
|
|
133
|
+
...convertRefineFilters(params.filters),
|
|
134
|
+
...convertRefinePagination(params.pagination)
|
|
135
|
+
};
|
|
136
|
+
const ordering = convertRefineSorters(params.sorters);
|
|
137
|
+
if (ordering) filters.ordering = ordering;
|
|
138
|
+
if (params.meta?.select) {
|
|
139
|
+
filters.fields = Array.isArray(params.meta.select) ? params.meta.select.join(",") : params.meta.select;
|
|
140
|
+
}
|
|
141
|
+
if (params.meta?.populate) {
|
|
142
|
+
filters.populate = Array.isArray(params.meta.populate) ? params.meta.populate.join(",") : params.meta.populate;
|
|
143
|
+
}
|
|
144
|
+
return filters;
|
|
145
|
+
};
|
|
146
|
+
return {
|
|
147
|
+
getList: async (params) => {
|
|
148
|
+
const { resource, pagination, filters, sorters, meta } = params;
|
|
149
|
+
const taruviMeta = meta;
|
|
150
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
151
|
+
const dbFilters = buildFilters({ filters, sorters, pagination, meta: taruviMeta });
|
|
152
|
+
const response = await new Database(client, {}).from(tableName).filter(dbFilters).execute();
|
|
153
|
+
return { data: response.data, total: response.total };
|
|
154
|
+
},
|
|
155
|
+
getOne: async (params) => {
|
|
156
|
+
const { resource, id, meta } = params;
|
|
157
|
+
const taruviMeta = meta;
|
|
158
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
159
|
+
const dbFilters = buildFilters({ meta: taruviMeta });
|
|
160
|
+
const data = await new Database(client, {}).from(tableName).filter(dbFilters).get(String(id)).execute();
|
|
161
|
+
return { data };
|
|
162
|
+
},
|
|
163
|
+
getMany: async (params) => {
|
|
164
|
+
const { resource, ids, meta } = params;
|
|
165
|
+
const taruviMeta = meta;
|
|
166
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
167
|
+
const idColumn = getIdColumn(taruviMeta);
|
|
168
|
+
const dbFilters = buildFilters({
|
|
169
|
+
filters: [{ field: idColumn, operator: "in", value: ids }],
|
|
170
|
+
meta: taruviMeta
|
|
171
|
+
});
|
|
172
|
+
const response = await new Database(client, {}).from(tableName).filter(dbFilters).execute();
|
|
173
|
+
return { data: response.data };
|
|
174
|
+
},
|
|
175
|
+
create: async (params) => {
|
|
176
|
+
const { resource, variables, meta } = params;
|
|
177
|
+
const taruviMeta = meta;
|
|
178
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
179
|
+
const data = await new Database(client, {}).from(tableName).create(variables).execute();
|
|
180
|
+
return { data };
|
|
181
|
+
},
|
|
182
|
+
createMany: async (params) => {
|
|
183
|
+
const { resource, variables, meta } = params;
|
|
184
|
+
const taruviMeta = meta;
|
|
185
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
186
|
+
const data = await Promise.all(
|
|
187
|
+
variables.map(async (vars) => {
|
|
188
|
+
return new Database(client, {}).from(tableName).create(vars).execute();
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
return { data };
|
|
192
|
+
},
|
|
193
|
+
update: async (params) => {
|
|
194
|
+
const { resource, id, variables, meta } = params;
|
|
195
|
+
const taruviMeta = meta;
|
|
196
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
197
|
+
const data = await new Database(client, {}).from(tableName).get(String(id)).update(variables).execute();
|
|
198
|
+
return { data };
|
|
199
|
+
},
|
|
200
|
+
updateMany: async (params) => {
|
|
201
|
+
const { resource, ids, variables, meta } = params;
|
|
202
|
+
const taruviMeta = meta;
|
|
203
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
204
|
+
const data = await Promise.all(
|
|
205
|
+
ids.map(async (id) => {
|
|
206
|
+
return new Database(client, {}).from(tableName).get(String(id)).update(variables).execute();
|
|
207
|
+
})
|
|
208
|
+
);
|
|
209
|
+
return { data };
|
|
210
|
+
},
|
|
211
|
+
deleteOne: async (params) => {
|
|
212
|
+
const { resource, id, meta } = params;
|
|
213
|
+
const taruviMeta = meta;
|
|
214
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
215
|
+
const data = await new Database(client, {}).from(tableName).delete(String(id)).execute();
|
|
216
|
+
return { data };
|
|
217
|
+
},
|
|
218
|
+
deleteMany: async (params) => {
|
|
219
|
+
const { resource, ids, meta } = params;
|
|
220
|
+
const taruviMeta = meta;
|
|
221
|
+
const tableName = getTableName(resource, taruviMeta);
|
|
222
|
+
const data = await Promise.all(
|
|
223
|
+
ids.map(async (id) => {
|
|
224
|
+
return new Database(client, {}).from(tableName).delete(String(id)).execute();
|
|
225
|
+
})
|
|
226
|
+
);
|
|
227
|
+
return { data };
|
|
228
|
+
},
|
|
229
|
+
custom: async (params) => {
|
|
230
|
+
const { url, method, payload } = params;
|
|
231
|
+
const fullUrl = url.startsWith("http") ? url : `${baseApiUrl}${url}`;
|
|
232
|
+
let data;
|
|
233
|
+
switch (method.toLowerCase()) {
|
|
234
|
+
case "get":
|
|
235
|
+
data = await client.httpClient.get(fullUrl);
|
|
236
|
+
break;
|
|
237
|
+
case "post":
|
|
238
|
+
data = await client.httpClient.post(fullUrl, payload);
|
|
239
|
+
break;
|
|
240
|
+
case "put":
|
|
241
|
+
data = await client.httpClient.put(fullUrl, payload);
|
|
242
|
+
break;
|
|
243
|
+
case "delete":
|
|
244
|
+
data = await client.httpClient.delete(fullUrl);
|
|
245
|
+
break;
|
|
246
|
+
default:
|
|
247
|
+
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
248
|
+
}
|
|
249
|
+
return { data };
|
|
250
|
+
},
|
|
251
|
+
getApiUrl: () => baseApiUrl
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function storageDataProvider(client) {
|
|
255
|
+
const config = client.getConfig();
|
|
256
|
+
const baseApiUrl = `${config.baseUrl}/api/apps/${config.appSlug}`;
|
|
257
|
+
const getBucketName = (resource, meta) => meta?.bucketName ?? resource;
|
|
258
|
+
const buildFilters = (params) => {
|
|
259
|
+
const filters = {
|
|
260
|
+
...convertRefineFilters(params.filters),
|
|
261
|
+
...convertRefinePagination(params.pagination)
|
|
262
|
+
};
|
|
263
|
+
const ordering = convertRefineSorters(params.sorters);
|
|
264
|
+
if (ordering) filters.ordering = ordering;
|
|
265
|
+
return filters;
|
|
266
|
+
};
|
|
267
|
+
return {
|
|
268
|
+
getList: async (params) => {
|
|
269
|
+
const { resource, pagination, filters, sorters, meta } = params;
|
|
270
|
+
const taruviMeta = meta;
|
|
271
|
+
const bucket = getBucketName(resource, taruviMeta);
|
|
272
|
+
const storageFilters = buildFilters({ filters, sorters, pagination});
|
|
273
|
+
const response = await new Storage(client, {}).from(bucket).filter(storageFilters).execute();
|
|
274
|
+
return { data: response.data, total: response.total };
|
|
275
|
+
},
|
|
276
|
+
getOne: async (params) => {
|
|
277
|
+
const { resource, id: path, meta } = params;
|
|
278
|
+
const taruviMeta = meta;
|
|
279
|
+
const bucket = getBucketName(resource, taruviMeta);
|
|
280
|
+
const data = await new Storage(client, {}).from(bucket).download(String(path)).execute();
|
|
281
|
+
return { data };
|
|
282
|
+
},
|
|
283
|
+
create: async (params) => {
|
|
284
|
+
const { resource, variables, meta } = params;
|
|
285
|
+
const taruviMeta = meta;
|
|
286
|
+
const bucket = getBucketName(resource, taruviMeta);
|
|
287
|
+
const { files, paths = [], metadatas = [] } = variables;
|
|
288
|
+
const filePaths = files.map((file, i) => paths[i] || file.name);
|
|
289
|
+
const fileMetadatas = files.map((_, i) => metadatas[i] || {});
|
|
290
|
+
const data = await new Storage(client, {}).from(bucket).upload({ files, paths: filePaths, metadatas: fileMetadatas }).execute();
|
|
291
|
+
return { data };
|
|
292
|
+
},
|
|
293
|
+
update: async (params) => {
|
|
294
|
+
const { resource, id: path, variables, meta } = params;
|
|
295
|
+
const taruviMeta = meta;
|
|
296
|
+
const bucket = getBucketName(resource, taruviMeta);
|
|
297
|
+
const data = await new Storage(client, {}).from(bucket).update(String(path), variables).execute();
|
|
298
|
+
return { data };
|
|
299
|
+
},
|
|
300
|
+
deleteOne: async (params) => {
|
|
301
|
+
const { resource, id: path, meta } = params;
|
|
302
|
+
const taruviMeta = meta;
|
|
303
|
+
const bucket = getBucketName(resource, taruviMeta);
|
|
304
|
+
const data = await new Storage(client, {}).from(bucket).delete([String(path)]).execute();
|
|
305
|
+
return { data };
|
|
306
|
+
},
|
|
307
|
+
getApiUrl: () => baseApiUrl,
|
|
308
|
+
// Not applicable for storage - return empty array
|
|
309
|
+
getMany: async () => ({ data: [] }),
|
|
310
|
+
createMany: async (params) => {
|
|
311
|
+
const { resource, variables, meta } = params;
|
|
312
|
+
const taruviMeta = meta;
|
|
313
|
+
const bucket = getBucketName(resource, taruviMeta);
|
|
314
|
+
const { files, paths = [], metadatas = [] } = variables;
|
|
315
|
+
const filePaths = files.map((file, i) => paths[i] || file.name);
|
|
316
|
+
const fileMetadatas = files.map((_, i) => metadatas[i] || {});
|
|
317
|
+
const data = await new Storage(client, {}).from(bucket).upload({ files, paths: filePaths, metadatas: fileMetadatas }).execute();
|
|
318
|
+
return { data };
|
|
319
|
+
},
|
|
320
|
+
deleteMany: async (params) => {
|
|
321
|
+
const { resource, ids, meta } = params;
|
|
322
|
+
const taruviMeta = meta;
|
|
323
|
+
const bucket = getBucketName(resource, taruviMeta);
|
|
324
|
+
const data = await new Storage(client, {}).from(bucket).delete(ids.map(String)).execute();
|
|
325
|
+
return { data: [data] };
|
|
326
|
+
},
|
|
327
|
+
custom: async (params) => {
|
|
328
|
+
const { url, method, payload } = params;
|
|
329
|
+
const fullUrl = url.startsWith("http") ? url : `${baseApiUrl}${url}`;
|
|
330
|
+
let data;
|
|
331
|
+
switch (method.toLowerCase()) {
|
|
332
|
+
case "get":
|
|
333
|
+
data = await client.httpClient.get(fullUrl);
|
|
334
|
+
break;
|
|
335
|
+
case "post":
|
|
336
|
+
data = await client.httpClient.post(fullUrl, payload);
|
|
337
|
+
break;
|
|
338
|
+
case "put":
|
|
339
|
+
data = await client.httpClient.put(fullUrl, payload);
|
|
340
|
+
break;
|
|
341
|
+
case "delete":
|
|
342
|
+
data = await client.httpClient.delete(fullUrl);
|
|
343
|
+
break;
|
|
344
|
+
default:
|
|
345
|
+
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
346
|
+
}
|
|
347
|
+
return { data };
|
|
348
|
+
},
|
|
349
|
+
// Not applicable for file storage - files are replaced, not updated
|
|
350
|
+
updateMany: void 0
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function authProvider(client) {
|
|
354
|
+
const auth = new Auth(client);
|
|
355
|
+
return {
|
|
356
|
+
login: async (params = {}) => {
|
|
357
|
+
const { callbackUrl, redirect = true } = params;
|
|
358
|
+
if (auth.isUserAuthenticated()) {
|
|
359
|
+
return {
|
|
360
|
+
success: true,
|
|
361
|
+
redirectTo: callbackUrl || "/"
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
if (redirect) {
|
|
365
|
+
auth.login(callbackUrl);
|
|
366
|
+
return {
|
|
367
|
+
success: true
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
success: false,
|
|
372
|
+
error: {
|
|
373
|
+
name: "LoginError",
|
|
374
|
+
message: "Login failed. Please try again."
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
},
|
|
378
|
+
logout: async (params = {}) => {
|
|
379
|
+
const { callbackUrl } = params;
|
|
380
|
+
auth.logout(callbackUrl);
|
|
381
|
+
return {
|
|
382
|
+
success: true,
|
|
383
|
+
redirectTo: callbackUrl || "/login"
|
|
384
|
+
};
|
|
385
|
+
},
|
|
386
|
+
check: async () => {
|
|
387
|
+
if (auth.isUserAuthenticated()) {
|
|
388
|
+
if (auth.isTokenExpired()) {
|
|
389
|
+
const refreshed = await auth.refreshAccessToken();
|
|
390
|
+
if (refreshed) {
|
|
391
|
+
return {
|
|
392
|
+
authenticated: true
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
authenticated: false,
|
|
397
|
+
logout: true,
|
|
398
|
+
redirectTo: "/login",
|
|
399
|
+
error: {
|
|
400
|
+
name: "SessionExpired",
|
|
401
|
+
message: "Your session has expired. Please log in again."
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
authenticated: true
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
authenticated: false,
|
|
411
|
+
redirectTo: "/login"
|
|
412
|
+
};
|
|
413
|
+
},
|
|
414
|
+
//TODO need to check if max retries logic is needed
|
|
415
|
+
onError: async (error) => {
|
|
416
|
+
const status = error?.statusCode || error?.status || error?.response?.status;
|
|
417
|
+
if (status === 401) {
|
|
418
|
+
if (auth.isUserAuthenticated()) {
|
|
419
|
+
const refreshed = await auth.refreshAccessToken();
|
|
420
|
+
if (refreshed) {
|
|
421
|
+
return {
|
|
422
|
+
error
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
logout: true,
|
|
428
|
+
redirectTo: "/login",
|
|
429
|
+
error
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
if (status === 403) {
|
|
433
|
+
return {
|
|
434
|
+
error
|
|
435
|
+
// Don't logout for 403, user is authenticated but not authorized
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
error
|
|
440
|
+
};
|
|
441
|
+
},
|
|
442
|
+
register: async (params = {}) => {
|
|
443
|
+
const { callbackUrl } = params;
|
|
444
|
+
auth.signup(callbackUrl);
|
|
445
|
+
return {
|
|
446
|
+
success: true
|
|
447
|
+
};
|
|
448
|
+
},
|
|
449
|
+
getIdentity: async () => {
|
|
450
|
+
const user = auth.getCurrentUser();
|
|
451
|
+
if (!user) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
return user;
|
|
455
|
+
},
|
|
456
|
+
getPermissions: async () => {
|
|
457
|
+
const user = auth.getCurrentUser();
|
|
458
|
+
if (!user) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
roles: user.roles || [],
|
|
463
|
+
permissions: user.permissions || [],
|
|
464
|
+
groups: user.groups || [],
|
|
465
|
+
is_staff: user.is_staff || false,
|
|
466
|
+
is_superuser: user.is_superuser || false
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function accessControlProvider(client) {
|
|
472
|
+
const policy = new Policy(client);
|
|
473
|
+
const auth = new Auth(client);
|
|
474
|
+
return {
|
|
475
|
+
can: async ({ resource, action, params }) => {
|
|
476
|
+
const user = auth.getCurrentUser();
|
|
477
|
+
if (!user) {
|
|
478
|
+
return {
|
|
479
|
+
can: false,
|
|
480
|
+
reason: "User not authenticated"
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
if (!resource) {
|
|
484
|
+
return {
|
|
485
|
+
can: false,
|
|
486
|
+
reason: "Resource not specified"
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
try {
|
|
490
|
+
const principal = {
|
|
491
|
+
id: String(user.user_id),
|
|
492
|
+
roles: user.roles || [],
|
|
493
|
+
attr: {
|
|
494
|
+
username: user.username,
|
|
495
|
+
email: user.email,
|
|
496
|
+
is_staff: user.is_staff || false,
|
|
497
|
+
is_superuser: user.is_superuser || false,
|
|
498
|
+
groups: user.groups || []
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
const resources = [
|
|
502
|
+
{
|
|
503
|
+
tableName: resource,
|
|
504
|
+
recordId: params?.id ? String(params.id) : "*",
|
|
505
|
+
attributes: params || {},
|
|
506
|
+
actions: [action]
|
|
507
|
+
}
|
|
508
|
+
];
|
|
509
|
+
const result = await policy.checkResource(resources, principal);
|
|
510
|
+
if (result && typeof result === "object") {
|
|
511
|
+
const allowed = result.results?.[0]?.actions?.[action]?.effect === "EFFECT_ALLOW" || result.allowed === true;
|
|
512
|
+
return {
|
|
513
|
+
can: allowed,
|
|
514
|
+
reason: result.reason || (allowed ? void 0 : "Permission denied by policy")
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
return {
|
|
518
|
+
can: false,
|
|
519
|
+
reason: "Invalid policy response"
|
|
520
|
+
};
|
|
521
|
+
} catch (error) {
|
|
522
|
+
console.error("Cerbos permission check failed:", error);
|
|
523
|
+
return {
|
|
524
|
+
can: false,
|
|
525
|
+
reason: error instanceof Error ? error.message : "Permission check failed"
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
options: {
|
|
530
|
+
buttons: {
|
|
531
|
+
enableAccessControl: true,
|
|
532
|
+
hideIfUnauthorized: false
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export { REFINE_OPERATOR_MAP, accessControlProvider, authProvider, buildQueryString, buildRefineQueryParams, convertRefineFilters, convertRefinePagination, convertRefineSorters, dataProvider, handleError, storageDataProvider };
|
|
539
|
+
//# sourceMappingURL=index.js.map
|
|
540
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/dataProvider.ts","../src/storageDataProvider.ts","../src/authProvider.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { CrudFilter, CrudSort, Pagination } from \"@refinedev/core\";\nimport type { TaruviMeta } from \"./types.js\";\n\n/**\n * Maps Refine operators to Taruvi DRF-style query parameter suffixes.\n * Example: { field: \"age\", operator: \"gte\", value: 18 } → \"age__gte=18\"\n */\nexport const REFINE_OPERATOR_MAP: Record<string, string> = {\n // Equality\n eq: \"\", // exact match (no suffix)\n ne: \"ne\",\n\n // Comparison\n lt: \"lt\",\n gt: \"gt\",\n lte: \"lte\",\n gte: \"gte\",\n\n // String operations (case-sensitive)\n contains: \"contains\",\n ncontains: \"ncontains\",\n startswith: \"startswith\",\n nstartswith: \"nstartswith\",\n endswith: \"endswith\",\n nendswith: \"nendswith\",\n\n // String operations (case-insensitive)\n containss: \"icontains\",\n ncontainss: \"nicontains\",\n startswiths: \"istartswith\",\n nstartswiths: \"nistartswith\",\n endswiths: \"iendswith\",\n nendswiths: \"niendswith\",\n\n // Array operations\n in: \"in\",\n nin: \"nin\",\n\n // Null checks\n null: \"null\",\n nnull: \"nnull\",\n\n // Range\n between: \"between\",\n nbetween: \"nbetween\",\n};\n\n/**\n * Converts Refine CrudFilter[] to Taruvi query parameters.\n * Handles both simple filters and logical operators (and/or).\n */\nexport function convertRefineFilters(\n filters?: CrudFilter[]\n): Record<string, string> {\n if (!filters || filters.length === 0) return {};\n\n const params: Record<string, string> = {};\n\n for (const filter of filters) {\n // Handle logical operators (and/or groups)\n if (\n \"operator\" in filter &&\n (filter.operator === \"and\" || filter.operator === \"or\")\n ) {\n // Recursively process nested filters\n // Note: Taruvi API treats multiple params as AND by default\n // OR logic would need special handling if supported by API\n if (filter.value && Array.isArray(filter.value)) {\n const nested = convertRefineFilters(filter.value as CrudFilter[]);\n Object.assign(params, nested);\n }\n continue;\n }\n\n // Handle conditional filters (field, operator, value)\n if (\"field\" in filter && filter.field && filter.operator) {\n const { field, operator, value } = filter;\n\n // Skip undefined/null values (except for null operator)\n if (value === undefined || (value === null && operator !== \"null\")) {\n continue;\n }\n\n const suffix = REFINE_OPERATOR_MAP[operator];\n\n if (suffix === undefined) {\n console.warn(`Unknown Refine operator: ${operator}`);\n continue;\n }\n\n // Build parameter key with double underscore for DRF style\n const paramKey = suffix ? `${field}__${suffix}` : String(field);\n\n // Format value based on operator\n if (operator === \"in\" || operator === \"nin\") {\n // Array values: join with comma\n params[paramKey] = Array.isArray(value) ? value.join(\",\") : String(value);\n } else if (operator === \"between\" || operator === \"nbetween\") {\n // Range values: expect [min, max] array\n params[paramKey] = Array.isArray(value) ? value.join(\",\") : String(value);\n } else if (operator === \"null\" || operator === \"nnull\") {\n // Boolean for null checks\n params[paramKey] = \"true\";\n } else {\n params[paramKey] = String(value);\n }\n }\n }\n\n return params;\n}\n\n/**\n * Converts Refine CrudSort[] to Taruvi ordering parameter.\n * Uses DRF convention: \"-field\" for DESC, \"field\" for ASC.\n */\nexport function convertRefineSorters(sorters?: CrudSort[]): string | undefined {\n if (!sorters || sorters.length === 0) return undefined;\n\n return sorters\n .map((sort) => (sort.order === \"desc\" ? `-${sort.field}` : sort.field))\n .join(\",\");\n}\n\n/**\n * Converts Refine Pagination to Taruvi page/page_size parameters.\n */\nexport function convertRefinePagination(\n pagination?: Pagination\n): { page?: number; page_size?: number } {\n if (!pagination) return {};\n\n const { current, pageSize, mode } = pagination;\n\n // Handle \"off\" mode - no pagination\n if (mode === \"off\") return {};\n\n return {\n page: current,\n page_size: pageSize,\n };\n}\n\n/**\n * Combines all Refine parameters into Taruvi query params.\n */\nexport function buildRefineQueryParams(options: {\n filters?: CrudFilter[];\n sorters?: CrudSort[];\n pagination?: Pagination;\n meta?: TaruviMeta;\n}): Record<string, unknown> {\n const { filters, sorters, pagination, meta } = options;\n\n const params: Record<string, unknown> = {\n ...convertRefineFilters(filters),\n ...convertRefinePagination(pagination),\n };\n\n const ordering = convertRefineSorters(sorters);\n if (ordering) {\n params.ordering = ordering;\n }\n\n // Handle populate from meta\n if (meta?.populate) {\n params.populate = Array.isArray(meta.populate)\n ? meta.populate.join(\",\")\n : meta.populate;\n }\n\n return params;\n}\n\n/**\n * Builds a query string from an object of parameters.\n */\nexport function buildQueryString(params?: Record<string, unknown>): string {\n if (!params || Object.keys(params).length === 0) return \"\";\n\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n }\n\n const queryString = searchParams.toString();\n return queryString ? `?${queryString}` : \"\";\n}\n\n\n/**\n * Handles and transforms Taruvi API errors.\n */\nexport function handleError(error: unknown): never {\n if (error instanceof Error) {\n throw error;\n }\n if (typeof error === \"object\" && error !== null && \"message\" in error) {\n throw new Error(String((error as { message: unknown }).message));\n }\n throw new Error(\"Unknown error occurred\");\n}\n","import type {\n DataProvider,\n BaseRecord,\n GetListParams,\n GetListResponse,\n GetOneParams,\n GetOneResponse,\n GetManyParams,\n GetManyResponse,\n CreateParams,\n CreateResponse,\n CreateManyParams,\n CreateManyResponse,\n UpdateParams,\n UpdateResponse,\n UpdateManyParams,\n UpdateManyResponse,\n DeleteOneParams,\n DeleteOneResponse,\n DeleteManyParams,\n DeleteManyResponse,\n CustomParams,\n CustomResponse,\n} from \"@refinedev/core\";\nimport { Client, Database } from \"@taruvi/sdk\";\nimport type { DatabaseFilters } from \"@taruvi/sdk\";\nimport type { TaruviListResponse, TaruviMeta } from \"./types.js\";\nimport { convertRefineFilters, convertRefineSorters, convertRefinePagination } from \"./utils.js\";\n\n/**\n * Creates a Refine DataProvider for Taruvi database operations.\n */\nexport function dataProvider(client: Client): DataProvider {\n const config = client.getConfig();\n const baseApiUrl = `${config.baseUrl}/api/apps/${config.appSlug}`;\n\n const getIdColumn = (meta?: TaruviMeta) => meta?.idColumnName ?? \"id\";\n const getTableName = (resource: string, meta?: TaruviMeta) => meta?.tableName ?? resource;\n\n const buildFilters = (params: {\n filters?: GetListParams[\"filters\"];\n sorters?: GetListParams[\"sorters\"];\n pagination?: GetListParams[\"pagination\"];\n meta?: TaruviMeta;\n }): DatabaseFilters => {\n const filters: DatabaseFilters = {\n ...convertRefineFilters(params.filters),\n ...convertRefinePagination(params.pagination),\n };\n\n const ordering = convertRefineSorters(params.sorters);\n if (ordering) filters.ordering = ordering;\n\n if (params.meta?.select) {\n (filters as Record<string, unknown>).fields = Array.isArray(params.meta.select)\n ? params.meta.select.join(\",\")\n : params.meta.select;\n }\n\n if (params.meta?.populate) {\n (filters as Record<string, unknown>).populate = Array.isArray(params.meta.populate)\n ? params.meta.populate.join(\",\")\n : params.meta.populate;\n }\n\n return filters;\n };\n\n return {\n getList: async <TData extends BaseRecord = BaseRecord>(\n params: GetListParams\n ): Promise<GetListResponse<TData>> => {\n const { resource, pagination, filters, sorters, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n const dbFilters = buildFilters({ filters, sorters, pagination, meta: taruviMeta });\n\n const response = await new Database(client, {})\n .from(tableName)\n .filter(dbFilters)\n .execute() as TaruviListResponse<TData>;\n\n return { data: response.data, total: response.total };\n },\n\n getOne: async <TData extends BaseRecord = BaseRecord>(\n params: GetOneParams\n ): Promise<GetOneResponse<TData>> => {\n const { resource, id, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n const dbFilters = buildFilters({ meta: taruviMeta });\n\n const data = await new Database(client, {})\n .from(tableName)\n .filter(dbFilters)\n .get(String(id))\n .execute() as TData;\n\n return { data };\n },\n\n getMany: async <TData extends BaseRecord = BaseRecord>(\n params: GetManyParams\n ): Promise<GetManyResponse<TData>> => {\n const { resource, ids, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n const idColumn = getIdColumn(taruviMeta);\n\n const dbFilters = buildFilters({\n filters: [{ field: idColumn, operator: \"in\", value: ids }],\n meta: taruviMeta,\n });\n\n const response = await new Database(client, {})\n .from(tableName)\n .filter(dbFilters)\n .execute() as TaruviListResponse<TData>;\n\n return { data: response.data };\n },\n\n create: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: CreateParams<TVariables>\n ): Promise<CreateResponse<TData>> => {\n const { resource, variables, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n\n // POST /api/apps/{appSlug}/datatables/{tableName}/data/\n const data = await new Database(client, {})\n .from(tableName)\n .create(variables as object)\n .execute() as TData;\n\n return { data };\n },\n\n createMany: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: CreateManyParams<TVariables>\n ): Promise<CreateManyResponse<TData>> => {\n const { resource, variables, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n\n // SDK doesn't have batch create - create records individually\n const data = await Promise.all(\n variables.map(async (vars) => {\n return new Database(client, {})\n .from(tableName)\n .create(vars as object)\n .execute() as Promise<TData>;\n })\n );\n\n return { data };\n },\n\n update: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: UpdateParams<TVariables>\n ): Promise<UpdateResponse<TData>> => {\n const { resource, id, variables, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n\n // SDK update() uses POST - chain with get(id) to update specific record\n // POST /api/apps/{appSlug}/datatables/{tableName}/data/{recordId}/\n const data = await new Database(client, {})\n .from(tableName)\n .get(String(id))\n .update(variables as object)\n .execute() as TData;\n\n return { data };\n },\n\n updateMany: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: UpdateManyParams<TVariables>\n ): Promise<UpdateManyResponse<TData>> => {\n const { resource, ids, variables, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n\n // SDK doesn't have batch update - update records individually\n const data = await Promise.all(\n ids.map(async (id) => {\n return new Database(client, {})\n .from(tableName)\n .get(String(id))\n .update(variables as object)\n .execute() as Promise<TData>;\n })\n );\n\n return { data };\n },\n\n deleteOne: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: DeleteOneParams<TVariables>\n ): Promise<DeleteOneResponse<TData>> => {\n const { resource, id, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n\n const data = await new Database(client, {})\n .from(tableName)\n .delete(String(id))\n .execute() as TData;\n\n return { data };\n },\n\n deleteMany: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: DeleteManyParams<TVariables>\n ): Promise<DeleteManyResponse<TData>> => {\n const { resource, ids, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const tableName = getTableName(resource, taruviMeta);\n\n const data = await Promise.all(\n ids.map(async (id) => {\n return new Database(client, {})\n .from(tableName)\n .delete(String(id))\n .execute() as Promise<TData>;\n })\n );\n\n return { data };\n },\n\n custom: async <TData extends BaseRecord = BaseRecord>(\n params: CustomParams\n ): Promise<CustomResponse<TData>> => {\n const { url, method, payload } = params;\n\n // Use the client's httpClient for custom API calls\n const fullUrl = url.startsWith('http') ? url : `${baseApiUrl}${url}`;\n\n let data: TData;\n switch (method.toLowerCase()) {\n case 'get':\n data = await client.httpClient.get(fullUrl) as TData;\n break;\n case 'post':\n data = await client.httpClient.post(fullUrl, payload) as TData;\n break;\n case 'put':\n data = await client.httpClient.put(fullUrl, payload) as TData;\n break;\n case 'delete':\n data = await client.httpClient.delete(fullUrl) as TData;\n break;\n default:\n throw new Error(`Unsupported HTTP method: ${method}`);\n }\n\n return { data };\n },\n\n getApiUrl: () => baseApiUrl,\n };\n}\n","import type {\n DataProvider,\n BaseRecord,\n GetListParams,\n GetListResponse,\n GetOneParams,\n GetOneResponse,\n GetManyResponse,\n CreateParams,\n CreateResponse,\n UpdateParams,\n UpdateResponse,\n DeleteOneParams,\n DeleteOneResponse,\n DeleteManyParams,\n DeleteManyResponse,\n CustomParams,\n CustomResponse,\n} from \"@refinedev/core\";\nimport { Client, Storage } from \"@taruvi/sdk\";\nimport type { StorageFilters } from \"@taruvi/sdk\";\nimport type { TaruviListResponse, TaruviMeta } from \"./types.js\";\nimport { convertRefineFilters, convertRefineSorters, convertRefinePagination } from \"./utils.js\";\n\n/**\n * Storage upload variables interface.\n */\nexport interface StorageUploadVariables {\n files: File[];\n paths?: string[];\n metadatas?: Record<string, unknown>[];\n}\n\n/**\n * Creates a Refine DataProvider for Taruvi file storage operations.\n */\nexport function storageDataProvider(client: Client): DataProvider {\n const config = client.getConfig();\n const baseApiUrl = `${config.baseUrl}/api/apps/${config.appSlug}`;\n\n const getBucketName = (resource: string, meta?: TaruviMeta) => meta?.bucketName ?? resource;\n\n const buildFilters = (params: {\n filters?: GetListParams[\"filters\"];\n sorters?: GetListParams[\"sorters\"];\n pagination?: GetListParams[\"pagination\"];\n meta?: TaruviMeta;\n }): StorageFilters => {\n const filters: StorageFilters = {\n ...convertRefineFilters(params.filters) as StorageFilters,\n ...convertRefinePagination(params.pagination),\n };\n\n const ordering = convertRefineSorters(params.sorters);\n if (ordering) filters.ordering = ordering;\n\n return filters;\n };\n\n return {\n getList: async <TData extends BaseRecord = BaseRecord>(\n params: GetListParams\n ): Promise<GetListResponse<TData>> => {\n const { resource, pagination, filters, sorters, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const bucket = getBucketName(resource, taruviMeta);\n const storageFilters = buildFilters({ filters, sorters, pagination, meta: taruviMeta });\n\n const response = await new Storage(client, {} as any)\n .from(bucket)\n .filter(storageFilters)\n .execute() as TaruviListResponse<TData>;\n\n return { data: response.data, total: response.total };\n },\n\n getOne: async <TData extends BaseRecord = BaseRecord>(\n params: GetOneParams\n ): Promise<GetOneResponse<TData>> => {\n const { resource, id: path, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const bucket = getBucketName(resource, taruviMeta);\n\n const data = await new Storage(client, {} as any)\n .from(bucket)\n .download(String(path))\n .execute() as TData;\n\n return { data };\n },\n\n create: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: CreateParams<TVariables>\n ): Promise<CreateResponse<TData>> => {\n const { resource, variables, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const bucket = getBucketName(resource, taruviMeta);\n const { files, paths = [], metadatas = [] } = variables as unknown as StorageUploadVariables;\n\n // Use default filenames if paths not provided\n const filePaths = files.map((file, i) => paths[i] || file.name);\n const fileMetadatas = files.map((_, i) => metadatas[i] || {});\n\n const data = await new Storage(client, {} as any)\n .from(bucket)\n .upload({ files, paths: filePaths, metadatas: fileMetadatas })\n .execute() as TData;\n\n return { data };\n },\n\n update: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: UpdateParams<TVariables>\n ): Promise<UpdateResponse<TData>> => {\n const { resource, id: path, variables, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const bucket = getBucketName(resource, taruviMeta);\n\n const data = await new Storage(client, {} as any)\n .from(bucket)\n .update(String(path), variables as object)\n .execute() as TData;\n\n return { data };\n },\n\n deleteOne: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: DeleteOneParams<TVariables>\n ): Promise<DeleteOneResponse<TData>> => {\n const { resource, id: path, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const bucket = getBucketName(resource, taruviMeta);\n\n // SDK delete() now accepts array, handles both single and batch\n const data = await new Storage(client, {} as any)\n .from(bucket)\n .delete([String(path)])\n .execute() as TData;\n\n return { data };\n },\n\n getApiUrl: () => baseApiUrl,\n\n // Not applicable for storage - return empty array\n getMany: async <TData extends BaseRecord = BaseRecord>(): Promise<GetManyResponse<TData>> => ({ data: [] }),\n\n createMany: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: CreateParams<TVariables>\n ): Promise<CreateResponse<TData>> => {\n const { resource, variables, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const bucket = getBucketName(resource, taruviMeta);\n const { files, paths = [], metadatas = [] } = variables as unknown as StorageUploadVariables;\n\n // SDK upload() handles batch upload\n const filePaths = files.map((file, i) => paths[i] || file.name);\n const fileMetadatas = files.map((_, i) => metadatas[i] || {});\n\n const data = await new Storage(client, {} as any)\n .from(bucket)\n .upload({ files, paths: filePaths, metadatas: fileMetadatas })\n .execute() as TData;\n\n return { data };\n },\n\n deleteMany: async <TData extends BaseRecord = BaseRecord, TVariables = {}>(\n params: DeleteManyParams<TVariables>\n ): Promise<DeleteManyResponse<TData>> => {\n const { resource, ids, meta } = params;\n const taruviMeta = meta as TaruviMeta | undefined;\n const bucket = getBucketName(resource, taruviMeta);\n\n // SDK delete() handles batch delete\n const data = await new Storage(client, {} as any)\n .from(bucket)\n .delete(ids.map(String))\n .execute() as TData;\n\n return { data: [data] };\n },\n\n custom: async <TData extends BaseRecord = BaseRecord>(\n params: CustomParams\n ): Promise<CustomResponse<TData>> => {\n const { url, method, payload } = params;\n\n const fullUrl = url.startsWith('http') ? url : `${baseApiUrl}${url}`;\n\n let data: TData;\n switch (method.toLowerCase()) {\n case 'get':\n data = await client.httpClient.get(fullUrl) as TData;\n break;\n case 'post':\n data = await client.httpClient.post(fullUrl, payload) as TData;\n break;\n case 'put':\n data = await client.httpClient.put(fullUrl, payload) as TData;\n break;\n case 'delete':\n data = await client.httpClient.delete(fullUrl) as TData;\n break;\n default:\n throw new Error(`Unsupported HTTP method: ${method}`);\n }\n\n return { data };\n },\n\n // Not applicable for file storage - files are replaced, not updated\n updateMany: undefined,\n };\n}\n","import type { AuthProvider, AccessControlProvider } from \"@refinedev/core\";\nimport { Client, Auth, Policy } from \"@taruvi/sdk\";\n\n/**\n * User identity returned from JWT token\n */\nexport interface TaruviUser {\n user_id: number;\n username: string;\n email?: string;\n exp?: number;\n iat?: number;\n jti?: string;\n token_type?: string;\n [key: string]: unknown;\n}\n\n/**\n * Login params - supports both redirect flow and credentials flow\n */\nexport interface LoginParams {\n /** For redirect-based login - URL to redirect after successful login */\n callbackUrl?: string;\n /** For credentials-based login (if supported) */\n username?: string;\n password?: string;\n /** Whether to use redirect flow (default: true) */\n redirect?: boolean;\n}\n\n/**\n * Logout params\n */\nexport interface LogoutParams {\n /** URL to redirect after logout */\n callbackUrl?: string;\n}\n\n/**\n * Register/Signup params\n */\nexport interface RegisterParams {\n /** URL to redirect after successful signup */\n callbackUrl?: string;\n}\n\n/**\n * Creates a Refine AuthProvider for Taruvi authentication.\n *\n * Supports redirect-based authentication flow (Web UI Flow):\n * 1. User calls login() → Redirects to backend /accounts/login/\n * 2. User authenticates on backend\n * 3. Backend redirects back with tokens in URL hash\n * 4. Client extracts and stores tokens automatically\n */\nexport function authProvider(client: Client): AuthProvider {\n const auth = new Auth(client);\n\n return {\n login: async (params: LoginParams = {}) => {\n const { callbackUrl, redirect = true } = params;\n\n // Check if already authenticated first (prevents infinite redirect loop)\n\n // TODO: check if this is necessary\n if (auth.isUserAuthenticated()) {\n return {\n success: true,\n redirectTo: callbackUrl || \"/\",\n };\n }\n\n if (redirect) {\n // Redirect-based login flow\n auth.login(callbackUrl);\n\n // Return success since we're redirecting\n // The actual auth state will be checked after redirect\n return {\n success: true,\n };\n }\n\n return {\n success: false,\n error: {\n name: \"LoginError\",\n message: \"Login failed. Please try again.\",\n },\n };\n },\n\n logout: async (params: LogoutParams = {}) => {\n const { callbackUrl } = params;\n\n auth.logout(callbackUrl);\n\n return {\n success: true,\n redirectTo: callbackUrl || \"/login\",\n };\n },\n\n check: async () => {\n // Check if user is authenticated\n if (auth.isUserAuthenticated()) {\n // Check if token is expired\n if (auth.isTokenExpired()) {\n // Try to refresh the token\n const refreshed = await auth.refreshAccessToken();\n\n if (refreshed) {\n return {\n authenticated: true,\n };\n }\n\n // Token refresh failed\n return {\n authenticated: false,\n logout: true,\n redirectTo: \"/login\",\n error: {\n name: \"SessionExpired\",\n message: \"Your session has expired. Please log in again.\",\n },\n };\n }\n\n return {\n authenticated: true,\n };\n }\n\n return {\n authenticated: false,\n redirectTo: \"/login\",\n };\n },\n\n //TODO need to check if max retries logic is needed\n onError: async (error) => {\n const status = error?.statusCode || error?.status || error?.response?.status;\n\n // Handle 401 Unauthorized\n if (status === 401) {\n // Try to refresh token first\n if (auth.isUserAuthenticated()) {\n const refreshed = await auth.refreshAccessToken();\n\n if (refreshed) {\n // Token refreshed, retry the request\n return {\n error,\n };\n }\n }\n\n return {\n logout: true,\n redirectTo: \"/login\",\n error,\n };\n }\n\n // Handle 403 Forbidden\n if (status === 403) {\n return {\n error,\n // Don't logout for 403, user is authenticated but not authorized\n };\n }\n\n return {\n error,\n };\n },\n\n register: async (params: RegisterParams = {}) => {\n const { callbackUrl } = params;\n\n // Redirect to signup page\n auth.signup(callbackUrl);\n\n return {\n success: true,\n };\n },\n\n getIdentity: async (): Promise<TaruviUser | null> => {\n const user = auth.getCurrentUser();\n\n if (!user) {\n return null;\n }\n\n return user as TaruviUser;\n },\n\n getPermissions: async () => {\n const user = auth.getCurrentUser();\n\n if (!user) {\n return null;\n }\n\n // Return any permissions from the JWT token\n // Typically stored in claims like 'permissions', 'roles', 'groups', etc.\n return {\n roles: user.roles || [],\n permissions: user.permissions || [],\n groups: user.groups || [],\n is_staff: user.is_staff || false,\n is_superuser: user.is_superuser || false,\n };\n },\n };\n}\n\n/**\n * Creates a Refine AccessControlProvider using Cerbos via the Policy client.\n *\n * This provides resource-based authorization checks using Cerbos policies.\n * Use this with Refine's `useCan` hook or `<CanAccess>` component.\n *\n * @example\n * ```tsx\n * import { Refine } from \"@refinedev/core\";\n * import { Client } from \"@taruvi/sdk\";\n * import { authProvider, accessControlProvider } from \"@taruvi-io/refine\";\n *\n * const client = new Client({ appSlug: \"my-app\", baseUrl: \"...\" });\n *\n * <Refine\n * authProvider={authProvider(client)}\n * accessControlProvider={accessControlProvider(client)}\n * // ...\n * />\n * ```\n */\nexport function accessControlProvider(client: Client): AccessControlProvider {\n const policy = new Policy(client);\n const auth = new Auth(client);\n\n return {\n can: async ({ resource, action, params }) => {\n const user = auth.getCurrentUser();\n\n if (!user) {\n return {\n can: false,\n reason: \"User not authenticated\",\n };\n }\n\n if (!resource) {\n return {\n can: false,\n reason: \"Resource not specified\",\n };\n }\n\n try {\n // Build principal from current user\n const principal = {\n id: String(user.user_id),\n roles: user.roles || [],\n attr: {\n username: user.username,\n email: user.email,\n is_staff: user.is_staff || false,\n is_superuser: user.is_superuser || false,\n groups: user.groups || [],\n },\n };\n\n // Build resource for Cerbos check\n const resources = [\n {\n tableName: resource,\n recordId: params?.id ? String(params.id) : \"*\",\n attributes: (params || {}) as Record<string, unknown>,\n actions: [action],\n },\n ];\n\n const result = await policy.checkResource(resources, principal) as {\n results?: Array<{ actions?: Record<string, { effect?: string }> }>;\n allowed?: boolean;\n reason?: string;\n };\n\n // Parse the Cerbos response\n // The response structure depends on your Cerbos setup\n if (result && typeof result === \"object\") {\n const allowed = result.results?.[0]?.actions?.[action]?.effect === \"EFFECT_ALLOW\"\n || result.allowed === true;\n\n return {\n can: allowed,\n reason: result.reason || (allowed ? undefined : \"Permission denied by policy\"),\n };\n }\n\n return {\n can: false,\n reason: \"Invalid policy response\",\n };\n } catch (error) {\n console.error(\"Cerbos permission check failed:\", error);\n return {\n can: false,\n reason: error instanceof Error ? error.message : \"Permission check failed\",\n };\n }\n },\n\n options: {\n buttons: {\n enableAccessControl: true,\n hideIfUnauthorized: false,\n },\n },\n };\n}\n"]}
|