@classytic/arc-next 0.3.1 → 0.4.1
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 +139 -32
- package/dist/api.d.ts +120 -3
- package/dist/api.js +109 -5
- package/dist/client.d.ts +63 -16
- package/dist/client.js +87 -18
- package/dist/hooks.d.ts +56 -2
- package/dist/hooks.js +360 -46
- package/dist/mutation.d.ts +5 -22
- package/dist/mutation.js +14 -15
- package/dist/prefetch.d.ts +56 -2
- package/dist/prefetch.js +70 -24
- package/dist/query.d.ts +41 -8
- package/dist/query.js +33 -11
- package/dist/sse.d.ts +69 -0
- package/dist/sse.js +145 -0
- package/package.json +22 -13
package/dist/hooks.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { getAuthMode, getClientAuthContext } from "./client.js";
|
|
4
4
|
import { isKeysetPagination, isOffsetPagination } from "./api.js";
|
|
5
5
|
import { DEFAULT_QUERY_CONFIG, createCacheUtils, createQueryKeys, extractItem, getItemId, updateListCache, useDetailQuery, useInfiniteListQuery, useListQuery } from "./query.js";
|
|
6
6
|
import { useMutationWithTransition, useOptimisticMutation } from "./mutation.js";
|
|
7
|
-
import {
|
|
8
|
-
import { useCallback,
|
|
7
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
8
|
+
import { useCallback, useRef } from "react";
|
|
9
9
|
|
|
10
10
|
//#region src/hooks.ts
|
|
11
11
|
let useRouterHook = null;
|
|
@@ -21,11 +21,27 @@ let useRouterHook = null;
|
|
|
21
21
|
function configureNavigation(hook) {
|
|
22
22
|
useRouterHook = hook;
|
|
23
23
|
}
|
|
24
|
-
function createEnabledRule(token, options, authMode = getAuthMode()) {
|
|
24
|
+
function createEnabledRule(token, options, authMode = getAuthMode(), hasStaticAuth = false) {
|
|
25
25
|
if (authMode === "cookie" || options.public) return options.enabled ?? true;
|
|
26
|
+
if (hasStaticAuth) return options.enabled ?? true;
|
|
26
27
|
return options.enabled !== void 0 ? options.enabled && !!token : !!token;
|
|
27
28
|
}
|
|
28
|
-
function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks = {}, client }) {
|
|
29
|
+
function createCrudHooks({ api, entityKey, singular, plural, idField, defaults = {}, callbacks = {}, client }) {
|
|
30
|
+
const pluralName = plural ?? `${singular}s`;
|
|
31
|
+
/** Resolve auth context — per-client auth takes priority over global */
|
|
32
|
+
const resolveAuth = () => getClientAuthContext(client);
|
|
33
|
+
/** Whether auth is provided via static config (headers, internalApiKey, per-client auth) — no token needed for enablement */
|
|
34
|
+
const hasStaticAuth = !!(client?.config?.defaultHeaders || client?.config?.internalApiKey || client?.auth);
|
|
35
|
+
/** Extract ID from an item using configured idField, falling back to _id → id */
|
|
36
|
+
function resolveItemId(item) {
|
|
37
|
+
if (!item || typeof item !== "object") return null;
|
|
38
|
+
const obj = item;
|
|
39
|
+
if (idField) {
|
|
40
|
+
const val = obj[idField];
|
|
41
|
+
if (val != null) return String(val);
|
|
42
|
+
}
|
|
43
|
+
return getItemId(item);
|
|
44
|
+
}
|
|
29
45
|
const KEYS = createQueryKeys(entityKey);
|
|
30
46
|
const cache = createCacheUtils(KEYS);
|
|
31
47
|
const instanceToast = client?.toast;
|
|
@@ -49,12 +65,12 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
49
65
|
let token;
|
|
50
66
|
let params;
|
|
51
67
|
let options;
|
|
52
|
-
if (tokenOrParams ===
|
|
68
|
+
if (typeof tokenOrParams === "string" || tokenOrParams === null && maybeOptions !== void 0) {
|
|
53
69
|
token = tokenOrParams;
|
|
54
70
|
params = paramsOrOptions ?? {};
|
|
55
71
|
options = maybeOptions ?? {};
|
|
56
72
|
} else {
|
|
57
|
-
const auth =
|
|
73
|
+
const auth = resolveAuth();
|
|
58
74
|
token = auth.token;
|
|
59
75
|
params = tokenOrParams ?? {};
|
|
60
76
|
options = paramsOrOptions ?? {};
|
|
@@ -80,7 +96,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
80
96
|
...requestOpts
|
|
81
97
|
}
|
|
82
98
|
}),
|
|
83
|
-
enabled: createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
99
|
+
enabled: createEnabledRule(token, queryOpts, resolveAuthMode(), hasStaticAuth),
|
|
84
100
|
options: {
|
|
85
101
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
86
102
|
gcTime: queryOpts.gcTime ?? config.gcTime,
|
|
@@ -90,18 +106,19 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
90
106
|
refetchIntervalInBackground: queryOpts.refetchIntervalInBackground
|
|
91
107
|
},
|
|
92
108
|
prefillDetailCache: queryOpts.prefillDetailCache ?? true,
|
|
93
|
-
detailKeyBuilder: (id) => KEYS.
|
|
109
|
+
detailKeyBuilder: (id) => KEYS.scopedDetail(id, organizationId ?? null),
|
|
110
|
+
itemIdResolver: resolveItemId,
|
|
94
111
|
select: queryOpts.select
|
|
95
112
|
});
|
|
96
113
|
}
|
|
97
114
|
function useDetail(id, tokenOrOptions, maybeOptions) {
|
|
98
115
|
let token;
|
|
99
116
|
let options;
|
|
100
|
-
if (tokenOrOptions ===
|
|
117
|
+
if (typeof tokenOrOptions === "string" || tokenOrOptions === null && maybeOptions !== void 0) {
|
|
101
118
|
token = tokenOrOptions;
|
|
102
119
|
options = maybeOptions ?? {};
|
|
103
120
|
} else {
|
|
104
|
-
const auth =
|
|
121
|
+
const auth = resolveAuth();
|
|
105
122
|
token = auth.token;
|
|
106
123
|
options = tokenOrOptions ?? {};
|
|
107
124
|
if (auth.organizationId && !options.organizationId) options = {
|
|
@@ -110,8 +127,9 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
110
127
|
};
|
|
111
128
|
}
|
|
112
129
|
const { organizationId, params: queryParams, request: requestOpts, ...restOptions } = options;
|
|
130
|
+
const detailKey = KEYS.scopedDetail(id || "", organizationId ?? null);
|
|
113
131
|
return useDetailQuery({
|
|
114
|
-
queryKey: queryParams ? [...
|
|
132
|
+
queryKey: queryParams ? [...detailKey, queryParams] : detailKey,
|
|
115
133
|
queryFn: ({ signal }) => api.getById({
|
|
116
134
|
id,
|
|
117
135
|
token,
|
|
@@ -122,7 +140,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
122
140
|
...requestOpts
|
|
123
141
|
}
|
|
124
142
|
}),
|
|
125
|
-
enabled: !!id && createEnabledRule(token, restOptions, resolveAuthMode()),
|
|
143
|
+
enabled: !!id && createEnabledRule(token, restOptions, resolveAuthMode(), hasStaticAuth),
|
|
126
144
|
options: {
|
|
127
145
|
staleTime: restOptions.staleTime ?? config.staleTime,
|
|
128
146
|
gcTime: restOptions.gcTime ?? config.gcTime,
|
|
@@ -151,7 +169,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
151
169
|
const optimisticItem = {
|
|
152
170
|
...data,
|
|
153
171
|
_optimistic: true,
|
|
154
|
-
[
|
|
172
|
+
[idField ?? (resolveItemId(data) ? "id" : "_id")]: resolveItemId(data) ?? `temp-${Date.now()}`
|
|
155
173
|
};
|
|
156
174
|
return updateListCache(oldData, (arr) => [optimisticItem, ...arr || []]);
|
|
157
175
|
},
|
|
@@ -181,17 +199,20 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
181
199
|
queryKeys: [KEYS.lists(), KEYS.details()],
|
|
182
200
|
shouldToast,
|
|
183
201
|
optimisticUpdate: (oldData, { id, data }) => {
|
|
184
|
-
const updated = updateListCache(oldData, (arr) => (arr || []).map((item) =>
|
|
202
|
+
const updated = updateListCache(oldData, (arr) => (arr || []).map((item) => resolveItemId(item) === id ? {
|
|
185
203
|
...item,
|
|
186
204
|
...data
|
|
187
205
|
} : item));
|
|
188
|
-
|
|
206
|
+
const detailUpdater = (current) => current ? {
|
|
189
207
|
...current,
|
|
190
208
|
data: {
|
|
191
209
|
...current.data || {},
|
|
192
210
|
...data
|
|
193
211
|
}
|
|
194
|
-
} : current
|
|
212
|
+
} : current;
|
|
213
|
+
queryClient.getQueriesData({ queryKey: KEYS.detail(id) }).forEach(([qKey, qData]) => {
|
|
214
|
+
if (qData) queryClient.setQueryData(qKey, detailUpdater);
|
|
215
|
+
});
|
|
195
216
|
return updated;
|
|
196
217
|
},
|
|
197
218
|
onSuccess: (raw, { id, data: updateData }) => {
|
|
@@ -229,7 +250,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
229
250
|
queryKeys: [KEYS.lists()],
|
|
230
251
|
shouldToast,
|
|
231
252
|
optimisticUpdate: (oldData, { id }) => {
|
|
232
|
-
return updateListCache(oldData, (arr) => (arr || []).filter((item) =>
|
|
253
|
+
return updateListCache(oldData, (arr) => (arr || []).filter((item) => resolveItemId(item) !== id));
|
|
233
254
|
},
|
|
234
255
|
onSuccess: (data, { id }) => {
|
|
235
256
|
queryClient.removeQueries({ queryKey: KEYS.detail(id) });
|
|
@@ -247,8 +268,25 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
247
268
|
},
|
|
248
269
|
toastHandler: instanceToast
|
|
249
270
|
});
|
|
250
|
-
const
|
|
251
|
-
|
|
271
|
+
const restoreMutation = useMutationWithTransition({
|
|
272
|
+
mutationFn: ({ token, organizationId, id }) => {
|
|
273
|
+
if (!api.restore) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a restore method`));
|
|
274
|
+
return api.restore({
|
|
275
|
+
token,
|
|
276
|
+
organizationId,
|
|
277
|
+
id
|
|
278
|
+
});
|
|
279
|
+
},
|
|
280
|
+
invalidateQueries: [KEYS.lists(), KEYS.custom("deleted")],
|
|
281
|
+
shouldToast,
|
|
282
|
+
messages: {
|
|
283
|
+
success: `${singular} restored successfully`,
|
|
284
|
+
error: `Failed to restore ${singular.toLowerCase()}`
|
|
285
|
+
},
|
|
286
|
+
toastHandler: instanceToast
|
|
287
|
+
});
|
|
288
|
+
const resolveActionAuth = useCallback((params) => {
|
|
289
|
+
const auth = resolveAuth();
|
|
252
290
|
return {
|
|
253
291
|
...params,
|
|
254
292
|
token: params.token ?? auth.token,
|
|
@@ -259,7 +297,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
259
297
|
create: useCallback(async (params, options) => {
|
|
260
298
|
silentRef.current = options?.silent ?? false;
|
|
261
299
|
try {
|
|
262
|
-
const entity = extractItem(await createMutation.mutateAsync(
|
|
300
|
+
const entity = extractItem(await createMutation.mutateAsync(resolveActionAuth(params)));
|
|
263
301
|
options?.onSuccess?.(entity);
|
|
264
302
|
options?.onSettled?.(entity, null);
|
|
265
303
|
return entity;
|
|
@@ -270,11 +308,11 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
270
308
|
} finally {
|
|
271
309
|
silentRef.current = false;
|
|
272
310
|
}
|
|
273
|
-
}, [createMutation,
|
|
311
|
+
}, [createMutation, resolveActionAuth]),
|
|
274
312
|
update: useCallback(async (params, options) => {
|
|
275
313
|
silentRef.current = options?.silent ?? false;
|
|
276
314
|
try {
|
|
277
|
-
const entity = extractItem(await updateMutation.mutateAsync(
|
|
315
|
+
const entity = extractItem(await updateMutation.mutateAsync(resolveActionAuth(params)));
|
|
278
316
|
options?.onSuccess?.(entity);
|
|
279
317
|
options?.onSettled?.(entity, null);
|
|
280
318
|
return entity;
|
|
@@ -285,11 +323,11 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
285
323
|
} finally {
|
|
286
324
|
silentRef.current = false;
|
|
287
325
|
}
|
|
288
|
-
}, [updateMutation,
|
|
326
|
+
}, [updateMutation, resolveActionAuth]),
|
|
289
327
|
remove: useCallback(async (params, options) => {
|
|
290
328
|
silentRef.current = options?.silent ?? false;
|
|
291
329
|
try {
|
|
292
|
-
const result = await deleteMutation.mutateAsync(
|
|
330
|
+
const result = await deleteMutation.mutateAsync(resolveActionAuth(params));
|
|
293
331
|
options?.onSuccess?.(result);
|
|
294
332
|
options?.onSettled?.(result, null);
|
|
295
333
|
return result;
|
|
@@ -300,23 +338,39 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
300
338
|
} finally {
|
|
301
339
|
silentRef.current = false;
|
|
302
340
|
}
|
|
303
|
-
}, [deleteMutation,
|
|
341
|
+
}, [deleteMutation, resolveActionAuth]),
|
|
342
|
+
restore: useCallback(async (params, options) => {
|
|
343
|
+
silentRef.current = options?.silent ?? false;
|
|
344
|
+
try {
|
|
345
|
+
const entity = extractItem(await restoreMutation.mutateAsync(resolveActionAuth(params)));
|
|
346
|
+
options?.onSuccess?.(entity);
|
|
347
|
+
options?.onSettled?.(entity, null);
|
|
348
|
+
return entity;
|
|
349
|
+
} catch (error) {
|
|
350
|
+
options?.onError?.(error);
|
|
351
|
+
options?.onSettled?.(void 0, error);
|
|
352
|
+
throw error;
|
|
353
|
+
} finally {
|
|
354
|
+
silentRef.current = false;
|
|
355
|
+
}
|
|
356
|
+
}, [restoreMutation, resolveActionAuth]),
|
|
304
357
|
isCreating: createMutation.isPending,
|
|
305
358
|
isUpdating: updateMutation.isPending,
|
|
306
359
|
isDeleting: deleteMutation.isPending,
|
|
307
|
-
|
|
360
|
+
isRestoring: restoreMutation.isPending,
|
|
361
|
+
isMutating: createMutation.isPending || updateMutation.isPending || deleteMutation.isPending || restoreMutation.isPending
|
|
308
362
|
};
|
|
309
363
|
}
|
|
310
364
|
function useInfiniteList(tokenOrParams, paramsOrOptions, maybeOptions) {
|
|
311
365
|
let token;
|
|
312
366
|
let params;
|
|
313
367
|
let options;
|
|
314
|
-
if (tokenOrParams ===
|
|
368
|
+
if (typeof tokenOrParams === "string" || tokenOrParams === null && maybeOptions !== void 0) {
|
|
315
369
|
token = tokenOrParams;
|
|
316
370
|
params = paramsOrOptions ?? {};
|
|
317
371
|
options = maybeOptions ?? {};
|
|
318
372
|
} else {
|
|
319
|
-
const auth =
|
|
373
|
+
const auth = resolveAuth();
|
|
320
374
|
token = auth.token;
|
|
321
375
|
params = tokenOrParams ?? {};
|
|
322
376
|
options = paramsOrOptions ?? {};
|
|
@@ -348,7 +402,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
348
402
|
}
|
|
349
403
|
});
|
|
350
404
|
},
|
|
351
|
-
enabled: createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
405
|
+
enabled: createEnabledRule(token, queryOpts, resolveAuthMode(), hasStaticAuth),
|
|
352
406
|
initialPageParam: restParams.after ? restParams.after : 1,
|
|
353
407
|
getNextPageParam: (lastPage) => {
|
|
354
408
|
const page = lastPage;
|
|
@@ -357,6 +411,13 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
357
411
|
const p = page;
|
|
358
412
|
if (typeof p.hasNext === "boolean" && typeof p.page === "number") return p.hasNext ? p.page + 1 : void 0;
|
|
359
413
|
},
|
|
414
|
+
getPreviousPageParam: queryOpts.maxPages != null ? (firstPage) => {
|
|
415
|
+
const page = firstPage;
|
|
416
|
+
if (isOffsetPagination(page)) return page.hasPrev ? page.page - 1 : void 0;
|
|
417
|
+
const p = page;
|
|
418
|
+
if (typeof p.hasPrev === "boolean" && typeof p.page === "number") return p.hasPrev ? p.page - 1 : void 0;
|
|
419
|
+
} : void 0,
|
|
420
|
+
maxPages: queryOpts.maxPages,
|
|
360
421
|
options: {
|
|
361
422
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
362
423
|
gcTime: queryOpts.gcTime ?? config.gcTime,
|
|
@@ -371,7 +432,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
371
432
|
return useMutationWithTransition({
|
|
372
433
|
mutationFn: ({ data, id, path }) => {
|
|
373
434
|
if (!api.upload) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define an upload method`));
|
|
374
|
-
const auth =
|
|
435
|
+
const auth = resolveAuth();
|
|
375
436
|
return api.upload({
|
|
376
437
|
token: auth.token,
|
|
377
438
|
organizationId: auth.organizationId,
|
|
@@ -392,9 +453,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
392
453
|
});
|
|
393
454
|
}
|
|
394
455
|
function useSearch(query, params, options) {
|
|
395
|
-
|
|
396
|
-
const searchApi = api.search;
|
|
397
|
-
const auth = getAuthContext();
|
|
456
|
+
const auth = resolveAuth();
|
|
398
457
|
const token = params?.token ?? auth.token;
|
|
399
458
|
const organizationId = params?.organizationId ?? auth.organizationId;
|
|
400
459
|
const { organizationId: _, token: _t, ...restParams } = params ?? {};
|
|
@@ -413,16 +472,19 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
413
472
|
"search",
|
|
414
473
|
searchKeyParams
|
|
415
474
|
],
|
|
416
|
-
queryFn: ({ signal }) =>
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
475
|
+
queryFn: ({ signal }) => {
|
|
476
|
+
if (!api.search) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a search method`));
|
|
477
|
+
return api.search({
|
|
478
|
+
token,
|
|
479
|
+
organizationId,
|
|
480
|
+
params: searchParams,
|
|
481
|
+
options: {
|
|
482
|
+
signal,
|
|
483
|
+
...requestOpts
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
},
|
|
487
|
+
enabled: !!api.search && query.length > 0 && createEnabledRule(token, queryOpts, resolveAuthMode(), hasStaticAuth),
|
|
426
488
|
options: {
|
|
427
489
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
428
490
|
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
@@ -441,6 +503,248 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
441
503
|
toastHandler: instanceToast
|
|
442
504
|
});
|
|
443
505
|
}
|
|
506
|
+
function useDeleted(params, options) {
|
|
507
|
+
const auth = resolveAuth();
|
|
508
|
+
const token = auth.token;
|
|
509
|
+
const mergedParams = params ?? {};
|
|
510
|
+
const organizationId = mergedParams.organizationId ?? auth.organizationId;
|
|
511
|
+
const { organizationId: _, ...restParams } = mergedParams;
|
|
512
|
+
const { request: requestOpts, ...queryOpts } = options ?? {};
|
|
513
|
+
return useListQuery({
|
|
514
|
+
queryKey: KEYS.custom("deleted", {
|
|
515
|
+
organizationId,
|
|
516
|
+
...restParams
|
|
517
|
+
}),
|
|
518
|
+
queryFn: ({ signal }) => {
|
|
519
|
+
if (!api.getDeleted) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a getDeleted method`));
|
|
520
|
+
return api.getDeleted({
|
|
521
|
+
token,
|
|
522
|
+
organizationId,
|
|
523
|
+
params: restParams,
|
|
524
|
+
options: {
|
|
525
|
+
signal,
|
|
526
|
+
...requestOpts
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
},
|
|
530
|
+
enabled: !!api.getDeleted && createEnabledRule(token, queryOpts, resolveAuthMode(), hasStaticAuth),
|
|
531
|
+
options: {
|
|
532
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
533
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
534
|
+
},
|
|
535
|
+
select: queryOpts.select
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
function useDetailBySlug(slug, options) {
|
|
539
|
+
const auth = resolveAuth();
|
|
540
|
+
const token = auth.token;
|
|
541
|
+
const resolvedOptions = options ?? {};
|
|
542
|
+
const organizationId = resolvedOptions.organizationId ?? auth.organizationId;
|
|
543
|
+
const { params: queryParams, request: requestOpts, ...restOptions } = resolvedOptions;
|
|
544
|
+
return useDetailQuery({
|
|
545
|
+
queryKey: queryParams ? KEYS.custom("slug", slug, queryParams) : KEYS.custom("slug", slug),
|
|
546
|
+
queryFn: ({ signal }) => {
|
|
547
|
+
if (!api.getBySlug) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a getBySlug method`));
|
|
548
|
+
return api.getBySlug({
|
|
549
|
+
slug,
|
|
550
|
+
token,
|
|
551
|
+
organizationId,
|
|
552
|
+
params: queryParams,
|
|
553
|
+
options: {
|
|
554
|
+
signal,
|
|
555
|
+
...requestOpts
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
},
|
|
559
|
+
enabled: !!api.getBySlug && !!slug && createEnabledRule(token, restOptions, resolveAuthMode(), hasStaticAuth),
|
|
560
|
+
options: {
|
|
561
|
+
staleTime: restOptions.staleTime ?? config.staleTime,
|
|
562
|
+
gcTime: restOptions.gcTime ?? config.gcTime,
|
|
563
|
+
refetchOnWindowFocus: restOptions.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
|
|
564
|
+
structuralSharing: restOptions.structuralSharing ?? config.structuralSharing
|
|
565
|
+
},
|
|
566
|
+
select: restOptions.select
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
function useTree(params, options) {
|
|
570
|
+
const auth = resolveAuth();
|
|
571
|
+
const token = auth.token;
|
|
572
|
+
const mergedParams = params ?? {};
|
|
573
|
+
const organizationId = mergedParams.organizationId ?? auth.organizationId;
|
|
574
|
+
const { organizationId: _, ...restParams } = mergedParams;
|
|
575
|
+
const { request: requestOpts, ...queryOpts } = options ?? {};
|
|
576
|
+
return useListQuery({
|
|
577
|
+
queryKey: KEYS.custom("tree", {
|
|
578
|
+
organizationId,
|
|
579
|
+
...restParams
|
|
580
|
+
}),
|
|
581
|
+
queryFn: ({ signal }) => {
|
|
582
|
+
if (!api.getTree) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a getTree method`));
|
|
583
|
+
return api.getTree({
|
|
584
|
+
token,
|
|
585
|
+
organizationId,
|
|
586
|
+
params: restParams,
|
|
587
|
+
options: {
|
|
588
|
+
signal,
|
|
589
|
+
...requestOpts
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
},
|
|
593
|
+
enabled: !!api.getTree && createEnabledRule(token, queryOpts, resolveAuthMode(), hasStaticAuth),
|
|
594
|
+
options: {
|
|
595
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
596
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
597
|
+
},
|
|
598
|
+
select: queryOpts.select
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
function useChildren(parentId, params, options) {
|
|
602
|
+
const auth = resolveAuth();
|
|
603
|
+
const token = auth.token;
|
|
604
|
+
const mergedParams = params ?? {};
|
|
605
|
+
const organizationId = mergedParams.organizationId ?? auth.organizationId;
|
|
606
|
+
const { organizationId: _, ...restParams } = mergedParams;
|
|
607
|
+
const { request: requestOpts, ...queryOpts } = options ?? {};
|
|
608
|
+
return useListQuery({
|
|
609
|
+
queryKey: KEYS.custom("children", parentId, {
|
|
610
|
+
organizationId,
|
|
611
|
+
...restParams
|
|
612
|
+
}),
|
|
613
|
+
queryFn: ({ signal }) => {
|
|
614
|
+
if (!api.getChildren) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a getChildren method`));
|
|
615
|
+
return api.getChildren({
|
|
616
|
+
token,
|
|
617
|
+
organizationId,
|
|
618
|
+
parentId,
|
|
619
|
+
params: restParams,
|
|
620
|
+
options: {
|
|
621
|
+
signal,
|
|
622
|
+
...requestOpts
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
},
|
|
626
|
+
enabled: !!api.getChildren && !!parentId && createEnabledRule(token, queryOpts, resolveAuthMode(), hasStaticAuth),
|
|
627
|
+
options: {
|
|
628
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
629
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
630
|
+
},
|
|
631
|
+
prefillDetailCache: queryOpts.prefillDetailCache ?? true,
|
|
632
|
+
detailKeyBuilder: (id) => KEYS.scopedDetail(id, organizationId ?? null),
|
|
633
|
+
itemIdResolver: resolveItemId,
|
|
634
|
+
select: queryOpts.select
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
function useFindBy(field, value, options) {
|
|
638
|
+
const auth = resolveAuth();
|
|
639
|
+
const token = auth.token;
|
|
640
|
+
const organizationId = auth.organizationId;
|
|
641
|
+
const { operator, request: requestOpts, ...queryOpts } = options ?? {};
|
|
642
|
+
return useListQuery({
|
|
643
|
+
queryKey: KEYS.custom("findBy", {
|
|
644
|
+
field,
|
|
645
|
+
value,
|
|
646
|
+
operator,
|
|
647
|
+
organizationId
|
|
648
|
+
}),
|
|
649
|
+
queryFn: ({ signal }) => {
|
|
650
|
+
if (!api.findBy) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a findBy method`));
|
|
651
|
+
return api.findBy({
|
|
652
|
+
token,
|
|
653
|
+
organizationId,
|
|
654
|
+
field,
|
|
655
|
+
value,
|
|
656
|
+
operator,
|
|
657
|
+
options: {
|
|
658
|
+
signal,
|
|
659
|
+
...requestOpts
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
},
|
|
663
|
+
enabled: !!api.findBy && value !== void 0 && value !== null && createEnabledRule(token, queryOpts, resolveAuthMode(), hasStaticAuth),
|
|
664
|
+
options: {
|
|
665
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
666
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
667
|
+
},
|
|
668
|
+
prefillDetailCache: queryOpts.prefillDetailCache ?? true,
|
|
669
|
+
detailKeyBuilder: (id) => KEYS.scopedDetail(id, organizationId ?? null),
|
|
670
|
+
itemIdResolver: resolveItemId,
|
|
671
|
+
select: queryOpts.select
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
function useBulkActions() {
|
|
675
|
+
const bulkCreateMutation = useMutationWithTransition({
|
|
676
|
+
mutationFn: (vars) => {
|
|
677
|
+
if (!api.bulkCreate) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a bulkCreate method`));
|
|
678
|
+
const auth = resolveAuth();
|
|
679
|
+
return api.bulkCreate({
|
|
680
|
+
token: vars.token ?? auth.token,
|
|
681
|
+
organizationId: vars.organizationId ?? auth.organizationId,
|
|
682
|
+
data: vars.data
|
|
683
|
+
});
|
|
684
|
+
},
|
|
685
|
+
invalidateQueries: [KEYS.lists()],
|
|
686
|
+
messages: {
|
|
687
|
+
success: `${pluralName} created successfully`,
|
|
688
|
+
error: `Failed to create ${pluralName.toLowerCase()}`
|
|
689
|
+
},
|
|
690
|
+
toastHandler: instanceToast
|
|
691
|
+
});
|
|
692
|
+
const bulkUpdateMutation = useMutationWithTransition({
|
|
693
|
+
mutationFn: (vars) => {
|
|
694
|
+
if (!api.bulkUpdate) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a bulkUpdate method`));
|
|
695
|
+
const auth = resolveAuth();
|
|
696
|
+
return api.bulkUpdate({
|
|
697
|
+
token: vars.token ?? auth.token,
|
|
698
|
+
organizationId: vars.organizationId ?? auth.organizationId,
|
|
699
|
+
filter: vars.filter,
|
|
700
|
+
data: vars.data
|
|
701
|
+
});
|
|
702
|
+
},
|
|
703
|
+
invalidateQueries: [KEYS.lists(), KEYS.details()],
|
|
704
|
+
messages: {
|
|
705
|
+
success: `${pluralName} updated successfully`,
|
|
706
|
+
error: `Failed to update ${pluralName.toLowerCase()}`
|
|
707
|
+
},
|
|
708
|
+
toastHandler: instanceToast
|
|
709
|
+
});
|
|
710
|
+
const bulkDeleteMutation = useMutationWithTransition({
|
|
711
|
+
mutationFn: (vars) => {
|
|
712
|
+
if (!api.bulkDelete) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a bulkDelete method`));
|
|
713
|
+
const auth = resolveAuth();
|
|
714
|
+
return api.bulkDelete({
|
|
715
|
+
token: vars.token ?? auth.token,
|
|
716
|
+
organizationId: vars.organizationId ?? auth.organizationId,
|
|
717
|
+
filter: vars.filter
|
|
718
|
+
});
|
|
719
|
+
},
|
|
720
|
+
invalidateQueries: [KEYS.lists()],
|
|
721
|
+
messages: {
|
|
722
|
+
success: `${pluralName} deleted successfully`,
|
|
723
|
+
error: `Failed to delete ${pluralName.toLowerCase()}`
|
|
724
|
+
},
|
|
725
|
+
toastHandler: instanceToast
|
|
726
|
+
});
|
|
727
|
+
return {
|
|
728
|
+
bulkCreate: async (params, options) => {
|
|
729
|
+
const items = (await bulkCreateMutation.mutateAsync(params))?.data ?? [];
|
|
730
|
+
options?.onSuccess?.(items);
|
|
731
|
+
return items;
|
|
732
|
+
},
|
|
733
|
+
bulkUpdate: async (params, options) => {
|
|
734
|
+
const result = await bulkUpdateMutation.mutateAsync(params);
|
|
735
|
+
options?.onSuccess?.(result);
|
|
736
|
+
return result;
|
|
737
|
+
},
|
|
738
|
+
bulkRemove: async (params, options) => {
|
|
739
|
+
const result = await bulkDeleteMutation.mutateAsync(params);
|
|
740
|
+
options?.onSuccess?.(result);
|
|
741
|
+
return result;
|
|
742
|
+
},
|
|
743
|
+
isBulkCreating: bulkCreateMutation.isPending,
|
|
744
|
+
isBulkUpdating: bulkUpdateMutation.isPending,
|
|
745
|
+
isBulkDeleting: bulkDeleteMutation.isPending
|
|
746
|
+
};
|
|
747
|
+
}
|
|
444
748
|
const resolvedRouterHook = instanceNavigation ?? useRouterHook ?? (() => ({
|
|
445
749
|
push: () => {},
|
|
446
750
|
replace: () => {}
|
|
@@ -449,8 +753,12 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
449
753
|
const queryClient = useQueryClient();
|
|
450
754
|
const router = resolvedRouterHook();
|
|
451
755
|
return useCallback((href, item, options = {}) => {
|
|
452
|
-
const id =
|
|
453
|
-
if (id)
|
|
756
|
+
const id = resolveItemId(item);
|
|
757
|
+
if (id) {
|
|
758
|
+
const orgId = resolveAuth().organizationId;
|
|
759
|
+
queryClient.setQueryData(KEYS.scopedDetail(id, orgId), { data: item });
|
|
760
|
+
if (orgId) queryClient.setQueryData(KEYS.detail(id), { data: item });
|
|
761
|
+
}
|
|
454
762
|
if (!router) return;
|
|
455
763
|
const { scroll = true, replace = false } = options;
|
|
456
764
|
if (replace) router.replace(href, { scroll });
|
|
@@ -464,6 +772,12 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
464
772
|
useDetail,
|
|
465
773
|
useInfiniteList,
|
|
466
774
|
useActions,
|
|
775
|
+
useBulkActions,
|
|
776
|
+
useDeleted,
|
|
777
|
+
useDetailBySlug,
|
|
778
|
+
useTree,
|
|
779
|
+
useChildren,
|
|
780
|
+
useFindBy,
|
|
467
781
|
useUpload,
|
|
468
782
|
useSearch,
|
|
469
783
|
useCustomMutation,
|
package/dist/mutation.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ToastHandler } from "./client.js";
|
|
2
|
-
import * as _tanstack_react_query0 from "@tanstack/react-query";
|
|
2
|
+
import * as _$_tanstack_react_query0 from "@tanstack/react-query";
|
|
3
3
|
import { QueryClient, QueryKey, UseMutateAsyncFunction, UseMutateFunction } from "@tanstack/react-query";
|
|
4
4
|
|
|
5
5
|
//#region src/mutation.d.ts
|
|
@@ -47,8 +47,8 @@ interface TransitionMutationConfig<TData, TVariables> {
|
|
|
47
47
|
toastHandler?: ToastHandler;
|
|
48
48
|
}
|
|
49
49
|
declare function useMutationWithTransition<TData, TVariables>(config: TransitionMutationConfig<TData, TVariables>): {
|
|
50
|
-
mutate: UseMutateFunction<TData, Error, TVariables,
|
|
51
|
-
mutateAsync: UseMutateAsyncFunction<TData, Error, TVariables,
|
|
50
|
+
mutate: UseMutateFunction<TData, Error, TVariables, void>;
|
|
51
|
+
mutateAsync: UseMutateAsyncFunction<TData, Error, TVariables, void>;
|
|
52
52
|
isPending: boolean;
|
|
53
53
|
isSuccess: boolean;
|
|
54
54
|
isError: boolean;
|
|
@@ -100,28 +100,11 @@ interface CreateOptimisticMutationConfig<TData, TVariables> {
|
|
|
100
100
|
shouldToast?: () => boolean;
|
|
101
101
|
toastHandler?: ToastHandler;
|
|
102
102
|
}
|
|
103
|
-
declare function useOptimisticMutation<TData, TVariables>(config: CreateOptimisticMutationConfig<TData, TVariables>): _tanstack_react_query0.UseMutationResult<TData, Error, TVariables, {
|
|
103
|
+
declare function useOptimisticMutation<TData, TVariables>(config: CreateOptimisticMutationConfig<TData, TVariables>): _$_tanstack_react_query0.UseMutationResult<TData, Error, TVariables, {
|
|
104
104
|
previous: {
|
|
105
105
|
key: readonly unknown[];
|
|
106
106
|
data: [readonly unknown[], unknown][];
|
|
107
107
|
}[];
|
|
108
108
|
}>;
|
|
109
|
-
declare const QUERY_CONFIGS: {
|
|
110
|
-
readonly realtime: {
|
|
111
|
-
readonly staleTime: 20000;
|
|
112
|
-
readonly refetchInterval: 30000;
|
|
113
|
-
};
|
|
114
|
-
readonly frequent: {
|
|
115
|
-
readonly staleTime: 60000;
|
|
116
|
-
};
|
|
117
|
-
readonly stable: {
|
|
118
|
-
readonly staleTime: 300000;
|
|
119
|
-
};
|
|
120
|
-
readonly static: {
|
|
121
|
-
readonly staleTime: 600000;
|
|
122
|
-
};
|
|
123
|
-
};
|
|
124
|
-
/** @deprecated Use `useOptimisticMutation` */
|
|
125
|
-
declare const createOptimisticMutation: typeof useOptimisticMutation;
|
|
126
109
|
//#endregion
|
|
127
|
-
export { CreateOptimisticMutationConfig, MutationCallbacks, MutationMessages, OptimisticMutationConfig,
|
|
110
|
+
export { CreateOptimisticMutationConfig, MutationCallbacks, MutationMessages, OptimisticMutationConfig, TransitionMutationConfig, TransitionMutationReturn, configureToast, useMutationWithOptimistic, useMutationWithTransition, useOptimisticMutation };
|