@classytic/arc-next 0.2.0 → 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/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, createDetailQuery, createInfiniteListQuery, createListQuery, createQueryKeys, getItemId, updateListCache } from "./query.js";
6
- import { createOptimisticMutation, useMutationWithTransition } from "./mutation.js";
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,8 +21,8 @@ let useRouterHook = null;
19
21
  function configureNavigation(hook) {
20
22
  useRouterHook = hook;
21
23
  }
22
- function createEnabledRule(token, options) {
23
- if (getAuthMode() === "cookie" || options.public) return options.enabled ?? true;
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
28
  function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks = {}, client }) {
@@ -28,6 +30,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
28
30
  const cache = createCacheUtils(KEYS);
29
31
  const instanceToast = client?.toast;
30
32
  const instanceNavigation = client?.navigation ?? null;
33
+ const resolveAuthMode = () => client?.config?.authMode ?? getAuthMode();
31
34
  const config = {
32
35
  ...DEFAULT_QUERY_CONFIG,
33
36
  ...defaults,
@@ -63,7 +66,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
63
66
  const { organizationId, ...restParams } = params;
64
67
  const scope = options._scope || (organizationId ? "tenant" : "super-admin");
65
68
  const { request: requestOpts, ...queryOpts } = options;
66
- return createListQuery({
69
+ return useListQuery({
67
70
  queryKey: KEYS.scopedList(scope, {
68
71
  organizationId,
69
72
  ...restParams
@@ -77,7 +80,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
77
80
  ...requestOpts
78
81
  }
79
82
  }),
80
- enabled: createEnabledRule(token, queryOpts),
83
+ enabled: createEnabledRule(token, queryOpts, resolveAuthMode()),
81
84
  options: {
82
85
  staleTime: queryOpts.staleTime ?? config.staleTime,
83
86
  gcTime: queryOpts.gcTime ?? config.gcTime,
@@ -107,7 +110,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
107
110
  };
108
111
  }
109
112
  const { organizationId, params: queryParams, request: requestOpts, ...restOptions } = options;
110
- return createDetailQuery({
113
+ return useDetailQuery({
111
114
  queryKey: queryParams ? [...KEYS.detail(id || ""), queryParams] : KEYS.detail(id || ""),
112
115
  queryFn: ({ signal }) => api.getById({
113
116
  id,
@@ -119,10 +122,11 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
119
122
  ...requestOpts
120
123
  }
121
124
  }),
122
- enabled: !!id && createEnabledRule(token, restOptions),
125
+ enabled: !!id && createEnabledRule(token, restOptions, resolveAuthMode()),
123
126
  options: {
124
127
  staleTime: restOptions.staleTime ?? config.staleTime,
125
128
  gcTime: restOptions.gcTime ?? config.gcTime,
129
+ refetchOnWindowFocus: restOptions.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
126
130
  structuralSharing: restOptions.structuralSharing ?? config.structuralSharing,
127
131
  refetchInterval: restOptions.refetchInterval,
128
132
  refetchIntervalInBackground: restOptions.refetchIntervalInBackground
@@ -134,7 +138,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
134
138
  const queryClient = useQueryClient();
135
139
  const silentRef = useRef(false);
136
140
  const shouldToast = useCallback(() => !silentRef.current, []);
137
- const createMutation = createOptimisticMutation({
141
+ const createMutation = useOptimisticMutation({
138
142
  mutationFn: ({ token, organizationId, data }) => api.create({
139
143
  token,
140
144
  organizationId,
@@ -151,14 +155,14 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
151
155
  };
152
156
  return updateListCache(oldData, (arr) => [optimisticItem, ...arr || []]);
153
157
  },
154
- onSuccess: (data, variables) => {
155
- callbacks.onCreate?.onSuccess?.(data, { data: variables.data }, void 0);
158
+ onSuccess: (raw, variables) => {
159
+ callbacks.onCreate?.onSuccess?.(extractItem(raw), { data: variables.data }, void 0);
156
160
  },
157
161
  onError: (error, variables) => {
158
162
  callbacks.onCreate?.onError?.(error, { data: variables.data }, void 0);
159
163
  },
160
- onSettled: (data, error, variables) => {
161
- callbacks.onCreate?.onSettled?.(data, error, { data: variables.data }, void 0);
164
+ onSettled: (raw, error, variables) => {
165
+ callbacks.onCreate?.onSettled?.(raw ? extractItem(raw) : void 0, error, { data: variables.data }, void 0);
162
166
  },
163
167
  messages: {
164
168
  success: config.messages.createSuccess,
@@ -166,7 +170,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
166
170
  },
167
171
  toastHandler: instanceToast
168
172
  });
169
- const updateMutation = createOptimisticMutation({
173
+ const updateMutation = useOptimisticMutation({
170
174
  mutationFn: ({ token, organizationId, id, data }) => api.update({
171
175
  token,
172
176
  organizationId,
@@ -174,7 +178,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
174
178
  data
175
179
  }),
176
180
  queryClient,
177
- queryKeys: [KEYS.lists()],
181
+ queryKeys: [KEYS.lists(), KEYS.details()],
178
182
  shouldToast,
179
183
  optimisticUpdate: (oldData, { id, data }) => {
180
184
  const updated = updateListCache(oldData, (arr) => (arr || []).map((item) => getItemId(item) === id ? {
@@ -190,9 +194,9 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
190
194
  } : current);
191
195
  return updated;
192
196
  },
193
- onSuccess: (data, { id, data: updateData }) => {
197
+ onSuccess: (raw, { id, data: updateData }) => {
194
198
  queryClient.invalidateQueries({ queryKey: KEYS.detail(id) });
195
- callbacks.onUpdate?.onSuccess?.(data, {
199
+ callbacks.onUpdate?.onSuccess?.(extractItem(raw), {
196
200
  id,
197
201
  data: updateData
198
202
  }, void 0);
@@ -203,8 +207,8 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
203
207
  data
204
208
  }, void 0);
205
209
  },
206
- onSettled: (data, error, { id, data: updateData }) => {
207
- callbacks.onUpdate?.onSettled?.(data, error, {
210
+ onSettled: (raw, error, { id, data: updateData }) => {
211
+ callbacks.onUpdate?.onSettled?.(raw ? extractItem(raw) : void 0, error, {
208
212
  id,
209
213
  data: updateData
210
214
  }, void 0);
@@ -215,7 +219,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
215
219
  },
216
220
  toastHandler: instanceToast
217
221
  });
218
- const deleteMutation = createOptimisticMutation({
222
+ const deleteMutation = useOptimisticMutation({
219
223
  mutationFn: ({ token, organizationId, id }) => api.delete({
220
224
  token,
221
225
  organizationId,
@@ -225,10 +229,10 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
225
229
  queryKeys: [KEYS.lists()],
226
230
  shouldToast,
227
231
  optimisticUpdate: (oldData, { id }) => {
228
- queryClient.removeQueries({ queryKey: KEYS.detail(id) });
229
232
  return updateListCache(oldData, (arr) => (arr || []).filter((item) => getItemId(item) !== id));
230
233
  },
231
234
  onSuccess: (data, { id }) => {
235
+ queryClient.removeQueries({ queryKey: KEYS.detail(id) });
232
236
  callbacks.onDelete?.onSuccess?.(data, { id }, void 0);
233
237
  },
234
238
  onError: (error, { id }) => {
@@ -243,63 +247,60 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
243
247
  },
244
248
  toastHandler: instanceToast
245
249
  });
246
- const resolveAuth = (params) => {
250
+ const resolveAuth = useCallback((params) => {
247
251
  const auth = getAuthContext();
248
252
  return {
249
253
  ...params,
250
254
  token: params.token ?? auth.token,
251
255
  organizationId: params.organizationId ?? auth.organizationId
252
256
  };
253
- };
254
- const create = async (params, options) => {
255
- silentRef.current = options?.silent ?? false;
256
- try {
257
- const result = await createMutation.mutateAsync(resolveAuth(params));
258
- options?.onSuccess?.(result);
259
- options?.onSettled?.(result, null);
260
- return result;
261
- } catch (error) {
262
- options?.onError?.(error);
263
- options?.onSettled?.(void 0, error);
264
- throw error;
265
- } finally {
266
- silentRef.current = false;
267
- }
268
- };
269
- const update = async (params, options) => {
270
- silentRef.current = options?.silent ?? false;
271
- try {
272
- const result = await updateMutation.mutateAsync(resolveAuth(params));
273
- options?.onSuccess?.(result);
274
- options?.onSettled?.(result, null);
275
- return result;
276
- } catch (error) {
277
- options?.onError?.(error);
278
- options?.onSettled?.(void 0, error);
279
- throw error;
280
- } finally {
281
- silentRef.current = false;
282
- }
283
- };
284
- const remove = async (params, options) => {
285
- silentRef.current = options?.silent ?? false;
286
- try {
287
- const result = await deleteMutation.mutateAsync(resolveAuth(params));
288
- options?.onSuccess?.(result);
289
- options?.onSettled?.(result, null);
290
- return result;
291
- } catch (error) {
292
- options?.onError?.(error);
293
- options?.onSettled?.(void 0, error);
294
- throw error;
295
- } finally {
296
- silentRef.current = false;
297
- }
298
- };
257
+ }, []);
299
258
  return {
300
- create,
301
- update,
302
- remove,
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]),
303
304
  isCreating: createMutation.isPending,
304
305
  isUpdating: updateMutation.isPending,
305
306
  isDeleting: deleteMutation.isPending,
@@ -327,7 +328,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
327
328
  const { organizationId, ...restParams } = params;
328
329
  const scope = options._scope || (organizationId ? "tenant" : "super-admin");
329
330
  const { request: requestOpts, ...queryOpts } = options;
330
- return createInfiniteListQuery({
331
+ return useInfiniteListQuery({
331
332
  queryKey: [...KEYS.scopedList(scope, {
332
333
  organizationId,
333
334
  ...restParams
@@ -347,7 +348,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
347
348
  }
348
349
  });
349
350
  },
350
- enabled: createEnabledRule(token, queryOpts),
351
+ enabled: createEnabledRule(token, queryOpts, resolveAuthMode()),
351
352
  initialPageParam: restParams.after ? restParams.after : 1,
352
353
  getNextPageParam: (lastPage) => {
353
354
  const page = lastPage;
@@ -360,17 +361,18 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
360
361
  staleTime: queryOpts.staleTime ?? config.staleTime,
361
362
  gcTime: queryOpts.gcTime ?? config.gcTime,
362
363
  refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
363
- structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing
364
+ structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing,
365
+ refetchInterval: queryOpts.refetchInterval,
366
+ refetchIntervalInBackground: queryOpts.refetchIntervalInBackground
364
367
  }
365
368
  });
366
369
  }
367
370
  function useUpload(options) {
368
- if (!api.upload) throw new Error(`[arc-next] "${entityKey}" api does not define an upload method`);
369
- const uploadApi = api.upload;
370
371
  return useMutationWithTransition({
371
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`));
372
374
  const auth = getAuthContext();
373
- return uploadApi({
375
+ return api.upload({
374
376
  token: auth.token,
375
377
  organizationId: auth.organizationId,
376
378
  data,
@@ -393,9 +395,9 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
393
395
  if (!api.search) throw new Error(`[arc-next] "${entityKey}" api does not define a search method`);
394
396
  const searchApi = api.search;
395
397
  const auth = getAuthContext();
396
- const token = auth.token;
398
+ const token = params?.token ?? auth.token;
397
399
  const organizationId = params?.organizationId ?? auth.organizationId;
398
- const { organizationId: _, ...restParams } = params ?? {};
400
+ const { organizationId: _, token: _t, ...restParams } = params ?? {};
399
401
  const searchParams = {
400
402
  q: query,
401
403
  ...restParams
@@ -405,7 +407,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
405
407
  organizationId,
406
408
  ...searchParams
407
409
  } : searchParams;
408
- return createListQuery({
410
+ return useListQuery({
409
411
  queryKey: [
410
412
  ...KEYS.lists(),
411
413
  "search",
@@ -420,7 +422,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
420
422
  ...requestOpts
421
423
  }
422
424
  }),
423
- enabled: query.length > 0 && createEnabledRule(token, queryOpts),
425
+ enabled: query.length > 0 && createEnabledRule(token, queryOpts, resolveAuthMode()),
424
426
  options: {
425
427
  staleTime: queryOpts.staleTime ?? config.staleTime,
426
428
  gcTime: queryOpts.gcTime ?? config.gcTime
@@ -439,9 +441,13 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
439
441
  toastHandler: instanceToast
440
442
  });
441
443
  }
444
+ const resolvedRouterHook = instanceNavigation ?? useRouterHook ?? (() => ({
445
+ push: () => {},
446
+ replace: () => {}
447
+ }));
442
448
  function useNavigation() {
443
449
  const queryClient = useQueryClient();
444
- const router = (instanceNavigation ?? useRouterHook)?.();
450
+ const router = resolvedRouterHook();
445
451
  return useCallback((href, item, options = {}) => {
446
452
  const id = getItemId(item);
447
453
  if (id) queryClient.setQueryData(KEYS.detail(id), { data: item });
@@ -466,5 +472,4 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
466
472
  }
467
473
 
468
474
  //#endregion
469
- export { configureNavigation, createCrudHooks };
470
- //# sourceMappingURL=hooks.js.map
475
+ export { configureNavigation, createCrudHooks };
@@ -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 createOptimisticMutation<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, {
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, type ToastHandler, TransitionMutationConfig, TransitionMutationReturn, configureToast, createOptimisticMutation, useMutationWithOptimistic, useMutationWithTransition };
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 createOptimisticMutation(config) {
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 };
@@ -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?: PrefetchOptions) => Promise<void>;
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 queryKey = detailKey(entityKey, id);
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({ id }),
68
- staleTime: options.staleTime
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 };
@@ -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 };
@@ -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 createListQuery<T>({
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 createDetailQuery<T>({
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 createInfiniteListQuery<T>({
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 };