@classytic/arc-next 0.2.1 → 0.3.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 +25 -20
- package/dist/api.d.ts +2 -32
- package/dist/api.js +12 -13
- package/dist/client.d.ts +18 -2
- package/dist/client.js +11 -5
- package/dist/hooks.d.ts +15 -73
- package/dist/hooks.js +98 -94
- package/dist/mutation.d.ts +6 -3
- package/dist/mutation.js +6 -3
- package/dist/prefetch.d.ts +9 -3
- package/dist/prefetch.js +9 -5
- package/dist/query-client.d.ts +1 -2
- package/dist/query-client.js +2 -2
- package/dist/query.d.ts +18 -5
- package/dist/query.js +54 -19
- package/package.json +9 -3
- 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,16 +2,18 @@
|
|
|
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 {
|
|
5
|
+
import { DEFAULT_QUERY_CONFIG, createCacheUtils, createQueryKeys, extractItem, getItemId, updateListCache, useDetailQuery, useInfiniteListQuery, useListQuery } from "./query.js";
|
|
6
|
+
import { useMutationWithTransition, useOptimisticMutation } from "./mutation.js";
|
|
7
7
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
8
|
-
import { useCallback, useRef } from "react";
|
|
8
|
+
import { useCallback, useMemo, useRef } from "react";
|
|
9
9
|
|
|
10
10
|
//#region src/hooks.ts
|
|
11
11
|
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,16 @@ 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 isPlatform = platformScoped ?? api.scope === "platform";
|
|
28
|
+
function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks = {}, client }) {
|
|
28
29
|
const KEYS = createQueryKeys(entityKey);
|
|
29
30
|
const cache = createCacheUtils(KEYS);
|
|
30
31
|
const instanceToast = client?.toast;
|
|
31
32
|
const instanceNavigation = client?.navigation ?? null;
|
|
33
|
+
const resolveAuthMode = () => client?.config?.authMode ?? getAuthMode();
|
|
32
34
|
const config = {
|
|
33
35
|
...DEFAULT_QUERY_CONFIG,
|
|
34
36
|
...defaults,
|
|
@@ -56,15 +58,15 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
56
58
|
token = auth.token;
|
|
57
59
|
params = tokenOrParams ?? {};
|
|
58
60
|
options = paramsOrOptions ?? {};
|
|
59
|
-
if (
|
|
61
|
+
if (auth.organizationId && !params.organizationId) params = {
|
|
60
62
|
...params,
|
|
61
63
|
organizationId: auth.organizationId
|
|
62
64
|
};
|
|
63
65
|
}
|
|
64
66
|
const { organizationId, ...restParams } = params;
|
|
65
|
-
const scope = options._scope || (
|
|
67
|
+
const scope = options._scope || (organizationId ? "tenant" : "super-admin");
|
|
66
68
|
const { request: requestOpts, ...queryOpts } = options;
|
|
67
|
-
return
|
|
69
|
+
return useListQuery({
|
|
68
70
|
queryKey: KEYS.scopedList(scope, {
|
|
69
71
|
organizationId,
|
|
70
72
|
...restParams
|
|
@@ -78,7 +80,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
78
80
|
...requestOpts
|
|
79
81
|
}
|
|
80
82
|
}),
|
|
81
|
-
enabled: createEnabledRule(token, queryOpts),
|
|
83
|
+
enabled: createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
82
84
|
options: {
|
|
83
85
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
84
86
|
gcTime: queryOpts.gcTime ?? config.gcTime,
|
|
@@ -102,13 +104,13 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
102
104
|
const auth = getAuthContext();
|
|
103
105
|
token = auth.token;
|
|
104
106
|
options = tokenOrOptions ?? {};
|
|
105
|
-
if (
|
|
107
|
+
if (auth.organizationId && !options.organizationId) options = {
|
|
106
108
|
...options,
|
|
107
109
|
organizationId: auth.organizationId
|
|
108
110
|
};
|
|
109
111
|
}
|
|
110
112
|
const { organizationId, params: queryParams, request: requestOpts, ...restOptions } = options;
|
|
111
|
-
return
|
|
113
|
+
return useDetailQuery({
|
|
112
114
|
queryKey: queryParams ? [...KEYS.detail(id || ""), queryParams] : KEYS.detail(id || ""),
|
|
113
115
|
queryFn: ({ signal }) => api.getById({
|
|
114
116
|
id,
|
|
@@ -120,10 +122,11 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
120
122
|
...requestOpts
|
|
121
123
|
}
|
|
122
124
|
}),
|
|
123
|
-
enabled: !!id && createEnabledRule(token, restOptions),
|
|
125
|
+
enabled: !!id && createEnabledRule(token, restOptions, resolveAuthMode()),
|
|
124
126
|
options: {
|
|
125
127
|
staleTime: restOptions.staleTime ?? config.staleTime,
|
|
126
128
|
gcTime: restOptions.gcTime ?? config.gcTime,
|
|
129
|
+
refetchOnWindowFocus: restOptions.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
|
|
127
130
|
structuralSharing: restOptions.structuralSharing ?? config.structuralSharing,
|
|
128
131
|
refetchInterval: restOptions.refetchInterval,
|
|
129
132
|
refetchIntervalInBackground: restOptions.refetchIntervalInBackground
|
|
@@ -135,7 +138,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
135
138
|
const queryClient = useQueryClient();
|
|
136
139
|
const silentRef = useRef(false);
|
|
137
140
|
const shouldToast = useCallback(() => !silentRef.current, []);
|
|
138
|
-
const createMutation =
|
|
141
|
+
const createMutation = useOptimisticMutation({
|
|
139
142
|
mutationFn: ({ token, organizationId, data }) => api.create({
|
|
140
143
|
token,
|
|
141
144
|
organizationId,
|
|
@@ -152,14 +155,14 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
152
155
|
};
|
|
153
156
|
return updateListCache(oldData, (arr) => [optimisticItem, ...arr || []]);
|
|
154
157
|
},
|
|
155
|
-
onSuccess: (
|
|
156
|
-
callbacks.onCreate?.onSuccess?.(
|
|
158
|
+
onSuccess: (raw, variables) => {
|
|
159
|
+
callbacks.onCreate?.onSuccess?.(extractItem(raw), { data: variables.data }, void 0);
|
|
157
160
|
},
|
|
158
161
|
onError: (error, variables) => {
|
|
159
162
|
callbacks.onCreate?.onError?.(error, { data: variables.data }, void 0);
|
|
160
163
|
},
|
|
161
|
-
onSettled: (
|
|
162
|
-
callbacks.onCreate?.onSettled?.(
|
|
164
|
+
onSettled: (raw, error, variables) => {
|
|
165
|
+
callbacks.onCreate?.onSettled?.(raw ? extractItem(raw) : void 0, error, { data: variables.data }, void 0);
|
|
163
166
|
},
|
|
164
167
|
messages: {
|
|
165
168
|
success: config.messages.createSuccess,
|
|
@@ -167,7 +170,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
167
170
|
},
|
|
168
171
|
toastHandler: instanceToast
|
|
169
172
|
});
|
|
170
|
-
const updateMutation =
|
|
173
|
+
const updateMutation = useOptimisticMutation({
|
|
171
174
|
mutationFn: ({ token, organizationId, id, data }) => api.update({
|
|
172
175
|
token,
|
|
173
176
|
organizationId,
|
|
@@ -175,7 +178,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
175
178
|
data
|
|
176
179
|
}),
|
|
177
180
|
queryClient,
|
|
178
|
-
queryKeys: [KEYS.lists()],
|
|
181
|
+
queryKeys: [KEYS.lists(), KEYS.details()],
|
|
179
182
|
shouldToast,
|
|
180
183
|
optimisticUpdate: (oldData, { id, data }) => {
|
|
181
184
|
const updated = updateListCache(oldData, (arr) => (arr || []).map((item) => getItemId(item) === id ? {
|
|
@@ -191,9 +194,9 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
191
194
|
} : current);
|
|
192
195
|
return updated;
|
|
193
196
|
},
|
|
194
|
-
onSuccess: (
|
|
197
|
+
onSuccess: (raw, { id, data: updateData }) => {
|
|
195
198
|
queryClient.invalidateQueries({ queryKey: KEYS.detail(id) });
|
|
196
|
-
callbacks.onUpdate?.onSuccess?.(
|
|
199
|
+
callbacks.onUpdate?.onSuccess?.(extractItem(raw), {
|
|
197
200
|
id,
|
|
198
201
|
data: updateData
|
|
199
202
|
}, void 0);
|
|
@@ -204,8 +207,8 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
204
207
|
data
|
|
205
208
|
}, void 0);
|
|
206
209
|
},
|
|
207
|
-
onSettled: (
|
|
208
|
-
callbacks.onUpdate?.onSettled?.(
|
|
210
|
+
onSettled: (raw, error, { id, data: updateData }) => {
|
|
211
|
+
callbacks.onUpdate?.onSettled?.(raw ? extractItem(raw) : void 0, error, {
|
|
209
212
|
id,
|
|
210
213
|
data: updateData
|
|
211
214
|
}, void 0);
|
|
@@ -216,7 +219,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
216
219
|
},
|
|
217
220
|
toastHandler: instanceToast
|
|
218
221
|
});
|
|
219
|
-
const deleteMutation =
|
|
222
|
+
const deleteMutation = useOptimisticMutation({
|
|
220
223
|
mutationFn: ({ token, organizationId, id }) => api.delete({
|
|
221
224
|
token,
|
|
222
225
|
organizationId,
|
|
@@ -226,10 +229,10 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
226
229
|
queryKeys: [KEYS.lists()],
|
|
227
230
|
shouldToast,
|
|
228
231
|
optimisticUpdate: (oldData, { id }) => {
|
|
229
|
-
queryClient.removeQueries({ queryKey: KEYS.detail(id) });
|
|
230
232
|
return updateListCache(oldData, (arr) => (arr || []).filter((item) => getItemId(item) !== id));
|
|
231
233
|
},
|
|
232
234
|
onSuccess: (data, { id }) => {
|
|
235
|
+
queryClient.removeQueries({ queryKey: KEYS.detail(id) });
|
|
233
236
|
callbacks.onDelete?.onSuccess?.(data, { id }, void 0);
|
|
234
237
|
},
|
|
235
238
|
onError: (error, { id }) => {
|
|
@@ -244,63 +247,60 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
244
247
|
},
|
|
245
248
|
toastHandler: instanceToast
|
|
246
249
|
});
|
|
247
|
-
const resolveAuth = (params) => {
|
|
250
|
+
const resolveAuth = useCallback((params) => {
|
|
248
251
|
const auth = getAuthContext();
|
|
249
252
|
return {
|
|
250
253
|
...params,
|
|
251
254
|
token: params.token ?? auth.token,
|
|
252
|
-
organizationId:
|
|
255
|
+
organizationId: params.organizationId ?? auth.organizationId
|
|
253
256
|
};
|
|
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
|
-
};
|
|
257
|
+
}, []);
|
|
300
258
|
return {
|
|
301
|
-
create,
|
|
302
|
-
|
|
303
|
-
|
|
259
|
+
create: useCallback(async (params, options) => {
|
|
260
|
+
silentRef.current = options?.silent ?? false;
|
|
261
|
+
try {
|
|
262
|
+
const entity = extractItem(await createMutation.mutateAsync(resolveAuth(params)));
|
|
263
|
+
options?.onSuccess?.(entity);
|
|
264
|
+
options?.onSettled?.(entity, null);
|
|
265
|
+
return entity;
|
|
266
|
+
} catch (error) {
|
|
267
|
+
options?.onError?.(error);
|
|
268
|
+
options?.onSettled?.(void 0, error);
|
|
269
|
+
throw error;
|
|
270
|
+
} finally {
|
|
271
|
+
silentRef.current = false;
|
|
272
|
+
}
|
|
273
|
+
}, [createMutation, resolveAuth]),
|
|
274
|
+
update: useCallback(async (params, options) => {
|
|
275
|
+
silentRef.current = options?.silent ?? false;
|
|
276
|
+
try {
|
|
277
|
+
const entity = extractItem(await updateMutation.mutateAsync(resolveAuth(params)));
|
|
278
|
+
options?.onSuccess?.(entity);
|
|
279
|
+
options?.onSettled?.(entity, null);
|
|
280
|
+
return entity;
|
|
281
|
+
} catch (error) {
|
|
282
|
+
options?.onError?.(error);
|
|
283
|
+
options?.onSettled?.(void 0, error);
|
|
284
|
+
throw error;
|
|
285
|
+
} finally {
|
|
286
|
+
silentRef.current = false;
|
|
287
|
+
}
|
|
288
|
+
}, [updateMutation, resolveAuth]),
|
|
289
|
+
remove: useCallback(async (params, options) => {
|
|
290
|
+
silentRef.current = options?.silent ?? false;
|
|
291
|
+
try {
|
|
292
|
+
const result = await deleteMutation.mutateAsync(resolveAuth(params));
|
|
293
|
+
options?.onSuccess?.(result);
|
|
294
|
+
options?.onSettled?.(result, null);
|
|
295
|
+
return result;
|
|
296
|
+
} catch (error) {
|
|
297
|
+
options?.onError?.(error);
|
|
298
|
+
options?.onSettled?.(void 0, error);
|
|
299
|
+
throw error;
|
|
300
|
+
} finally {
|
|
301
|
+
silentRef.current = false;
|
|
302
|
+
}
|
|
303
|
+
}, [deleteMutation, resolveAuth]),
|
|
304
304
|
isCreating: createMutation.isPending,
|
|
305
305
|
isUpdating: updateMutation.isPending,
|
|
306
306
|
isDeleting: deleteMutation.isPending,
|
|
@@ -320,7 +320,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
320
320
|
token = auth.token;
|
|
321
321
|
params = tokenOrParams ?? {};
|
|
322
322
|
options = paramsOrOptions ?? {};
|
|
323
|
-
if (
|
|
323
|
+
if (auth.organizationId && !params.organizationId) params = {
|
|
324
324
|
...params,
|
|
325
325
|
organizationId: auth.organizationId
|
|
326
326
|
};
|
|
@@ -328,7 +328,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
328
328
|
const { organizationId, ...restParams } = params;
|
|
329
329
|
const scope = options._scope || (organizationId ? "tenant" : "super-admin");
|
|
330
330
|
const { request: requestOpts, ...queryOpts } = options;
|
|
331
|
-
return
|
|
331
|
+
return useInfiniteListQuery({
|
|
332
332
|
queryKey: [...KEYS.scopedList(scope, {
|
|
333
333
|
organizationId,
|
|
334
334
|
...restParams
|
|
@@ -348,7 +348,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
348
348
|
}
|
|
349
349
|
});
|
|
350
350
|
},
|
|
351
|
-
enabled: createEnabledRule(token, queryOpts),
|
|
351
|
+
enabled: createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
352
352
|
initialPageParam: restParams.after ? restParams.after : 1,
|
|
353
353
|
getNextPageParam: (lastPage) => {
|
|
354
354
|
const page = lastPage;
|
|
@@ -361,19 +361,20 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
361
361
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
362
362
|
gcTime: queryOpts.gcTime ?? config.gcTime,
|
|
363
363
|
refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
|
|
364
|
-
structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing
|
|
364
|
+
structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing,
|
|
365
|
+
refetchInterval: queryOpts.refetchInterval,
|
|
366
|
+
refetchIntervalInBackground: queryOpts.refetchIntervalInBackground
|
|
365
367
|
}
|
|
366
368
|
});
|
|
367
369
|
}
|
|
368
370
|
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
371
|
return useMutationWithTransition({
|
|
372
372
|
mutationFn: ({ data, id, path }) => {
|
|
373
|
+
if (!api.upload) return Promise.reject(/* @__PURE__ */ new Error(`[arc-next] "${entityKey}" api does not define an upload method`));
|
|
373
374
|
const auth = getAuthContext();
|
|
374
|
-
return
|
|
375
|
+
return api.upload({
|
|
375
376
|
token: auth.token,
|
|
376
|
-
organizationId:
|
|
377
|
+
organizationId: auth.organizationId,
|
|
377
378
|
data,
|
|
378
379
|
id,
|
|
379
380
|
path
|
|
@@ -394,9 +395,9 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
394
395
|
if (!api.search) throw new Error(`[arc-next] "${entityKey}" api does not define a search method`);
|
|
395
396
|
const searchApi = api.search;
|
|
396
397
|
const auth = getAuthContext();
|
|
397
|
-
const token = auth.token;
|
|
398
|
-
const organizationId =
|
|
399
|
-
const { organizationId: _, ...restParams } = params ?? {};
|
|
398
|
+
const token = params?.token ?? auth.token;
|
|
399
|
+
const organizationId = params?.organizationId ?? auth.organizationId;
|
|
400
|
+
const { organizationId: _, token: _t, ...restParams } = params ?? {};
|
|
400
401
|
const searchParams = {
|
|
401
402
|
q: query,
|
|
402
403
|
...restParams
|
|
@@ -406,7 +407,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
406
407
|
organizationId,
|
|
407
408
|
...searchParams
|
|
408
409
|
} : searchParams;
|
|
409
|
-
return
|
|
410
|
+
return useListQuery({
|
|
410
411
|
queryKey: [
|
|
411
412
|
...KEYS.lists(),
|
|
412
413
|
"search",
|
|
@@ -421,7 +422,7 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
421
422
|
...requestOpts
|
|
422
423
|
}
|
|
423
424
|
}),
|
|
424
|
-
enabled: query.length > 0 && createEnabledRule(token, queryOpts),
|
|
425
|
+
enabled: query.length > 0 && createEnabledRule(token, queryOpts, resolveAuthMode()),
|
|
425
426
|
options: {
|
|
426
427
|
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
427
428
|
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
@@ -440,9 +441,13 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
440
441
|
toastHandler: instanceToast
|
|
441
442
|
});
|
|
442
443
|
}
|
|
444
|
+
const resolvedRouterHook = instanceNavigation ?? useRouterHook ?? (() => ({
|
|
445
|
+
push: () => {},
|
|
446
|
+
replace: () => {}
|
|
447
|
+
}));
|
|
443
448
|
function useNavigation() {
|
|
444
449
|
const queryClient = useQueryClient();
|
|
445
|
-
const router = (
|
|
450
|
+
const router = resolvedRouterHook();
|
|
446
451
|
return useCallback((href, item, options = {}) => {
|
|
447
452
|
const id = getItemId(item);
|
|
448
453
|
if (id) queryClient.setQueryData(KEYS.detail(id), { data: item });
|
|
@@ -467,5 +472,4 @@ function createCrudHooks({ api, entityKey, singular, platformScoped, defaults =
|
|
|
467
472
|
}
|
|
468
473
|
|
|
469
474
|
//#endregion
|
|
470
|
-
export { configureNavigation, createCrudHooks };
|
|
471
|
-
//# sourceMappingURL=hooks.js.map
|
|
475
|
+
export { configureNavigation, createCrudHooks };
|
package/dist/mutation.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ interface TransitionMutationReturn<TData, TVariables> {
|
|
|
26
26
|
/**
|
|
27
27
|
* Configure toast handler. Call once at app init.
|
|
28
28
|
*
|
|
29
|
+
* **SSR safety:** This sets module-level state. Call only in client-side code.
|
|
30
|
+
*
|
|
29
31
|
* @example
|
|
30
32
|
* import { toast } from "sonner";
|
|
31
33
|
* configureToast({ success: toast.success, error: toast.error });
|
|
@@ -98,7 +100,7 @@ interface CreateOptimisticMutationConfig<TData, TVariables> {
|
|
|
98
100
|
shouldToast?: () => boolean;
|
|
99
101
|
toastHandler?: ToastHandler;
|
|
100
102
|
}
|
|
101
|
-
declare function
|
|
103
|
+
declare function useOptimisticMutation<TData, TVariables>(config: CreateOptimisticMutationConfig<TData, TVariables>): _tanstack_react_query0.UseMutationResult<TData, Error, TVariables, {
|
|
102
104
|
previous: {
|
|
103
105
|
key: readonly unknown[];
|
|
104
106
|
data: [readonly unknown[], unknown][];
|
|
@@ -119,6 +121,7 @@ declare const QUERY_CONFIGS: {
|
|
|
119
121
|
readonly staleTime: 600000;
|
|
120
122
|
};
|
|
121
123
|
};
|
|
124
|
+
/** @deprecated Use `useOptimisticMutation` */
|
|
125
|
+
declare const createOptimisticMutation: typeof useOptimisticMutation;
|
|
122
126
|
//#endregion
|
|
123
|
-
export { CreateOptimisticMutationConfig, MutationCallbacks, MutationMessages, OptimisticMutationConfig, QUERY_CONFIGS,
|
|
124
|
-
//# sourceMappingURL=mutation.d.ts.map
|
|
127
|
+
export { CreateOptimisticMutationConfig, MutationCallbacks, MutationMessages, OptimisticMutationConfig, QUERY_CONFIGS, TransitionMutationConfig, TransitionMutationReturn, configureToast, createOptimisticMutation, useMutationWithOptimistic, useMutationWithTransition, useOptimisticMutation };
|
package/dist/mutation.js
CHANGED
|
@@ -12,6 +12,8 @@ let toastHandler = {
|
|
|
12
12
|
/**
|
|
13
13
|
* Configure toast handler. 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 { toast } from "sonner";
|
|
17
19
|
* configureToast({ success: toast.success, error: toast.error });
|
|
@@ -112,7 +114,7 @@ function useMutationWithOptimistic(config) {
|
|
|
112
114
|
reset: mutation.reset
|
|
113
115
|
};
|
|
114
116
|
}
|
|
115
|
-
function
|
|
117
|
+
function useOptimisticMutation(config) {
|
|
116
118
|
const { mutationFn, queryClient, queryKeys, optimisticUpdate, onSuccess, onError, onSettled, messages, toastHandler: instanceToast } = config;
|
|
117
119
|
return useMutation({
|
|
118
120
|
mutationFn,
|
|
@@ -158,7 +160,8 @@ const QUERY_CONFIGS = {
|
|
|
158
160
|
stable: { staleTime: 3e5 },
|
|
159
161
|
static: { staleTime: 6e5 }
|
|
160
162
|
};
|
|
163
|
+
/** @deprecated Use `useOptimisticMutation` */
|
|
164
|
+
const createOptimisticMutation = useOptimisticMutation;
|
|
161
165
|
|
|
162
166
|
//#endregion
|
|
163
|
-
export { QUERY_CONFIGS, configureToast, createOptimisticMutation, useMutationWithOptimistic, useMutationWithTransition };
|
|
164
|
-
//# sourceMappingURL=mutation.js.map
|
|
167
|
+
export { QUERY_CONFIGS, configureToast, createOptimisticMutation, useMutationWithOptimistic, useMutationWithTransition, useOptimisticMutation };
|
package/dist/prefetch.d.ts
CHANGED
|
@@ -4,6 +4,13 @@ import { QueryClient, dehydrate } from "@tanstack/react-query";
|
|
|
4
4
|
interface PrefetchOptions {
|
|
5
5
|
staleTime?: number;
|
|
6
6
|
}
|
|
7
|
+
interface PrefetchDetailOptions extends PrefetchOptions {
|
|
8
|
+
/** Query params (select, populate) — key must match useDetail's params to share cache */
|
|
9
|
+
params?: {
|
|
10
|
+
select?: string;
|
|
11
|
+
populate?: string | string[];
|
|
12
|
+
};
|
|
13
|
+
}
|
|
7
14
|
interface CrudPrefetcher {
|
|
8
15
|
/**
|
|
9
16
|
* Prefetch a list query on the server. Uses the same query keys as useList.
|
|
@@ -20,7 +27,7 @@ interface CrudPrefetcher {
|
|
|
20
27
|
* const queryClient = getQueryClient();
|
|
21
28
|
* await productsPrefetcher.prefetchDetail(queryClient, productId);
|
|
22
29
|
*/
|
|
23
|
-
prefetchDetail: (queryClient: QueryClient, id: string, options?:
|
|
30
|
+
prefetchDetail: (queryClient: QueryClient, id: string, options?: PrefetchDetailOptions) => Promise<void>;
|
|
24
31
|
}
|
|
25
32
|
/**
|
|
26
33
|
* Create server-safe prefetch helpers for CRUD queries.
|
|
@@ -60,5 +67,4 @@ declare function createCrudPrefetcher(api: {
|
|
|
60
67
|
}) => Promise<unknown>;
|
|
61
68
|
}, entityKey: string): CrudPrefetcher;
|
|
62
69
|
//#endregion
|
|
63
|
-
export { CrudPrefetcher, PrefetchOptions, createCrudPrefetcher, dehydrate };
|
|
64
|
-
//# sourceMappingURL=prefetch.d.ts.map
|
|
70
|
+
export { CrudPrefetcher, PrefetchDetailOptions, PrefetchOptions, createCrudPrefetcher, dehydrate };
|
package/dist/prefetch.js
CHANGED
|
@@ -61,16 +61,20 @@ function createCrudPrefetcher(api, entityKey) {
|
|
|
61
61
|
});
|
|
62
62
|
},
|
|
63
63
|
async prefetchDetail(queryClient, id, options = {}) {
|
|
64
|
-
const
|
|
64
|
+
const { params, staleTime } = options;
|
|
65
|
+
const baseKey = detailKey(entityKey, id);
|
|
66
|
+
const queryKey = params ? [...baseKey, params] : baseKey;
|
|
65
67
|
await queryClient.prefetchQuery({
|
|
66
68
|
queryKey,
|
|
67
|
-
queryFn: () => api.getById({
|
|
68
|
-
|
|
69
|
+
queryFn: () => api.getById({
|
|
70
|
+
id,
|
|
71
|
+
...params ? { params } : {}
|
|
72
|
+
}),
|
|
73
|
+
staleTime
|
|
69
74
|
});
|
|
70
75
|
}
|
|
71
76
|
};
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
//#endregion
|
|
75
|
-
export { createCrudPrefetcher, dehydrate };
|
|
76
|
-
//# sourceMappingURL=prefetch.js.map
|
|
80
|
+
export { createCrudPrefetcher, dehydrate };
|
package/dist/query-client.d.ts
CHANGED
|
@@ -21,5 +21,4 @@ interface QueryClientOverrides {
|
|
|
21
21
|
*/
|
|
22
22
|
declare function getQueryClient(overrides?: QueryClientOverrides): QueryClient;
|
|
23
23
|
//#endregion
|
|
24
|
-
export { QueryClientOverrides, getQueryClient };
|
|
25
|
-
//# sourceMappingURL=query-client.d.ts.map
|
|
24
|
+
export { QueryClientOverrides, getQueryClient };
|
package/dist/query-client.js
CHANGED
|
@@ -38,9 +38,9 @@ let browserQueryClient;
|
|
|
38
38
|
function getQueryClient(overrides) {
|
|
39
39
|
if (isServer) return makeQueryClient(overrides);
|
|
40
40
|
if (!browserQueryClient) browserQueryClient = makeQueryClient(overrides);
|
|
41
|
+
else if (overrides) console.warn("[arc-next] getQueryClient(): Browser singleton already exists — overrides are ignored. Pass overrides only on the first call.");
|
|
41
42
|
return browserQueryClient;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
//#endregion
|
|
45
|
-
export { getQueryClient };
|
|
46
|
-
//# sourceMappingURL=query-client.js.map
|
|
46
|
+
export { getQueryClient };
|
package/dist/query.d.ts
CHANGED
|
@@ -2,12 +2,16 @@ import { InfiniteData, QueryClient, QueryKey } from "@tanstack/react-query";
|
|
|
2
2
|
|
|
3
3
|
//#region src/query.d.ts
|
|
4
4
|
interface PaginationData {
|
|
5
|
+
/** Pagination method detected from response (offset | keyset | aggregate) */
|
|
6
|
+
method: 'offset' | 'keyset' | 'aggregate' | null;
|
|
5
7
|
total: number;
|
|
6
8
|
pages: number;
|
|
7
9
|
page: number;
|
|
8
10
|
limit: number;
|
|
9
11
|
hasNext: boolean;
|
|
10
12
|
hasPrev: boolean;
|
|
13
|
+
/** Keyset cursor for next page (keyset pagination only) */
|
|
14
|
+
next?: string | null;
|
|
11
15
|
}
|
|
12
16
|
/** Request-level options passed through to the fetch call */
|
|
13
17
|
interface RequestPassthrough {
|
|
@@ -39,6 +43,7 @@ interface DetailQueryOptions<TData = unknown> {
|
|
|
39
43
|
enabled?: boolean;
|
|
40
44
|
staleTime?: number;
|
|
41
45
|
gcTime?: number;
|
|
46
|
+
refetchOnWindowFocus?: boolean;
|
|
42
47
|
structuralSharing?: boolean;
|
|
43
48
|
refetchInterval?: number | false;
|
|
44
49
|
refetchIntervalInBackground?: boolean;
|
|
@@ -99,6 +104,7 @@ declare const DEFAULT_QUERY_CONFIG: {
|
|
|
99
104
|
readonly retry: 0;
|
|
100
105
|
};
|
|
101
106
|
declare function getItemId(item: unknown): string | null;
|
|
107
|
+
declare function extractItem<T>(data: unknown): T | null;
|
|
102
108
|
declare function updateListCache<T>(listData: unknown, updater: (items: T[]) => T[]): unknown;
|
|
103
109
|
declare function createQueryKeys(entityKey: string): QueryKeys;
|
|
104
110
|
declare function createCacheUtils<T>(KEYS: QueryKeys): CacheUtils<T>;
|
|
@@ -113,7 +119,7 @@ interface CreateListQueryConfig {
|
|
|
113
119
|
detailKeyBuilder?: (id: string) => QueryKey;
|
|
114
120
|
select?: (data: unknown) => unknown;
|
|
115
121
|
}
|
|
116
|
-
declare function
|
|
122
|
+
declare function useListQuery<T>({
|
|
117
123
|
queryKey,
|
|
118
124
|
queryFn,
|
|
119
125
|
enabled,
|
|
@@ -131,7 +137,7 @@ interface CreateDetailQueryConfig {
|
|
|
131
137
|
options?: Record<string, unknown>;
|
|
132
138
|
select?: (data: unknown) => unknown;
|
|
133
139
|
}
|
|
134
|
-
declare function
|
|
140
|
+
declare function useDetailQuery<T>({
|
|
135
141
|
queryKey,
|
|
136
142
|
queryFn,
|
|
137
143
|
enabled,
|
|
@@ -145,6 +151,8 @@ interface InfiniteListQueryOptions {
|
|
|
145
151
|
gcTime?: number;
|
|
146
152
|
refetchOnWindowFocus?: boolean;
|
|
147
153
|
structuralSharing?: boolean;
|
|
154
|
+
refetchInterval?: number | false;
|
|
155
|
+
refetchIntervalInBackground?: boolean;
|
|
148
156
|
_scope?: string;
|
|
149
157
|
request?: RequestPassthrough;
|
|
150
158
|
}
|
|
@@ -176,7 +184,7 @@ interface CreateInfiniteListQueryConfig {
|
|
|
176
184
|
getNextPageParam: (lastPage: unknown) => unknown;
|
|
177
185
|
getPreviousPageParam?: (firstPage: unknown) => unknown;
|
|
178
186
|
}
|
|
179
|
-
declare function
|
|
187
|
+
declare function useInfiniteListQuery<T>({
|
|
180
188
|
queryKey,
|
|
181
189
|
queryFn,
|
|
182
190
|
enabled,
|
|
@@ -185,6 +193,11 @@ declare function createInfiniteListQuery<T>({
|
|
|
185
193
|
getNextPageParam,
|
|
186
194
|
getPreviousPageParam
|
|
187
195
|
}: CreateInfiniteListQueryConfig): InfiniteListQueryResult<T>;
|
|
196
|
+
/** @deprecated Use `useListQuery` */
|
|
197
|
+
declare const createListQuery: typeof useListQuery;
|
|
198
|
+
/** @deprecated Use `useDetailQuery` */
|
|
199
|
+
declare const createDetailQuery: typeof useDetailQuery;
|
|
200
|
+
/** @deprecated Use `useInfiniteListQuery` */
|
|
201
|
+
declare const createInfiniteListQuery: typeof useInfiniteListQuery;
|
|
188
202
|
//#endregion
|
|
189
|
-
export { CacheUtils, CreateDetailQueryConfig, CreateInfiniteListQueryConfig, CreateListQueryConfig, DEFAULT_QUERY_CONFIG, DetailQueryOptions, DetailQueryResult, InfiniteListQueryOptions, InfiniteListQueryResult, ListQueryOptions, ListQueryResult, PaginationData, QueryKeys, RequestPassthrough, createCacheUtils, createDetailQuery, createInfiniteListQuery, createListQuery, createQueryKeys, getItemId, updateListCache };
|
|
190
|
-
//# sourceMappingURL=query.d.ts.map
|
|
203
|
+
export { CacheUtils, CreateDetailQueryConfig, CreateInfiniteListQueryConfig, CreateListQueryConfig, DEFAULT_QUERY_CONFIG, DetailQueryOptions, DetailQueryResult, InfiniteListQueryOptions, InfiniteListQueryResult, ListQueryOptions, ListQueryResult, PaginationData, QueryKeys, RequestPassthrough, createCacheUtils, createDetailQuery, createInfiniteListQuery, createListQuery, createQueryKeys, extractItem, getItemId, updateListCache, useDetailQuery, useInfiniteListQuery, useListQuery };
|