@harishmano/react-enterprise-api 1.0.0
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.d.mts +280 -0
- package/dist/index.d.ts +280 -0
- package/dist/index.js +696 -0
- package/dist/index.mjs +664 -0
- package/package.json +65 -0
- package/vite.config.ts +9 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
createApiClient: () => createApiClient,
|
|
34
|
+
createResource: () => createResource
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/createApiClient.ts
|
|
39
|
+
var import_axios = __toESM(require("axios"));
|
|
40
|
+
|
|
41
|
+
// src/resource.ts
|
|
42
|
+
var import_react_query = require("@tanstack/react-query");
|
|
43
|
+
|
|
44
|
+
// src/utils.ts
|
|
45
|
+
function buildQueryParams(options, defaultParams) {
|
|
46
|
+
var _a;
|
|
47
|
+
const params = { ...defaultParams };
|
|
48
|
+
if (!options) return params;
|
|
49
|
+
if (options.pagination) {
|
|
50
|
+
const { page, pageSize, sortBy, sortOrder } = options.pagination;
|
|
51
|
+
if (page !== void 0) params.page = page;
|
|
52
|
+
if (pageSize !== void 0) params.pageSize = pageSize;
|
|
53
|
+
if (sortBy) params.sortBy = sortBy;
|
|
54
|
+
if (sortOrder) params.sortOrder = sortOrder;
|
|
55
|
+
}
|
|
56
|
+
if (options.search) {
|
|
57
|
+
params.search = options.search;
|
|
58
|
+
if ((_a = options.searchFields) == null ? void 0 : _a.length) {
|
|
59
|
+
params.searchFields = options.searchFields.join(",");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (options.filters) {
|
|
63
|
+
if (Array.isArray(options.filters)) {
|
|
64
|
+
params.filters = JSON.stringify(options.filters);
|
|
65
|
+
} else {
|
|
66
|
+
Object.assign(params, options.filters);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return params;
|
|
70
|
+
}
|
|
71
|
+
function buildQueryKey(resource, options) {
|
|
72
|
+
const key = [resource];
|
|
73
|
+
if (options == null ? void 0 : options.pagination) key.push({ pagination: options.pagination });
|
|
74
|
+
if (options == null ? void 0 : options.search) key.push({ search: options.search });
|
|
75
|
+
if (options == null ? void 0 : options.filters) key.push({ filters: serializeFilters(options.filters) });
|
|
76
|
+
return key;
|
|
77
|
+
}
|
|
78
|
+
function serializeFilters(filters) {
|
|
79
|
+
if (!filters) return "";
|
|
80
|
+
return JSON.stringify(filters);
|
|
81
|
+
}
|
|
82
|
+
function triggerBrowserDownload(blob, filename, mimeType) {
|
|
83
|
+
const resolvedBlob = mimeType && blob.type !== mimeType ? new Blob([blob], { type: mimeType }) : blob;
|
|
84
|
+
const url = URL.createObjectURL(resolvedBlob);
|
|
85
|
+
const a = document.createElement("a");
|
|
86
|
+
a.href = url;
|
|
87
|
+
a.download = filename;
|
|
88
|
+
document.body.appendChild(a);
|
|
89
|
+
a.click();
|
|
90
|
+
document.body.removeChild(a);
|
|
91
|
+
URL.revokeObjectURL(url);
|
|
92
|
+
}
|
|
93
|
+
function sleep(ms) {
|
|
94
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/resource.ts
|
|
98
|
+
function createResource(client, name, resourceOptions = {}) {
|
|
99
|
+
const {
|
|
100
|
+
path = `/${name}`,
|
|
101
|
+
defaultParams,
|
|
102
|
+
transform,
|
|
103
|
+
staleTime: defaultStaleTime = 1e3 * 60,
|
|
104
|
+
optimistic = false
|
|
105
|
+
} = resourceOptions;
|
|
106
|
+
function applyTransform(data) {
|
|
107
|
+
return transform ? transform(data) : data;
|
|
108
|
+
}
|
|
109
|
+
function useList(options) {
|
|
110
|
+
var _a;
|
|
111
|
+
const params = buildQueryParams(options, defaultParams);
|
|
112
|
+
const queryKey = buildQueryKey(name, options);
|
|
113
|
+
return (0, import_react_query.useQuery)({
|
|
114
|
+
queryKey,
|
|
115
|
+
queryFn: async ({ signal }) => {
|
|
116
|
+
const res = await client.get(path, {
|
|
117
|
+
params,
|
|
118
|
+
signal,
|
|
119
|
+
...options == null ? void 0 : options.axiosConfig
|
|
120
|
+
});
|
|
121
|
+
return applyTransform(res.data);
|
|
122
|
+
},
|
|
123
|
+
staleTime: (_a = options == null ? void 0 : options.staleTime) != null ? _a : defaultStaleTime,
|
|
124
|
+
placeholderData: import_react_query.keepPreviousData,
|
|
125
|
+
enabled: options == null ? void 0 : options.enabled,
|
|
126
|
+
refetchInterval: options == null ? void 0 : options.refetchInterval
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function useGet(id, options) {
|
|
130
|
+
var _a, _b;
|
|
131
|
+
return (0, import_react_query.useQuery)({
|
|
132
|
+
queryKey: [name, id],
|
|
133
|
+
queryFn: async ({ signal }) => {
|
|
134
|
+
const res = await client.get(`${path}/${id}`, {
|
|
135
|
+
params: buildQueryParams(options, defaultParams),
|
|
136
|
+
signal,
|
|
137
|
+
...options == null ? void 0 : options.axiosConfig
|
|
138
|
+
});
|
|
139
|
+
return applyTransform(res.data);
|
|
140
|
+
},
|
|
141
|
+
staleTime: (_a = options == null ? void 0 : options.staleTime) != null ? _a : defaultStaleTime,
|
|
142
|
+
enabled: (_b = options == null ? void 0 : options.enabled) != null ? _b : !!id,
|
|
143
|
+
refetchInterval: options == null ? void 0 : options.refetchInterval
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function usePaginatedList(pagination, options) {
|
|
147
|
+
var _a;
|
|
148
|
+
const mergedOptions = { ...options, pagination };
|
|
149
|
+
const params = buildQueryParams(mergedOptions, defaultParams);
|
|
150
|
+
const queryKey = buildQueryKey(`${name}/paginated`, mergedOptions);
|
|
151
|
+
return (0, import_react_query.useQuery)({
|
|
152
|
+
queryKey,
|
|
153
|
+
queryFn: async ({ signal }) => {
|
|
154
|
+
const res = await client.get(path, {
|
|
155
|
+
params,
|
|
156
|
+
signal,
|
|
157
|
+
...options == null ? void 0 : options.axiosConfig
|
|
158
|
+
});
|
|
159
|
+
return applyTransform(res.data);
|
|
160
|
+
},
|
|
161
|
+
staleTime: (_a = options == null ? void 0 : options.staleTime) != null ? _a : defaultStaleTime,
|
|
162
|
+
placeholderData: import_react_query.keepPreviousData,
|
|
163
|
+
enabled: options == null ? void 0 : options.enabled
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function useInfiniteList(options) {
|
|
167
|
+
var _a;
|
|
168
|
+
const baseParams = buildQueryParams(options, defaultParams);
|
|
169
|
+
return (0, import_react_query.useInfiniteQuery)({
|
|
170
|
+
queryKey: [...buildQueryKey(name, options), "infinite"],
|
|
171
|
+
queryFn: async ({ pageParam = 1, signal }) => {
|
|
172
|
+
var _a2;
|
|
173
|
+
const res = await client.get(path, {
|
|
174
|
+
params: { ...baseParams, page: pageParam, pageSize: (_a2 = options == null ? void 0 : options.pageSize) != null ? _a2 : 20 },
|
|
175
|
+
signal,
|
|
176
|
+
...options == null ? void 0 : options.axiosConfig
|
|
177
|
+
});
|
|
178
|
+
return applyTransform(res.data);
|
|
179
|
+
},
|
|
180
|
+
initialPageParam: 1,
|
|
181
|
+
getNextPageParam: (lastPage, allPages) => Array.isArray(lastPage) && lastPage.length > 0 ? allPages.length + 1 : void 0,
|
|
182
|
+
staleTime: (_a = options == null ? void 0 : options.staleTime) != null ? _a : defaultStaleTime,
|
|
183
|
+
enabled: options == null ? void 0 : options.enabled
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function useCursorList(pagination, options) {
|
|
187
|
+
var _a;
|
|
188
|
+
const baseParams = buildQueryParams(options, defaultParams);
|
|
189
|
+
return (0, import_react_query.useInfiniteQuery)({
|
|
190
|
+
queryKey: [...buildQueryKey(name, options), "cursor", pagination],
|
|
191
|
+
queryFn: async ({ pageParam, signal }) => {
|
|
192
|
+
var _a2;
|
|
193
|
+
const res = await client.get(path, {
|
|
194
|
+
params: {
|
|
195
|
+
...baseParams,
|
|
196
|
+
cursor: pageParam != null ? pageParam : pagination == null ? void 0 : pagination.cursor,
|
|
197
|
+
pageSize: (_a2 = pagination == null ? void 0 : pagination.pageSize) != null ? _a2 : 20,
|
|
198
|
+
sortBy: pagination == null ? void 0 : pagination.sortBy,
|
|
199
|
+
sortOrder: pagination == null ? void 0 : pagination.sortOrder
|
|
200
|
+
},
|
|
201
|
+
signal,
|
|
202
|
+
...options == null ? void 0 : options.axiosConfig
|
|
203
|
+
});
|
|
204
|
+
return applyTransform(res.data);
|
|
205
|
+
},
|
|
206
|
+
initialPageParam: null,
|
|
207
|
+
getNextPageParam: (lastPage) => lastPage.hasMore ? lastPage.nextCursor : void 0,
|
|
208
|
+
staleTime: (_a = options == null ? void 0 : options.staleTime) != null ? _a : defaultStaleTime,
|
|
209
|
+
enabled: options == null ? void 0 : options.enabled
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
function useCreate(mutationOptions) {
|
|
213
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
214
|
+
return (0, import_react_query.useMutation)({
|
|
215
|
+
mutationFn: async (data) => {
|
|
216
|
+
const res = await client.post(path, data);
|
|
217
|
+
return applyTransform(res.data);
|
|
218
|
+
},
|
|
219
|
+
onMutate: optimistic ? async (newItem) => {
|
|
220
|
+
await qc.cancelQueries({ queryKey: [name] });
|
|
221
|
+
const prev = qc.getQueryData([name]);
|
|
222
|
+
qc.setQueryData([name], (old = []) => [
|
|
223
|
+
...old,
|
|
224
|
+
newItem
|
|
225
|
+
]);
|
|
226
|
+
return { prev };
|
|
227
|
+
} : void 0,
|
|
228
|
+
onError: (error, variables, context) => {
|
|
229
|
+
var _a;
|
|
230
|
+
const ctx = context;
|
|
231
|
+
if (optimistic && (ctx == null ? void 0 : ctx.prev)) qc.setQueryData([name], ctx.prev);
|
|
232
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onError) == null ? void 0 : _a.call(mutationOptions, error, variables);
|
|
233
|
+
},
|
|
234
|
+
onSuccess: (data, variables) => {
|
|
235
|
+
var _a;
|
|
236
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
237
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a.call(mutationOptions, data, variables);
|
|
238
|
+
},
|
|
239
|
+
onSettled: mutationOptions == null ? void 0 : mutationOptions.onSettled
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
function useUpdate(mutationOptions) {
|
|
243
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
244
|
+
return (0, import_react_query.useMutation)({
|
|
245
|
+
mutationFn: async ({ id, data }) => {
|
|
246
|
+
const res = await client.put(`${path}/${id}`, data);
|
|
247
|
+
return applyTransform(res.data);
|
|
248
|
+
},
|
|
249
|
+
onMutate: optimistic ? async ({ id, data }) => {
|
|
250
|
+
await qc.cancelQueries({ queryKey: [name, id] });
|
|
251
|
+
const prev = qc.getQueryData([name, id]);
|
|
252
|
+
qc.setQueryData([name, id], (old) => ({
|
|
253
|
+
...old,
|
|
254
|
+
...data
|
|
255
|
+
}));
|
|
256
|
+
return { prev };
|
|
257
|
+
} : void 0,
|
|
258
|
+
onError: (error, variables, context) => {
|
|
259
|
+
var _a;
|
|
260
|
+
const ctx = context;
|
|
261
|
+
if (optimistic && (ctx == null ? void 0 : ctx.prev)) qc.setQueryData([name, variables.id], ctx.prev);
|
|
262
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onError) == null ? void 0 : _a.call(mutationOptions, error, variables);
|
|
263
|
+
},
|
|
264
|
+
onSuccess: (data, variables) => {
|
|
265
|
+
var _a;
|
|
266
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
267
|
+
qc.invalidateQueries({ queryKey: [name, variables.id] });
|
|
268
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a.call(mutationOptions, data, variables);
|
|
269
|
+
},
|
|
270
|
+
onSettled: mutationOptions == null ? void 0 : mutationOptions.onSettled
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function usePatch(mutationOptions) {
|
|
274
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
275
|
+
return (0, import_react_query.useMutation)({
|
|
276
|
+
mutationFn: async ({ id, data }) => {
|
|
277
|
+
const res = await client.patch(`${path}/${id}`, data);
|
|
278
|
+
return applyTransform(res.data);
|
|
279
|
+
},
|
|
280
|
+
onMutate: optimistic ? async ({ id, data }) => {
|
|
281
|
+
await qc.cancelQueries({ queryKey: [name, id] });
|
|
282
|
+
const prev = qc.getQueryData([name, id]);
|
|
283
|
+
qc.setQueryData([name, id], (old) => ({
|
|
284
|
+
...old,
|
|
285
|
+
...data
|
|
286
|
+
}));
|
|
287
|
+
return { prev };
|
|
288
|
+
} : void 0,
|
|
289
|
+
onError: (error, variables, context) => {
|
|
290
|
+
var _a;
|
|
291
|
+
const ctx = context;
|
|
292
|
+
if (optimistic && (ctx == null ? void 0 : ctx.prev)) qc.setQueryData([name, variables.id], ctx.prev);
|
|
293
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onError) == null ? void 0 : _a.call(mutationOptions, error, variables);
|
|
294
|
+
},
|
|
295
|
+
onSuccess: (data, variables) => {
|
|
296
|
+
var _a;
|
|
297
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
298
|
+
qc.invalidateQueries({ queryKey: [name, variables.id] });
|
|
299
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a.call(mutationOptions, data, variables);
|
|
300
|
+
},
|
|
301
|
+
onSettled: mutationOptions == null ? void 0 : mutationOptions.onSettled
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function useDelete(mutationOptions) {
|
|
305
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
306
|
+
return (0, import_react_query.useMutation)({
|
|
307
|
+
mutationFn: async (id) => {
|
|
308
|
+
await client.delete(`${path}/${id}`);
|
|
309
|
+
},
|
|
310
|
+
onMutate: optimistic ? async (id) => {
|
|
311
|
+
await qc.cancelQueries({ queryKey: [name] });
|
|
312
|
+
const prev = qc.getQueryData([name]);
|
|
313
|
+
qc.setQueryData(
|
|
314
|
+
[name],
|
|
315
|
+
(old = []) => old.filter((item) => item.id !== id)
|
|
316
|
+
);
|
|
317
|
+
return { prev };
|
|
318
|
+
} : void 0,
|
|
319
|
+
onError: (error, id, context) => {
|
|
320
|
+
var _a;
|
|
321
|
+
const ctx = context;
|
|
322
|
+
if (optimistic && (ctx == null ? void 0 : ctx.prev)) qc.setQueryData([name], ctx.prev);
|
|
323
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onError) == null ? void 0 : _a.call(mutationOptions, error, id);
|
|
324
|
+
},
|
|
325
|
+
onSuccess: (_, id) => {
|
|
326
|
+
var _a;
|
|
327
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
328
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a.call(mutationOptions, void 0, id);
|
|
329
|
+
},
|
|
330
|
+
onSettled: mutationOptions == null ? void 0 : mutationOptions.onSettled
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
function useBulkDelete(mutationOptions) {
|
|
334
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
335
|
+
return (0, import_react_query.useMutation)({
|
|
336
|
+
mutationFn: async (ids) => {
|
|
337
|
+
await client.delete(path, { data: { ids } });
|
|
338
|
+
},
|
|
339
|
+
onSuccess: (_, ids) => {
|
|
340
|
+
var _a;
|
|
341
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
342
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a.call(mutationOptions, void 0, ids);
|
|
343
|
+
},
|
|
344
|
+
onError: mutationOptions == null ? void 0 : mutationOptions.onError
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
function useBulkUpdate(mutationOptions) {
|
|
348
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
349
|
+
return (0, import_react_query.useMutation)({
|
|
350
|
+
mutationFn: async ({ ids, data }) => {
|
|
351
|
+
const res = await client.patch(path, { ids, ...data });
|
|
352
|
+
return applyTransform(res.data);
|
|
353
|
+
},
|
|
354
|
+
onSuccess: (data, variables) => {
|
|
355
|
+
var _a;
|
|
356
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
357
|
+
(_a = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a.call(mutationOptions, data, variables);
|
|
358
|
+
},
|
|
359
|
+
onError: mutationOptions == null ? void 0 : mutationOptions.onError
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
function useUpload(uploadOptions) {
|
|
363
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
364
|
+
return (0, import_react_query.useMutation)({
|
|
365
|
+
mutationFn: async ({ id, file, extraFields }) => {
|
|
366
|
+
var _a;
|
|
367
|
+
const formData = new FormData();
|
|
368
|
+
const fieldName = (_a = uploadOptions == null ? void 0 : uploadOptions.fieldName) != null ? _a : "file";
|
|
369
|
+
if (Array.isArray(file)) {
|
|
370
|
+
file.forEach((f) => formData.append(fieldName, f));
|
|
371
|
+
} else {
|
|
372
|
+
formData.append(fieldName, file);
|
|
373
|
+
}
|
|
374
|
+
const mergedExtra = { ...uploadOptions == null ? void 0 : uploadOptions.extraFields, ...extraFields };
|
|
375
|
+
Object.entries(mergedExtra).forEach(([k, v]) => formData.append(k, v));
|
|
376
|
+
const url = id ? `${path}/${id}/upload` : `${path}/upload`;
|
|
377
|
+
const res = await client.post(url, formData, {
|
|
378
|
+
headers: { "Content-Type": "multipart/form-data" },
|
|
379
|
+
onUploadProgress: (e) => {
|
|
380
|
+
if ((uploadOptions == null ? void 0 : uploadOptions.onProgress) && e.total) {
|
|
381
|
+
uploadOptions.onProgress(Math.round(e.loaded * 100 / e.total));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
return applyTransform(res.data);
|
|
386
|
+
},
|
|
387
|
+
onSuccess: () => qc.invalidateQueries({ queryKey: [name] })
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
function useFormData(opts) {
|
|
391
|
+
var _a, _b;
|
|
392
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
393
|
+
const method = (_a = opts == null ? void 0 : opts.method) != null ? _a : "post";
|
|
394
|
+
const url = (opts == null ? void 0 : opts.id) ? `${path}/${opts.id}` : path;
|
|
395
|
+
return (0, import_react_query.useMutation)({
|
|
396
|
+
mutationFn: async (formData) => {
|
|
397
|
+
const res = await client[method](url, formData, {
|
|
398
|
+
headers: { "Content-Type": "multipart/form-data" },
|
|
399
|
+
onUploadProgress: (e) => {
|
|
400
|
+
if ((opts == null ? void 0 : opts.onProgress) && e.total) {
|
|
401
|
+
opts.onProgress(Math.round(e.loaded * 100 / e.total));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
return applyTransform(res.data);
|
|
406
|
+
},
|
|
407
|
+
onSuccess: (data, variables) => {
|
|
408
|
+
var _a2, _b2;
|
|
409
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
410
|
+
(_b2 = (_a2 = opts == null ? void 0 : opts.mutationOptions) == null ? void 0 : _a2.onSuccess) == null ? void 0 : _b2.call(_a2, data, variables);
|
|
411
|
+
},
|
|
412
|
+
onError: (_b = opts == null ? void 0 : opts.mutationOptions) == null ? void 0 : _b.onError
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
function useDownload(downloadOptions) {
|
|
416
|
+
return (0, import_react_query.useMutation)({
|
|
417
|
+
mutationFn: async ({ id, params }) => {
|
|
418
|
+
var _a, _b;
|
|
419
|
+
const url = id ? `${path}/${id}/download` : `${path}/download`;
|
|
420
|
+
const res = await client.get(url, {
|
|
421
|
+
params,
|
|
422
|
+
responseType: "blob",
|
|
423
|
+
onDownloadProgress: (e) => {
|
|
424
|
+
if ((downloadOptions == null ? void 0 : downloadOptions.onProgress) && e.total) {
|
|
425
|
+
downloadOptions.onProgress(Math.round(e.loaded * 100 / e.total));
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
if ((downloadOptions == null ? void 0 : downloadOptions.saveAs) !== false) {
|
|
430
|
+
const filename = (_b = (_a = downloadOptions == null ? void 0 : downloadOptions.filename) != null ? _a : extractFilename(res.headers["content-disposition"])) != null ? _b : `${name}-download`;
|
|
431
|
+
triggerBrowserDownload(res.data, filename, downloadOptions == null ? void 0 : downloadOptions.mimeType);
|
|
432
|
+
}
|
|
433
|
+
return res.data;
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
function useExport(opts) {
|
|
438
|
+
return (0, import_react_query.useMutation)({
|
|
439
|
+
mutationFn: async (queryOptions) => {
|
|
440
|
+
var _a, _b, _c;
|
|
441
|
+
const params = buildQueryParams(queryOptions, defaultParams);
|
|
442
|
+
const res = await client.get(`${path}/export`, {
|
|
443
|
+
params: { ...params, format: (_a = opts == null ? void 0 : opts.format) != null ? _a : "csv" },
|
|
444
|
+
responseType: "blob",
|
|
445
|
+
onDownloadProgress: (e) => {
|
|
446
|
+
if ((opts == null ? void 0 : opts.onProgress) && e.total) {
|
|
447
|
+
opts.onProgress(Math.round(e.loaded * 100 / e.total));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
const fmt = (_b = opts == null ? void 0 : opts.format) != null ? _b : "csv";
|
|
452
|
+
const filename = (_c = opts == null ? void 0 : opts.filename) != null ? _c : `${name}-export.${fmt}`;
|
|
453
|
+
const mimeMap = {
|
|
454
|
+
csv: "text/csv",
|
|
455
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
456
|
+
pdf: "application/pdf"
|
|
457
|
+
};
|
|
458
|
+
triggerBrowserDownload(res.data, filename, mimeMap[fmt]);
|
|
459
|
+
return res.data;
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
function useAction(action, opts) {
|
|
464
|
+
var _a, _b;
|
|
465
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
466
|
+
const method = (_a = opts == null ? void 0 : opts.method) != null ? _a : "post";
|
|
467
|
+
const url = (opts == null ? void 0 : opts.id) ? `${path}/${opts.id}/${action}` : `${path}/${action}`;
|
|
468
|
+
return (0, import_react_query.useMutation)({
|
|
469
|
+
mutationFn: async (payload) => {
|
|
470
|
+
const res = await client[method](url, payload);
|
|
471
|
+
return applyTransform(res.data);
|
|
472
|
+
},
|
|
473
|
+
onSuccess: (data, variables) => {
|
|
474
|
+
var _a2, _b2;
|
|
475
|
+
if ((opts == null ? void 0 : opts.invalidate) !== false) {
|
|
476
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
477
|
+
}
|
|
478
|
+
(_b2 = (_a2 = opts == null ? void 0 : opts.mutationOptions) == null ? void 0 : _a2.onSuccess) == null ? void 0 : _b2.call(_a2, data, variables);
|
|
479
|
+
},
|
|
480
|
+
onError: (_b = opts == null ? void 0 : opts.mutationOptions) == null ? void 0 : _b.onError
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
function useInvalidate() {
|
|
484
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
485
|
+
return (id) => {
|
|
486
|
+
if (id) {
|
|
487
|
+
qc.invalidateQueries({ queryKey: [name, id] });
|
|
488
|
+
} else {
|
|
489
|
+
qc.invalidateQueries({ queryKey: [name] });
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
function usePrefetch() {
|
|
494
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
495
|
+
return (id) => {
|
|
496
|
+
if (id) {
|
|
497
|
+
qc.prefetchQuery({
|
|
498
|
+
queryKey: [name, id],
|
|
499
|
+
queryFn: () => client.get(`${path}/${id}`).then((r) => r.data)
|
|
500
|
+
});
|
|
501
|
+
} else {
|
|
502
|
+
qc.prefetchQuery({
|
|
503
|
+
queryKey: [name],
|
|
504
|
+
queryFn: () => client.get(path).then((r) => r.data)
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function useSetCache() {
|
|
510
|
+
const qc = (0, import_react_query.useQueryClient)();
|
|
511
|
+
return (data, id) => {
|
|
512
|
+
if (id) {
|
|
513
|
+
qc.setQueryData([name, id], data);
|
|
514
|
+
} else {
|
|
515
|
+
qc.setQueryData([name], data);
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
return {
|
|
520
|
+
// ── Queries ──────────────────────────────────────────────────────────
|
|
521
|
+
/** Full list — with filters, search, sorting, polling */
|
|
522
|
+
useList,
|
|
523
|
+
/** Single item by ID */
|
|
524
|
+
useGet,
|
|
525
|
+
/** Page-number pagination */
|
|
526
|
+
usePaginatedList,
|
|
527
|
+
/** Offset-based infinite scroll */
|
|
528
|
+
useInfiniteList,
|
|
529
|
+
/** Cursor-based infinite scroll (for DB cursor pagination) */
|
|
530
|
+
useCursorList,
|
|
531
|
+
// ── Mutations ─────────────────────────────────────────────────────────
|
|
532
|
+
/** Create — POST /resource */
|
|
533
|
+
useCreate,
|
|
534
|
+
/** Full replace — PUT /resource/:id */
|
|
535
|
+
useUpdate,
|
|
536
|
+
/** Partial update — PATCH /resource/:id */
|
|
537
|
+
usePatch,
|
|
538
|
+
/** Delete — DELETE /resource/:id */
|
|
539
|
+
useDelete,
|
|
540
|
+
/** Delete many — DELETE /resource { ids: [...] } */
|
|
541
|
+
useBulkDelete,
|
|
542
|
+
/** Update many — PATCH /resource { ids: [...], ...fields } */
|
|
543
|
+
useBulkUpdate,
|
|
544
|
+
// ── File Operations ───────────────────────────────────────────────────
|
|
545
|
+
/** Upload file(s) with progress tracking */
|
|
546
|
+
useUpload,
|
|
547
|
+
/** Submit any FormData (mixed files + fields) */
|
|
548
|
+
useFormData,
|
|
549
|
+
/** Download blob file with progress + auto "Save As" */
|
|
550
|
+
useDownload,
|
|
551
|
+
/** Export list to CSV / XLSX / PDF */
|
|
552
|
+
useExport,
|
|
553
|
+
// ── Custom Actions ────────────────────────────────────────────────────
|
|
554
|
+
/** Arbitrary endpoint action (e.g. /resource/:id/approve) */
|
|
555
|
+
useAction,
|
|
556
|
+
// ── Cache Utilities ───────────────────────────────────────────────────
|
|
557
|
+
/** Manually invalidate cache */
|
|
558
|
+
useInvalidate,
|
|
559
|
+
/** Prefetch on hover/navigation */
|
|
560
|
+
usePrefetch,
|
|
561
|
+
/** Manually write data into cache (SSR/seed) */
|
|
562
|
+
useSetCache,
|
|
563
|
+
// ── Meta ──────────────────────────────────────────────────────────────
|
|
564
|
+
path,
|
|
565
|
+
name
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
function extractFilename(contentDisposition) {
|
|
569
|
+
if (!contentDisposition) return null;
|
|
570
|
+
const match = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
|
|
571
|
+
return match ? match[1].replace(/['"]/g, "").trim() : null;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// src/createApiClient.ts
|
|
575
|
+
function createApiClient(config) {
|
|
576
|
+
const {
|
|
577
|
+
baseURL,
|
|
578
|
+
getToken,
|
|
579
|
+
onTokenRefresh,
|
|
580
|
+
onAuthFailure,
|
|
581
|
+
onError,
|
|
582
|
+
headers = {},
|
|
583
|
+
timeout = 3e4,
|
|
584
|
+
retry = { count: 0, delay: 1e3, statusCodes: [429, 503] }
|
|
585
|
+
} = config;
|
|
586
|
+
const client = import_axios.default.create({
|
|
587
|
+
baseURL,
|
|
588
|
+
timeout,
|
|
589
|
+
headers: {
|
|
590
|
+
"Content-Type": "application/json",
|
|
591
|
+
...headers
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
client.interceptors.request.use(async (req) => {
|
|
595
|
+
const token = await (getToken == null ? void 0 : getToken());
|
|
596
|
+
if (token) {
|
|
597
|
+
req.headers.Authorization = `Bearer ${token}`;
|
|
598
|
+
}
|
|
599
|
+
return req;
|
|
600
|
+
});
|
|
601
|
+
let isRefreshing = false;
|
|
602
|
+
let refreshQueue = [];
|
|
603
|
+
function processRefreshQueue(token, error = null) {
|
|
604
|
+
refreshQueue.forEach(({ resolve, reject }) => {
|
|
605
|
+
if (token) resolve(token);
|
|
606
|
+
else reject(error);
|
|
607
|
+
});
|
|
608
|
+
refreshQueue = [];
|
|
609
|
+
}
|
|
610
|
+
client.interceptors.response.use(
|
|
611
|
+
(res) => res,
|
|
612
|
+
async (error) => {
|
|
613
|
+
var _a, _b;
|
|
614
|
+
const originalRequest = error.config;
|
|
615
|
+
if (onError) onError(error);
|
|
616
|
+
if (((_a = error.response) == null ? void 0 : _a.status) === 401 && originalRequest && !originalRequest._retryCount) {
|
|
617
|
+
if (isRefreshing) {
|
|
618
|
+
return new Promise((resolve, reject) => {
|
|
619
|
+
refreshQueue.push({ resolve, reject });
|
|
620
|
+
}).then((token) => {
|
|
621
|
+
originalRequest.headers.Authorization = `Bearer ${token}`;
|
|
622
|
+
return client(originalRequest);
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
if (onTokenRefresh) {
|
|
626
|
+
isRefreshing = true;
|
|
627
|
+
try {
|
|
628
|
+
const newToken = await refreshTokenRequest(config);
|
|
629
|
+
onTokenRefresh(newToken);
|
|
630
|
+
processRefreshQueue(newToken);
|
|
631
|
+
isRefreshing = false;
|
|
632
|
+
originalRequest.headers.Authorization = `Bearer ${newToken}`;
|
|
633
|
+
return client(originalRequest);
|
|
634
|
+
} catch (refreshError) {
|
|
635
|
+
processRefreshQueue(null, refreshError);
|
|
636
|
+
isRefreshing = false;
|
|
637
|
+
onAuthFailure == null ? void 0 : onAuthFailure();
|
|
638
|
+
return Promise.reject(refreshError);
|
|
639
|
+
}
|
|
640
|
+
} else {
|
|
641
|
+
onAuthFailure == null ? void 0 : onAuthFailure();
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if (originalRequest && shouldRetry(error, retry)) {
|
|
645
|
+
originalRequest._retryCount = ((_b = originalRequest._retryCount) != null ? _b : 0) + 1;
|
|
646
|
+
if (originalRequest._retryCount <= retry.count) {
|
|
647
|
+
const delay = retry.delay !== void 0 ? retry.delay * originalRequest._retryCount : 1e3;
|
|
648
|
+
await sleep(delay);
|
|
649
|
+
return client(originalRequest);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return Promise.reject(error);
|
|
653
|
+
}
|
|
654
|
+
);
|
|
655
|
+
return {
|
|
656
|
+
/** Access the raw axios instance for custom requests */
|
|
657
|
+
axiosInstance: client,
|
|
658
|
+
/** Create a resource with CRUD hooks */
|
|
659
|
+
resource: (name, options) => createResource(client, name, options),
|
|
660
|
+
/** Raw GET */
|
|
661
|
+
get: (url, axiosConfig) => client.get(url, axiosConfig).then((r) => r.data),
|
|
662
|
+
/** Raw POST */
|
|
663
|
+
post: (url, data, axiosConfig) => client.post(url, data, axiosConfig).then((r) => r.data),
|
|
664
|
+
/** Raw PUT */
|
|
665
|
+
put: (url, data, axiosConfig) => client.put(url, data, axiosConfig).then((r) => r.data),
|
|
666
|
+
/** Raw PATCH */
|
|
667
|
+
patch: (url, data, axiosConfig) => client.patch(url, data, axiosConfig).then((r) => r.data),
|
|
668
|
+
/** Raw DELETE */
|
|
669
|
+
delete: (url, axiosConfig) => client.delete(url, axiosConfig).then((r) => r.data)
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
async function refreshTokenRequest(config) {
|
|
673
|
+
var _a, _b, _c, _d;
|
|
674
|
+
const currentToken = await ((_a = config.getToken) == null ? void 0 : _a.call(config));
|
|
675
|
+
const res = await import_axios.default.post(
|
|
676
|
+
`${config.baseURL}/auth/refresh`,
|
|
677
|
+
{},
|
|
678
|
+
{
|
|
679
|
+
headers: currentToken ? { Authorization: `Bearer ${currentToken}` } : void 0
|
|
680
|
+
}
|
|
681
|
+
);
|
|
682
|
+
return (_d = (_b = res.data) == null ? void 0 : _b.token) != null ? _d : (_c = res.data) == null ? void 0 : _c.accessToken;
|
|
683
|
+
}
|
|
684
|
+
function shouldRetry(error, retry) {
|
|
685
|
+
if (!retry.count) return false;
|
|
686
|
+
if (!error.response) return true;
|
|
687
|
+
if (retry.statusCodes && retry.statusCodes.length > 0) {
|
|
688
|
+
return retry.statusCodes.includes(error.response.status);
|
|
689
|
+
}
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
693
|
+
0 && (module.exports = {
|
|
694
|
+
createApiClient,
|
|
695
|
+
createResource
|
|
696
|
+
});
|