@classytic/arc-next 0.2.1 → 0.4.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/README.md +93 -27
- package/dist/api.d.ts +120 -33
- package/dist/api.js +116 -13
- package/dist/client.d.ts +38 -12
- package/dist/client.js +24 -7
- package/dist/hooks.d.ts +66 -70
- package/dist/hooks.js +410 -110
- package/dist/mutation.d.ts +10 -21
- package/dist/mutation.js +20 -15
- package/dist/prefetch.d.ts +40 -3
- package/dist/prefetch.js +57 -22
- package/dist/query-client.d.ts +1 -2
- package/dist/query-client.js +2 -2
- package/dist/query.d.ts +47 -6
- package/dist/query.js +67 -20
- package/dist/sse.d.ts +62 -0
- package/dist/sse.js +144 -0
- package/package.json +28 -13
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/hooks.d.ts.map +0 -1
- package/dist/hooks.js.map +0 -1
- package/dist/mutation.d.ts.map +0 -1
- package/dist/mutation.js.map +0 -1
- package/dist/prefetch.d.ts.map +0 -1
- package/dist/prefetch.js.map +0 -1
- package/dist/query-client.d.ts.map +0 -1
- package/dist/query-client.js.map +0 -1
- package/dist/query.d.ts.map +0 -1
- package/dist/query.js.map +0 -1
package/dist/hooks.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { getAuthContext, getAuthMode } from "./client.js";
|
|
4
4
|
import { isKeysetPagination, isOffsetPagination } from "./api.js";
|
|
5
|
-
import { DEFAULT_QUERY_CONFIG, createCacheUtils,
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { DEFAULT_QUERY_CONFIG, createCacheUtils, createQueryKeys, extractItem, getItemId, updateListCache, useDetailQuery, useInfiniteListQuery, useListQuery } from "./query.js";
|
|
6
|
+
import { useMutationWithTransition, useOptimisticMutation } from "./mutation.js";
|
|
7
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
8
8
|
import { useCallback, useRef } from "react";
|
|
9
9
|
|
|
10
10
|
//#region src/hooks.ts
|
|
@@ -12,6 +12,8 @@ let useRouterHook = null;
|
|
|
12
12
|
/**
|
|
13
13
|
* Configure the router hook for useNavigation. Call once at app init.
|
|
14
14
|
*
|
|
15
|
+
* **SSR safety:** This sets module-level state. Call only in client-side code.
|
|
16
|
+
*
|
|
15
17
|
* @example
|
|
16
18
|
* import { useRouter } from "next/navigation";
|
|
17
19
|
* configureNavigation(useRouter);
|
|
@@ -19,16 +21,27 @@ let useRouterHook = null;
|
|
|
19
21
|
function configureNavigation(hook) {
|
|
20
22
|
useRouterHook = hook;
|
|
21
23
|
}
|
|
22
|
-
function createEnabledRule(token, options) {
|
|
23
|
-
if (
|
|
24
|
+
function createEnabledRule(token, options, authMode = getAuthMode()) {
|
|
25
|
+
if (authMode === "cookie" || options.public) return options.enabled ?? true;
|
|
24
26
|
return options.enabled !== void 0 ? options.enabled && !!token : !!token;
|
|
25
27
|
}
|
|
26
|
-
function createCrudHooks({ api, entityKey, singular,
|
|
27
|
-
const
|
|
28
|
+
function createCrudHooks({ api, entityKey, singular, plural, idField, defaults = {}, callbacks = {}, client }) {
|
|
29
|
+
const pluralName = plural ?? `${singular}s`;
|
|
30
|
+
/** Extract ID from an item using configured idField, falling back to _id → id */
|
|
31
|
+
function resolveItemId(item) {
|
|
32
|
+
if (!item || typeof item !== "object") return null;
|
|
33
|
+
const obj = item;
|
|
34
|
+
if (idField) {
|
|
35
|
+
const val = obj[idField];
|
|
36
|
+
if (val != null) return String(val);
|
|
37
|
+
}
|
|
38
|
+
return getItemId(item);
|
|
39
|
+
}
|
|
28
40
|
const KEYS = createQueryKeys(entityKey);
|
|
29
41
|
const cache = createCacheUtils(KEYS);
|
|
30
42
|
const instanceToast = client?.toast;
|
|
31
43
|
const instanceNavigation = client?.navigation ?? null;
|
|
44
|
+
const resolveAuthMode = () => client?.config?.authMode ?? getAuthMode();
|
|
32
45
|
const config = {
|
|
33
46
|
...DEFAULT_QUERY_CONFIG,
|
|
34
47
|
...defaults,
|
|
@@ -56,15 +69,15 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
56
69
|
token = auth.token;
|
|
57
70
|
params = tokenOrParams ?? {};
|
|
58
71
|
options = paramsOrOptions ?? {};
|
|
59
|
-
if (
|
|
72
|
+
if (auth.organizationId && !params.organizationId) params = {
|
|
60
73
|
...params,
|
|
61
74
|
organizationId: auth.organizationId
|
|
62
75
|
};
|
|
63
76
|
}
|
|
64
77
|
const { organizationId, ...restParams } = params;
|
|
65
|
-
const scope = options._scope || (
|
|
78
|
+
const scope = options._scope || (organizationId ? "tenant" : "super-admin");
|
|
66
79
|
const { request: requestOpts, ...queryOpts } = options;
|
|
67
|
-
return
|
|
80
|
+
return useListQuery({
|
|
68
81
|
queryKey: KEYS.scopedList(scope, {
|
|
69
82
|
organizationId,
|
|
70
83
|
...restParams
|
|
@@ -78,7 +91,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
78
91
|
...requestOpts
|
|
79
92
|
}
|
|
80
93
|
}),
|
|
81
|
-
enabled: createEnabledRule(token, queryOpts),
|
|
94
|
+
enabled: createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
82
95
|
options: {
|
|
83
96
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
84
97
|
gcTime: queryOpts.gcTime ?? config.gcTime,
|
|
@@ -89,6 +102,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
89
102
|
},
|
|
90
103
|
prefillDetailCache: queryOpts.prefillDetailCache ?? true,
|
|
91
104
|
detailKeyBuilder: (id) => KEYS.detail(id),
|
|
105
|
+
itemIdResolver: resolveItemId,
|
|
92
106
|
select: queryOpts.select
|
|
93
107
|
});
|
|
94
108
|
}
|
|
@@ -102,13 +116,13 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
102
116
|
const auth = getAuthContext();
|
|
103
117
|
token = auth.token;
|
|
104
118
|
options = tokenOrOptions ?? {};
|
|
105
|
-
if (
|
|
119
|
+
if (auth.organizationId && !options.organizationId) options = {
|
|
106
120
|
...options,
|
|
107
121
|
organizationId: auth.organizationId
|
|
108
122
|
};
|
|
109
123
|
}
|
|
110
124
|
const { organizationId, params: queryParams, request: requestOpts, ...restOptions } = options;
|
|
111
|
-
return
|
|
125
|
+
return useDetailQuery({
|
|
112
126
|
queryKey: queryParams ? [...KEYS.detail(id || ""), queryParams] : KEYS.detail(id || ""),
|
|
113
127
|
queryFn: ({ signal }) => api.getById({
|
|
114
128
|
id,
|
|
@@ -120,10 +134,11 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
120
134
|
...requestOpts
|
|
121
135
|
}
|
|
122
136
|
}),
|
|
123
|
-
enabled: !!id && createEnabledRule(token, restOptions),
|
|
137
|
+
enabled: !!id && createEnabledRule(token, restOptions, resolveAuthMode()),
|
|
124
138
|
options: {
|
|
125
139
|
staleTime: restOptions.staleTime ?? config.staleTime,
|
|
126
140
|
gcTime: restOptions.gcTime ?? config.gcTime,
|
|
141
|
+
refetchOnWindowFocus: restOptions.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
|
|
127
142
|
structuralSharing: restOptions.structuralSharing ?? config.structuralSharing,
|
|
128
143
|
refetchInterval: restOptions.refetchInterval,
|
|
129
144
|
refetchIntervalInBackground: restOptions.refetchIntervalInBackground
|
|
@@ -135,7 +150,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
135
150
|
const queryClient = useQueryClient();
|
|
136
151
|
const silentRef = useRef(false);
|
|
137
152
|
const shouldToast = useCallback(() => !silentRef.current, []);
|
|
138
|
-
const createMutation =
|
|
153
|
+
const createMutation = useOptimisticMutation({
|
|
139
154
|
mutationFn: ({ token, organizationId, data }) => api.create({
|
|
140
155
|
token,
|
|
141
156
|
organizationId,
|
|
@@ -148,18 +163,18 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
148
163
|
const optimisticItem = {
|
|
149
164
|
...data,
|
|
150
165
|
_optimistic: true,
|
|
151
|
-
[
|
|
166
|
+
[idField ?? (resolveItemId(data) ? "id" : "_id")]: resolveItemId(data) ?? `temp-${Date.now()}`
|
|
152
167
|
};
|
|
153
168
|
return updateListCache(oldData, (arr) => [optimisticItem, ...arr || []]);
|
|
154
169
|
},
|
|
155
|
-
onSuccess: (
|
|
156
|
-
callbacks.onCreate?.onSuccess?.(
|
|
170
|
+
onSuccess: (raw, variables) => {
|
|
171
|
+
callbacks.onCreate?.onSuccess?.(extractItem(raw), { data: variables.data }, void 0);
|
|
157
172
|
},
|
|
158
173
|
onError: (error, variables) => {
|
|
159
174
|
callbacks.onCreate?.onError?.(error, { data: variables.data }, void 0);
|
|
160
175
|
},
|
|
161
|
-
onSettled: (
|
|
162
|
-
callbacks.onCreate?.onSettled?.(
|
|
176
|
+
onSettled: (raw, error, variables) => {
|
|
177
|
+
callbacks.onCreate?.onSettled?.(raw ? extractItem(raw) : void 0, error, { data: variables.data }, void 0);
|
|
163
178
|
},
|
|
164
179
|
messages: {
|
|
165
180
|
success: config.messages.createSuccess,
|
|
@@ -167,7 +182,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
167
182
|
},
|
|
168
183
|
toastHandler: instanceToast
|
|
169
184
|
});
|
|
170
|
-
const updateMutation =
|
|
185
|
+
const updateMutation = useOptimisticMutation({
|
|
171
186
|
mutationFn: ({ token, organizationId, id, data }) => api.update({
|
|
172
187
|
token,
|
|
173
188
|
organizationId,
|
|
@@ -175,10 +190,10 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
175
190
|
data
|
|
176
191
|
}),
|
|
177
192
|
queryClient,
|
|
178
|
-
queryKeys: [KEYS.lists()],
|
|
193
|
+
queryKeys: [KEYS.lists(), KEYS.details()],
|
|
179
194
|
shouldToast,
|
|
180
195
|
optimisticUpdate: (oldData, { id, data }) => {
|
|
181
|
-
const updated = updateListCache(oldData, (arr) => (arr || []).map((item) =>
|
|
196
|
+
const updated = updateListCache(oldData, (arr) => (arr || []).map((item) => resolveItemId(item) === id ? {
|
|
182
197
|
...item,
|
|
183
198
|
...data
|
|
184
199
|
} : item));
|
|
@@ -191,9 +206,9 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
191
206
|
} : current);
|
|
192
207
|
return updated;
|
|
193
208
|
},
|
|
194
|
-
onSuccess: (
|
|
209
|
+
onSuccess: (raw, { id, data: updateData }) => {
|
|
195
210
|
queryClient.invalidateQueries({ queryKey: KEYS.detail(id) });
|
|
196
|
-
callbacks.onUpdate?.onSuccess?.(
|
|
211
|
+
callbacks.onUpdate?.onSuccess?.(extractItem(raw), {
|
|
197
212
|
id,
|
|
198
213
|
data: updateData
|
|
199
214
|
}, void 0);
|
|
@@ -204,8 +219,8 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
204
219
|
data
|
|
205
220
|
}, void 0);
|
|
206
221
|
},
|
|
207
|
-
onSettled: (
|
|
208
|
-
callbacks.onUpdate?.onSettled?.(
|
|
222
|
+
onSettled: (raw, error, { id, data: updateData }) => {
|
|
223
|
+
callbacks.onUpdate?.onSettled?.(raw ? extractItem(raw) : void 0, error, {
|
|
209
224
|
id,
|
|
210
225
|
data: updateData
|
|
211
226
|
}, void 0);
|
|
@@ -216,7 +231,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
216
231
|
},
|
|
217
232
|
toastHandler: instanceToast
|
|
218
233
|
});
|
|
219
|
-
const deleteMutation =
|
|
234
|
+
const deleteMutation = useOptimisticMutation({
|
|
220
235
|
mutationFn: ({ token, organizationId, id }) => api.delete({
|
|
221
236
|
token,
|
|
222
237
|
organizationId,
|
|
@@ -226,10 +241,10 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
226
241
|
queryKeys: [KEYS.lists()],
|
|
227
242
|
shouldToast,
|
|
228
243
|
optimisticUpdate: (oldData, { id }) => {
|
|
229
|
-
|
|
230
|
-
return updateListCache(oldData, (arr) => (arr || []).filter((item) => getItemId(item) !== id));
|
|
244
|
+
return updateListCache(oldData, (arr) => (arr || []).filter((item) => resolveItemId(item) !== id));
|
|
231
245
|
},
|
|
232
246
|
onSuccess: (data, { id }) => {
|
|
247
|
+
queryClient.removeQueries({ queryKey: KEYS.detail(id) });
|
|
233
248
|
callbacks.onDelete?.onSuccess?.(data, { id }, void 0);
|
|
234
249
|
},
|
|
235
250
|
onError: (error, { id }) => {
|
|
@@ -244,67 +259,97 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
244
259
|
},
|
|
245
260
|
toastHandler: instanceToast
|
|
246
261
|
});
|
|
247
|
-
const
|
|
262
|
+
const restoreMutation = useMutationWithTransition({
|
|
263
|
+
mutationFn: ({ token, organizationId, id }) => {
|
|
264
|
+
if (!api.restore) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a restore method`));
|
|
265
|
+
return api.restore({
|
|
266
|
+
token,
|
|
267
|
+
organizationId,
|
|
268
|
+
id
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
invalidateQueries: [KEYS.lists(), KEYS.custom("deleted")],
|
|
272
|
+
shouldToast,
|
|
273
|
+
messages: {
|
|
274
|
+
success: `${singular} restored successfully`,
|
|
275
|
+
error: `Failed to restore ${singular.toLowerCase()}`
|
|
276
|
+
},
|
|
277
|
+
toastHandler: instanceToast
|
|
278
|
+
});
|
|
279
|
+
const resolveAuth = useCallback((params) => {
|
|
248
280
|
const auth = getAuthContext();
|
|
249
281
|
return {
|
|
250
282
|
...params,
|
|
251
283
|
token: params.token ?? auth.token,
|
|
252
|
-
organizationId:
|
|
284
|
+
organizationId: params.organizationId ?? auth.organizationId
|
|
253
285
|
};
|
|
254
|
-
};
|
|
255
|
-
const create = async (params, options) => {
|
|
256
|
-
silentRef.current = options?.silent ?? false;
|
|
257
|
-
try {
|
|
258
|
-
const result = await createMutation.mutateAsync(resolveAuth(params));
|
|
259
|
-
options?.onSuccess?.(result);
|
|
260
|
-
options?.onSettled?.(result, null);
|
|
261
|
-
return result;
|
|
262
|
-
} catch (error) {
|
|
263
|
-
options?.onError?.(error);
|
|
264
|
-
options?.onSettled?.(void 0, error);
|
|
265
|
-
throw error;
|
|
266
|
-
} finally {
|
|
267
|
-
silentRef.current = false;
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
const update = async (params, options) => {
|
|
271
|
-
silentRef.current = options?.silent ?? false;
|
|
272
|
-
try {
|
|
273
|
-
const result = await updateMutation.mutateAsync(resolveAuth(params));
|
|
274
|
-
options?.onSuccess?.(result);
|
|
275
|
-
options?.onSettled?.(result, null);
|
|
276
|
-
return result;
|
|
277
|
-
} catch (error) {
|
|
278
|
-
options?.onError?.(error);
|
|
279
|
-
options?.onSettled?.(void 0, error);
|
|
280
|
-
throw error;
|
|
281
|
-
} finally {
|
|
282
|
-
silentRef.current = false;
|
|
283
|
-
}
|
|
284
|
-
};
|
|
285
|
-
const remove = async (params, options) => {
|
|
286
|
-
silentRef.current = options?.silent ?? false;
|
|
287
|
-
try {
|
|
288
|
-
const result = await deleteMutation.mutateAsync(resolveAuth(params));
|
|
289
|
-
options?.onSuccess?.(result);
|
|
290
|
-
options?.onSettled?.(result, null);
|
|
291
|
-
return result;
|
|
292
|
-
} catch (error) {
|
|
293
|
-
options?.onError?.(error);
|
|
294
|
-
options?.onSettled?.(void 0, error);
|
|
295
|
-
throw error;
|
|
296
|
-
} finally {
|
|
297
|
-
silentRef.current = false;
|
|
298
|
-
}
|
|
299
|
-
};
|
|
286
|
+
}, []);
|
|
300
287
|
return {
|
|
301
|
-
create,
|
|
302
|
-
|
|
303
|
-
|
|
288
|
+
create: useCallback(async (params, options) => {
|
|
289
|
+
silentRef.current = options?.silent ?? false;
|
|
290
|
+
try {
|
|
291
|
+
const entity = extractItem(await createMutation.mutateAsync(resolveAuth(params)));
|
|
292
|
+
options?.onSuccess?.(entity);
|
|
293
|
+
options?.onSettled?.(entity, null);
|
|
294
|
+
return entity;
|
|
295
|
+
} catch (error) {
|
|
296
|
+
options?.onError?.(error);
|
|
297
|
+
options?.onSettled?.(void 0, error);
|
|
298
|
+
throw error;
|
|
299
|
+
} finally {
|
|
300
|
+
silentRef.current = false;
|
|
301
|
+
}
|
|
302
|
+
}, [createMutation, resolveAuth]),
|
|
303
|
+
update: useCallback(async (params, options) => {
|
|
304
|
+
silentRef.current = options?.silent ?? false;
|
|
305
|
+
try {
|
|
306
|
+
const entity = extractItem(await updateMutation.mutateAsync(resolveAuth(params)));
|
|
307
|
+
options?.onSuccess?.(entity);
|
|
308
|
+
options?.onSettled?.(entity, null);
|
|
309
|
+
return entity;
|
|
310
|
+
} catch (error) {
|
|
311
|
+
options?.onError?.(error);
|
|
312
|
+
options?.onSettled?.(void 0, error);
|
|
313
|
+
throw error;
|
|
314
|
+
} finally {
|
|
315
|
+
silentRef.current = false;
|
|
316
|
+
}
|
|
317
|
+
}, [updateMutation, resolveAuth]),
|
|
318
|
+
remove: useCallback(async (params, options) => {
|
|
319
|
+
silentRef.current = options?.silent ?? false;
|
|
320
|
+
try {
|
|
321
|
+
const result = await deleteMutation.mutateAsync(resolveAuth(params));
|
|
322
|
+
options?.onSuccess?.(result);
|
|
323
|
+
options?.onSettled?.(result, null);
|
|
324
|
+
return result;
|
|
325
|
+
} catch (error) {
|
|
326
|
+
options?.onError?.(error);
|
|
327
|
+
options?.onSettled?.(void 0, error);
|
|
328
|
+
throw error;
|
|
329
|
+
} finally {
|
|
330
|
+
silentRef.current = false;
|
|
331
|
+
}
|
|
332
|
+
}, [deleteMutation, resolveAuth]),
|
|
333
|
+
restore: useCallback(async (params, options) => {
|
|
334
|
+
silentRef.current = options?.silent ?? false;
|
|
335
|
+
try {
|
|
336
|
+
const entity = extractItem(await restoreMutation.mutateAsync(resolveAuth(params)));
|
|
337
|
+
options?.onSuccess?.(entity);
|
|
338
|
+
options?.onSettled?.(entity, null);
|
|
339
|
+
return entity;
|
|
340
|
+
} catch (error) {
|
|
341
|
+
options?.onError?.(error);
|
|
342
|
+
options?.onSettled?.(void 0, error);
|
|
343
|
+
throw error;
|
|
344
|
+
} finally {
|
|
345
|
+
silentRef.current = false;
|
|
346
|
+
}
|
|
347
|
+
}, [restoreMutation, resolveAuth]),
|
|
304
348
|
isCreating: createMutation.isPending,
|
|
305
349
|
isUpdating: updateMutation.isPending,
|
|
306
350
|
isDeleting: deleteMutation.isPending,
|
|
307
|
-
|
|
351
|
+
isRestoring: restoreMutation.isPending,
|
|
352
|
+
isMutating: createMutation.isPending || updateMutation.isPending || deleteMutation.isPending || restoreMutation.isPending
|
|
308
353
|
};
|
|
309
354
|
}
|
|
310
355
|
function useInfiniteList(tokenOrParams, paramsOrOptions, maybeOptions) {
|
|
@@ -320,7 +365,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
320
365
|
token = auth.token;
|
|
321
366
|
params = tokenOrParams ?? {};
|
|
322
367
|
options = paramsOrOptions ?? {};
|
|
323
|
-
if (
|
|
368
|
+
if (auth.organizationId && !params.organizationId) params = {
|
|
324
369
|
...params,
|
|
325
370
|
organizationId: auth.organizationId
|
|
326
371
|
};
|
|
@@ -328,7 +373,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
328
373
|
const { organizationId, ...restParams } = params;
|
|
329
374
|
const scope = options._scope || (organizationId ? "tenant" : "super-admin");
|
|
330
375
|
const { request: requestOpts, ...queryOpts } = options;
|
|
331
|
-
return
|
|
376
|
+
return useInfiniteListQuery({
|
|
332
377
|
queryKey: [...KEYS.scopedList(scope, {
|
|
333
378
|
organizationId,
|
|
334
379
|
...restParams
|
|
@@ -348,7 +393,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
348
393
|
}
|
|
349
394
|
});
|
|
350
395
|
},
|
|
351
|
-
enabled: createEnabledRule(token, queryOpts),
|
|
396
|
+
enabled: createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
352
397
|
initialPageParam: restParams.after ? restParams.after : 1,
|
|
353
398
|
getNextPageParam: (lastPage) => {
|
|
354
399
|
const page = lastPage;
|
|
@@ -357,23 +402,31 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
357
402
|
const p = page;
|
|
358
403
|
if (typeof p.hasNext === "boolean" && typeof p.page === "number") return p.hasNext ? p.page + 1 : void 0;
|
|
359
404
|
},
|
|
405
|
+
getPreviousPageParam: queryOpts.maxPages != null ? (firstPage) => {
|
|
406
|
+
const page = firstPage;
|
|
407
|
+
if (isOffsetPagination(page)) return page.hasPrev ? page.page - 1 : void 0;
|
|
408
|
+
const p = page;
|
|
409
|
+
if (typeof p.hasPrev === "boolean" && typeof p.page === "number") return p.hasPrev ? p.page - 1 : void 0;
|
|
410
|
+
} : void 0,
|
|
411
|
+
maxPages: queryOpts.maxPages,
|
|
360
412
|
options: {
|
|
361
413
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
362
414
|
gcTime: queryOpts.gcTime ?? config.gcTime,
|
|
363
415
|
refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
|
|
364
|
-
structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing
|
|
416
|
+
structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing,
|
|
417
|
+
refetchInterval: queryOpts.refetchInterval,
|
|
418
|
+
refetchIntervalInBackground: queryOpts.refetchIntervalInBackground
|
|
365
419
|
}
|
|
366
420
|
});
|
|
367
421
|
}
|
|
368
422
|
function useUpload(options) {
|
|
369
|
-
if (!api.upload) throw new Error(`[arc-next] "${entityKey}" api does not define an upload method`);
|
|
370
|
-
const uploadApi = api.upload;
|
|
371
423
|
return useMutationWithTransition({
|
|
372
424
|
mutationFn: ({ data, id, path }) => {
|
|
425
|
+
if (!api.upload) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define an upload method`));
|
|
373
426
|
const auth = getAuthContext();
|
|
374
|
-
return
|
|
427
|
+
return api.upload({
|
|
375
428
|
token: auth.token,
|
|
376
|
-
organizationId:
|
|
429
|
+
organizationId: auth.organizationId,
|
|
377
430
|
data,
|
|
378
431
|
id,
|
|
379
432
|
path
|
|
@@ -391,12 +444,10 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
391
444
|
});
|
|
392
445
|
}
|
|
393
446
|
function useSearch(query, params, options) {
|
|
394
|
-
if (!api.search) throw new Error(`[arc-next] "${entityKey}" api does not define a search method`);
|
|
395
|
-
const searchApi = api.search;
|
|
396
447
|
const auth = getAuthContext();
|
|
397
|
-
const token = auth.token;
|
|
398
|
-
const organizationId =
|
|
399
|
-
const { organizationId: _, ...restParams } = params ?? {};
|
|
448
|
+
const token = params?.token ?? auth.token;
|
|
449
|
+
const organizationId = params?.organizationId ?? auth.organizationId;
|
|
450
|
+
const { organizationId: _, token: _t, ...restParams } = params ?? {};
|
|
400
451
|
const searchParams = {
|
|
401
452
|
q: query,
|
|
402
453
|
...restParams
|
|
@@ -406,22 +457,25 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
406
457
|
organizationId,
|
|
407
458
|
...searchParams
|
|
408
459
|
} : searchParams;
|
|
409
|
-
return
|
|
460
|
+
return useListQuery({
|
|
410
461
|
queryKey: [
|
|
411
462
|
...KEYS.lists(),
|
|
412
463
|
"search",
|
|
413
464
|
searchKeyParams
|
|
414
465
|
],
|
|
415
|
-
queryFn: ({ signal }) =>
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
466
|
+
queryFn: ({ signal }) => {
|
|
467
|
+
if (!api.search) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a search method`));
|
|
468
|
+
return api.search({
|
|
469
|
+
token,
|
|
470
|
+
organizationId,
|
|
471
|
+
params: searchParams,
|
|
472
|
+
options: {
|
|
473
|
+
signal,
|
|
474
|
+
...requestOpts
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
},
|
|
478
|
+
enabled: !!api.search && query.length > 0 && createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
425
479
|
options: {
|
|
426
480
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
427
481
|
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
@@ -440,11 +494,252 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
440
494
|
toastHandler: instanceToast
|
|
441
495
|
});
|
|
442
496
|
}
|
|
497
|
+
function useDeleted(params, options) {
|
|
498
|
+
const auth = getAuthContext();
|
|
499
|
+
const token = auth.token;
|
|
500
|
+
const mergedParams = params ?? {};
|
|
501
|
+
const organizationId = mergedParams.organizationId ?? auth.organizationId;
|
|
502
|
+
const { organizationId: _, ...restParams } = mergedParams;
|
|
503
|
+
const { request: requestOpts, ...queryOpts } = options ?? {};
|
|
504
|
+
return useListQuery({
|
|
505
|
+
queryKey: KEYS.custom("deleted", {
|
|
506
|
+
organizationId,
|
|
507
|
+
...restParams
|
|
508
|
+
}),
|
|
509
|
+
queryFn: ({ signal }) => {
|
|
510
|
+
if (!api.getDeleted) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a getDeleted method`));
|
|
511
|
+
return api.getDeleted({
|
|
512
|
+
token,
|
|
513
|
+
organizationId,
|
|
514
|
+
params: restParams,
|
|
515
|
+
options: {
|
|
516
|
+
signal,
|
|
517
|
+
...requestOpts
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
},
|
|
521
|
+
enabled: !!api.getDeleted && createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
522
|
+
options: {
|
|
523
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
524
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
525
|
+
},
|
|
526
|
+
select: queryOpts.select
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
function useDetailBySlug(slug, options) {
|
|
530
|
+
const auth = getAuthContext();
|
|
531
|
+
const token = auth.token;
|
|
532
|
+
const resolvedOptions = options ?? {};
|
|
533
|
+
const organizationId = resolvedOptions.organizationId ?? auth.organizationId;
|
|
534
|
+
const { params: queryParams, request: requestOpts, ...restOptions } = resolvedOptions;
|
|
535
|
+
return useDetailQuery({
|
|
536
|
+
queryKey: queryParams ? KEYS.custom("slug", slug, queryParams) : KEYS.custom("slug", slug),
|
|
537
|
+
queryFn: ({ signal }) => {
|
|
538
|
+
if (!api.getBySlug) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a getBySlug method`));
|
|
539
|
+
return api.getBySlug({
|
|
540
|
+
slug,
|
|
541
|
+
token,
|
|
542
|
+
organizationId,
|
|
543
|
+
params: queryParams,
|
|
544
|
+
options: {
|
|
545
|
+
signal,
|
|
546
|
+
...requestOpts
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
},
|
|
550
|
+
enabled: !!api.getBySlug && !!slug && createEnabledRule(token, restOptions, resolveAuthMode()),
|
|
551
|
+
options: {
|
|
552
|
+
staleTime: restOptions.staleTime ?? config.staleTime,
|
|
553
|
+
gcTime: restOptions.gcTime ?? config.gcTime,
|
|
554
|
+
refetchOnWindowFocus: restOptions.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
|
|
555
|
+
structuralSharing: restOptions.structuralSharing ?? config.structuralSharing
|
|
556
|
+
},
|
|
557
|
+
select: restOptions.select
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
function useTree(params, options) {
|
|
561
|
+
const auth = getAuthContext();
|
|
562
|
+
const token = auth.token;
|
|
563
|
+
const mergedParams = params ?? {};
|
|
564
|
+
const organizationId = mergedParams.organizationId ?? auth.organizationId;
|
|
565
|
+
const { organizationId: _, ...restParams } = mergedParams;
|
|
566
|
+
const { request: requestOpts, ...queryOpts } = options ?? {};
|
|
567
|
+
return useListQuery({
|
|
568
|
+
queryKey: KEYS.custom("tree", {
|
|
569
|
+
organizationId,
|
|
570
|
+
...restParams
|
|
571
|
+
}),
|
|
572
|
+
queryFn: ({ signal }) => {
|
|
573
|
+
if (!api.getTree) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a getTree method`));
|
|
574
|
+
return api.getTree({
|
|
575
|
+
token,
|
|
576
|
+
organizationId,
|
|
577
|
+
params: restParams,
|
|
578
|
+
options: {
|
|
579
|
+
signal,
|
|
580
|
+
...requestOpts
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
},
|
|
584
|
+
enabled: !!api.getTree && createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
585
|
+
options: {
|
|
586
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
587
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
588
|
+
},
|
|
589
|
+
select: queryOpts.select
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
function useChildren(parentId, params, options) {
|
|
593
|
+
const auth = getAuthContext();
|
|
594
|
+
const token = auth.token;
|
|
595
|
+
const mergedParams = params ?? {};
|
|
596
|
+
const organizationId = mergedParams.organizationId ?? auth.organizationId;
|
|
597
|
+
const { organizationId: _, ...restParams } = mergedParams;
|
|
598
|
+
const { request: requestOpts, ...queryOpts } = options ?? {};
|
|
599
|
+
return useListQuery({
|
|
600
|
+
queryKey: KEYS.custom("children", parentId, {
|
|
601
|
+
organizationId,
|
|
602
|
+
...restParams
|
|
603
|
+
}),
|
|
604
|
+
queryFn: ({ signal }) => {
|
|
605
|
+
if (!api.getChildren) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a getChildren method`));
|
|
606
|
+
return api.getChildren({
|
|
607
|
+
token,
|
|
608
|
+
organizationId,
|
|
609
|
+
parentId,
|
|
610
|
+
params: restParams,
|
|
611
|
+
options: {
|
|
612
|
+
signal,
|
|
613
|
+
...requestOpts
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
},
|
|
617
|
+
enabled: !!api.getChildren && !!parentId && createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
618
|
+
options: {
|
|
619
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
620
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
621
|
+
},
|
|
622
|
+
prefillDetailCache: queryOpts.prefillDetailCache ?? true,
|
|
623
|
+
detailKeyBuilder: (id) => KEYS.detail(id),
|
|
624
|
+
itemIdResolver: resolveItemId,
|
|
625
|
+
select: queryOpts.select
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
function useFindBy(field, value, options) {
|
|
629
|
+
const auth = getAuthContext();
|
|
630
|
+
const token = auth.token;
|
|
631
|
+
const organizationId = auth.organizationId;
|
|
632
|
+
const { operator, request: requestOpts, ...queryOpts } = options ?? {};
|
|
633
|
+
return useListQuery({
|
|
634
|
+
queryKey: KEYS.custom("findBy", field, value, operator),
|
|
635
|
+
queryFn: ({ signal }) => {
|
|
636
|
+
if (!api.findBy) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a findBy method`));
|
|
637
|
+
return api.findBy({
|
|
638
|
+
token,
|
|
639
|
+
organizationId,
|
|
640
|
+
field,
|
|
641
|
+
value,
|
|
642
|
+
operator,
|
|
643
|
+
options: {
|
|
644
|
+
signal,
|
|
645
|
+
...requestOpts
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
},
|
|
649
|
+
enabled: !!api.findBy && value !== void 0 && value !== null && createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
650
|
+
options: {
|
|
651
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
652
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
653
|
+
},
|
|
654
|
+
prefillDetailCache: queryOpts.prefillDetailCache ?? true,
|
|
655
|
+
detailKeyBuilder: (id) => KEYS.detail(id),
|
|
656
|
+
itemIdResolver: resolveItemId,
|
|
657
|
+
select: queryOpts.select
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
function useBulkActions() {
|
|
661
|
+
const bulkCreateMutation = useMutationWithTransition({
|
|
662
|
+
mutationFn: (vars) => {
|
|
663
|
+
if (!api.bulkCreate) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a bulkCreate method`));
|
|
664
|
+
const auth = getAuthContext();
|
|
665
|
+
return api.bulkCreate({
|
|
666
|
+
token: vars.token ?? auth.token,
|
|
667
|
+
organizationId: vars.organizationId ?? auth.organizationId,
|
|
668
|
+
data: vars.data
|
|
669
|
+
});
|
|
670
|
+
},
|
|
671
|
+
invalidateQueries: [KEYS.lists()],
|
|
672
|
+
messages: {
|
|
673
|
+
success: `${pluralName} created successfully`,
|
|
674
|
+
error: `Failed to create ${pluralName.toLowerCase()}`
|
|
675
|
+
},
|
|
676
|
+
toastHandler: instanceToast
|
|
677
|
+
});
|
|
678
|
+
const bulkUpdateMutation = useMutationWithTransition({
|
|
679
|
+
mutationFn: (vars) => {
|
|
680
|
+
if (!api.bulkUpdate) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a bulkUpdate method`));
|
|
681
|
+
const auth = getAuthContext();
|
|
682
|
+
return api.bulkUpdate({
|
|
683
|
+
token: vars.token ?? auth.token,
|
|
684
|
+
organizationId: vars.organizationId ?? auth.organizationId,
|
|
685
|
+
filter: vars.filter,
|
|
686
|
+
data: vars.data
|
|
687
|
+
});
|
|
688
|
+
},
|
|
689
|
+
invalidateQueries: [KEYS.lists(), KEYS.details()],
|
|
690
|
+
messages: {
|
|
691
|
+
success: `${pluralName} updated successfully`,
|
|
692
|
+
error: `Failed to update ${pluralName.toLowerCase()}`
|
|
693
|
+
},
|
|
694
|
+
toastHandler: instanceToast
|
|
695
|
+
});
|
|
696
|
+
const bulkDeleteMutation = useMutationWithTransition({
|
|
697
|
+
mutationFn: (vars) => {
|
|
698
|
+
if (!api.bulkDelete) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define a bulkDelete method`));
|
|
699
|
+
const auth = getAuthContext();
|
|
700
|
+
return api.bulkDelete({
|
|
701
|
+
token: vars.token ?? auth.token,
|
|
702
|
+
organizationId: vars.organizationId ?? auth.organizationId,
|
|
703
|
+
filter: vars.filter
|
|
704
|
+
});
|
|
705
|
+
},
|
|
706
|
+
invalidateQueries: [KEYS.lists()],
|
|
707
|
+
messages: {
|
|
708
|
+
success: `${pluralName} deleted successfully`,
|
|
709
|
+
error: `Failed to delete ${pluralName.toLowerCase()}`
|
|
710
|
+
},
|
|
711
|
+
toastHandler: instanceToast
|
|
712
|
+
});
|
|
713
|
+
return {
|
|
714
|
+
bulkCreate: async (params, options) => {
|
|
715
|
+
const items = (await bulkCreateMutation.mutateAsync(params))?.data ?? [];
|
|
716
|
+
options?.onSuccess?.(items);
|
|
717
|
+
return items;
|
|
718
|
+
},
|
|
719
|
+
bulkUpdate: async (params, options) => {
|
|
720
|
+
const result = await bulkUpdateMutation.mutateAsync(params);
|
|
721
|
+
options?.onSuccess?.(result);
|
|
722
|
+
return result;
|
|
723
|
+
},
|
|
724
|
+
bulkRemove: async (params, options) => {
|
|
725
|
+
const result = await bulkDeleteMutation.mutateAsync(params);
|
|
726
|
+
options?.onSuccess?.(result);
|
|
727
|
+
return result;
|
|
728
|
+
},
|
|
729
|
+
isBulkCreating: bulkCreateMutation.isPending,
|
|
730
|
+
isBulkUpdating: bulkUpdateMutation.isPending,
|
|
731
|
+
isBulkDeleting: bulkDeleteMutation.isPending
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
const resolvedRouterHook = instanceNavigation ?? useRouterHook ?? (() => ({
|
|
735
|
+
push: () => {},
|
|
736
|
+
replace: () => {}
|
|
737
|
+
}));
|
|
443
738
|
function useNavigation() {
|
|
444
739
|
const queryClient = useQueryClient();
|
|
445
|
-
const router = (
|
|
740
|
+
const router = resolvedRouterHook();
|
|
446
741
|
return useCallback((href, item, options = {}) => {
|
|
447
|
-
const id =
|
|
742
|
+
const id = resolveItemId(item);
|
|
448
743
|
if (id) queryClient.setQueryData(KEYS.detail(id), { data: item });
|
|
449
744
|
if (!router) return;
|
|
450
745
|
const { scroll = true, replace = false } = options;
|
|
@@ -459,6 +754,12 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
459
754
|
useDetail,
|
|
460
755
|
useInfiniteList,
|
|
461
756
|
useActions,
|
|
757
|
+
useBulkActions,
|
|
758
|
+
useDeleted,
|
|
759
|
+
useDetailBySlug,
|
|
760
|
+
useTree,
|
|
761
|
+
useChildren,
|
|
762
|
+
useFindBy,
|
|
462
763
|
useUpload,
|
|
463
764
|
useSearch,
|
|
464
765
|
useCustomMutation,
|
|
@@ -467,5 +768,4 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
467
768
|
}
|
|
468
769
|
|
|
469
770
|
//#endregion
|
|
470
|
-
export { configureNavigation, createCrudHooks };
|
|
471
|
-
//# sourceMappingURL=hooks.js.map
|
|
771
|
+
export { configureNavigation, createCrudHooks };
|