@classytic/arc-next 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hooks.js ADDED
@@ -0,0 +1,357 @@
1
+ "use client";
2
+
3
+ import { getAuthContext, getAuthMode } from "./client.js";
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 } from "./mutation.js";
7
+ import { useQueryClient } from "@tanstack/react-query";
8
+ import { useCallback } from "react";
9
+
10
+ //#region src/hooks.ts
11
+ let useRouterHook = null;
12
+ /**
13
+ * Configure the router hook for useNavigation. Call once at app init.
14
+ *
15
+ * @example
16
+ * import { useRouter } from "next/navigation";
17
+ * configureNavigation(useRouter);
18
+ */
19
+ function configureNavigation(hook) {
20
+ useRouterHook = hook;
21
+ }
22
+ function createEnabledRule(token, options) {
23
+ if (getAuthMode() === "cookie" || options.public) return options.enabled ?? true;
24
+ return options.enabled !== void 0 ? options.enabled && !!token : !!token;
25
+ }
26
+ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks = {}, client }) {
27
+ const KEYS = createQueryKeys(entityKey);
28
+ const cache = createCacheUtils(KEYS);
29
+ const instanceToast = client?.toast;
30
+ const instanceNavigation = client?.navigation ?? null;
31
+ const config = {
32
+ ...DEFAULT_QUERY_CONFIG,
33
+ ...defaults,
34
+ structuralSharing: defaults.structuralSharing,
35
+ messages: {
36
+ createSuccess: `${singular} created successfully`,
37
+ createError: `Failed to create ${singular.toLowerCase()}`,
38
+ updateSuccess: `${singular} updated successfully`,
39
+ updateError: `Failed to update ${singular.toLowerCase()}`,
40
+ deleteSuccess: `${singular} deleted successfully`,
41
+ deleteError: `Failed to delete ${singular.toLowerCase()}`,
42
+ ...defaults.messages
43
+ }
44
+ };
45
+ function useList(tokenOrParams, paramsOrOptions, maybeOptions) {
46
+ let token;
47
+ let params;
48
+ let options;
49
+ if (tokenOrParams === null || typeof tokenOrParams === "string") {
50
+ token = tokenOrParams;
51
+ params = paramsOrOptions ?? {};
52
+ options = maybeOptions ?? {};
53
+ } else {
54
+ const auth = getAuthContext();
55
+ token = auth.token;
56
+ params = tokenOrParams ?? {};
57
+ options = paramsOrOptions ?? {};
58
+ if (auth.organizationId && !params.organizationId) params = {
59
+ ...params,
60
+ organizationId: auth.organizationId
61
+ };
62
+ }
63
+ const { organizationId, ...restParams } = params;
64
+ const scope = options._scope || (organizationId ? "tenant" : "super-admin");
65
+ const { request: requestOpts, ...queryOpts } = options;
66
+ return createListQuery({
67
+ queryKey: KEYS.scopedList(scope, {
68
+ organizationId,
69
+ ...restParams
70
+ }),
71
+ queryFn: ({ signal }) => api.getAll({
72
+ token,
73
+ organizationId,
74
+ params: restParams,
75
+ options: {
76
+ signal,
77
+ ...requestOpts
78
+ }
79
+ }),
80
+ enabled: createEnabledRule(token, queryOpts),
81
+ options: {
82
+ staleTime: queryOpts.staleTime ?? config.staleTime,
83
+ gcTime: queryOpts.gcTime ?? config.gcTime,
84
+ refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
85
+ structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing,
86
+ refetchInterval: queryOpts.refetchInterval,
87
+ refetchIntervalInBackground: queryOpts.refetchIntervalInBackground
88
+ },
89
+ prefillDetailCache: queryOpts.prefillDetailCache ?? true,
90
+ detailKeyBuilder: (id) => KEYS.detail(id)
91
+ });
92
+ }
93
+ function useDetail(id, tokenOrOptions, maybeOptions) {
94
+ let token;
95
+ let options;
96
+ if (tokenOrOptions === null || typeof tokenOrOptions === "string") {
97
+ token = tokenOrOptions;
98
+ options = maybeOptions ?? {};
99
+ } else {
100
+ const auth = getAuthContext();
101
+ token = auth.token;
102
+ options = tokenOrOptions ?? {};
103
+ if (auth.organizationId && !options.organizationId) options = {
104
+ ...options,
105
+ organizationId: auth.organizationId
106
+ };
107
+ }
108
+ const { organizationId, request: requestOpts, ...restOptions } = options;
109
+ return createDetailQuery({
110
+ queryKey: KEYS.detail(id || ""),
111
+ queryFn: ({ signal }) => api.getById({
112
+ id,
113
+ token,
114
+ organizationId,
115
+ options: {
116
+ signal,
117
+ ...requestOpts
118
+ }
119
+ }),
120
+ enabled: !!id && createEnabledRule(token, restOptions),
121
+ options: {
122
+ staleTime: restOptions.staleTime ?? config.staleTime,
123
+ gcTime: restOptions.gcTime ?? config.gcTime,
124
+ structuralSharing: restOptions.structuralSharing ?? config.structuralSharing,
125
+ refetchInterval: restOptions.refetchInterval,
126
+ refetchIntervalInBackground: restOptions.refetchIntervalInBackground
127
+ }
128
+ });
129
+ }
130
+ function useActions() {
131
+ const queryClient = useQueryClient();
132
+ const createMutation = createOptimisticMutation({
133
+ mutationFn: ({ token, organizationId, data }) => api.create({
134
+ token,
135
+ organizationId,
136
+ data
137
+ }),
138
+ queryClient,
139
+ queryKeys: [KEYS.lists()],
140
+ optimisticUpdate: (oldData, { data }) => {
141
+ const optimisticItem = {
142
+ ...data,
143
+ _optimistic: true,
144
+ [getItemId(data) ? "id" : "_id"]: getItemId(data) ?? `temp-${Date.now()}`
145
+ };
146
+ return updateListCache(oldData, (arr) => [optimisticItem, ...arr || []]);
147
+ },
148
+ onSuccess: (data, variables) => {
149
+ callbacks.onCreate?.onSuccess?.(data, { data: variables.data }, void 0);
150
+ },
151
+ onError: (error, variables) => {
152
+ callbacks.onCreate?.onError?.(error, { data: variables.data }, void 0);
153
+ },
154
+ messages: {
155
+ success: config.messages.createSuccess,
156
+ error: config.messages.createError
157
+ },
158
+ toastHandler: instanceToast
159
+ });
160
+ const updateMutation = createOptimisticMutation({
161
+ mutationFn: ({ token, organizationId, id, data }) => api.update({
162
+ token,
163
+ organizationId,
164
+ id,
165
+ data
166
+ }),
167
+ queryClient,
168
+ queryKeys: [KEYS.lists()],
169
+ optimisticUpdate: (oldData, { id, data }) => {
170
+ const updated = updateListCache(oldData, (arr) => (arr || []).map((item) => getItemId(item) === id ? {
171
+ ...item,
172
+ ...data
173
+ } : item));
174
+ queryClient.setQueryData(KEYS.detail(id), (current) => current ? {
175
+ ...current,
176
+ data: {
177
+ ...current.data || {},
178
+ ...data
179
+ }
180
+ } : current);
181
+ return updated;
182
+ },
183
+ onSuccess: (data, { id }) => {
184
+ queryClient.invalidateQueries({ queryKey: KEYS.detail(id) });
185
+ callbacks.onUpdate?.onSuccess?.(data, {
186
+ id,
187
+ data: {}
188
+ }, void 0);
189
+ },
190
+ onError: (error, { id, data }) => {
191
+ callbacks.onUpdate?.onError?.(error, {
192
+ id,
193
+ data
194
+ }, void 0);
195
+ },
196
+ messages: {
197
+ success: config.messages.updateSuccess,
198
+ error: config.messages.updateError
199
+ },
200
+ toastHandler: instanceToast
201
+ });
202
+ const deleteMutation = createOptimisticMutation({
203
+ mutationFn: ({ token, organizationId, id }) => api.delete({
204
+ token,
205
+ organizationId,
206
+ id
207
+ }),
208
+ queryClient,
209
+ queryKeys: [KEYS.lists()],
210
+ optimisticUpdate: (oldData, { id }) => {
211
+ queryClient.removeQueries({ queryKey: KEYS.detail(id) });
212
+ return updateListCache(oldData, (arr) => (arr || []).filter((item) => getItemId(item) !== id));
213
+ },
214
+ onSuccess: (data, { id }) => {
215
+ callbacks.onDelete?.onSuccess?.(data, { id }, void 0);
216
+ },
217
+ onError: (error, { id }) => {
218
+ callbacks.onDelete?.onError?.(error, { id }, void 0);
219
+ },
220
+ messages: {
221
+ success: config.messages.deleteSuccess,
222
+ error: config.messages.deleteError
223
+ },
224
+ toastHandler: instanceToast
225
+ });
226
+ const resolveAuth = (params) => {
227
+ const auth = getAuthContext();
228
+ return {
229
+ ...params,
230
+ token: params.token ?? auth.token,
231
+ organizationId: params.organizationId ?? auth.organizationId
232
+ };
233
+ };
234
+ const create = async (params, options) => {
235
+ try {
236
+ const result = await createMutation.mutateAsync(resolveAuth(params));
237
+ options?.onSuccess?.(result);
238
+ return result;
239
+ } catch (error) {
240
+ options?.onError?.(error);
241
+ throw error;
242
+ }
243
+ };
244
+ const update = async (params, options) => {
245
+ try {
246
+ const result = await updateMutation.mutateAsync(resolveAuth(params));
247
+ options?.onSuccess?.(result);
248
+ return result;
249
+ } catch (error) {
250
+ options?.onError?.(error);
251
+ throw error;
252
+ }
253
+ };
254
+ const remove = async (params, options) => {
255
+ try {
256
+ const result = await deleteMutation.mutateAsync(resolveAuth(params));
257
+ options?.onSuccess?.(result);
258
+ return result;
259
+ } catch (error) {
260
+ options?.onError?.(error);
261
+ throw error;
262
+ }
263
+ };
264
+ return {
265
+ create,
266
+ update,
267
+ remove,
268
+ isCreating: createMutation.isPending,
269
+ isUpdating: updateMutation.isPending,
270
+ isDeleting: deleteMutation.isPending,
271
+ isMutating: createMutation.isPending || updateMutation.isPending || deleteMutation.isPending
272
+ };
273
+ }
274
+ function useInfiniteList(tokenOrParams, paramsOrOptions, maybeOptions) {
275
+ let token;
276
+ let params;
277
+ let options;
278
+ if (tokenOrParams === null || typeof tokenOrParams === "string") {
279
+ token = tokenOrParams;
280
+ params = paramsOrOptions ?? {};
281
+ options = maybeOptions ?? {};
282
+ } else {
283
+ const auth = getAuthContext();
284
+ token = auth.token;
285
+ params = tokenOrParams ?? {};
286
+ options = paramsOrOptions ?? {};
287
+ if (auth.organizationId && !params.organizationId) params = {
288
+ ...params,
289
+ organizationId: auth.organizationId
290
+ };
291
+ }
292
+ const { organizationId, ...restParams } = params;
293
+ const scope = options._scope || (organizationId ? "tenant" : "super-admin");
294
+ const { request: requestOpts, ...queryOpts } = options;
295
+ return createInfiniteListQuery({
296
+ queryKey: [...KEYS.scopedList(scope, {
297
+ organizationId,
298
+ ...restParams
299
+ }), "infinite"],
300
+ queryFn: ({ signal, pageParam }) => {
301
+ const paginationParams = typeof pageParam === "string" ? { after: pageParam } : { page: pageParam };
302
+ return api.getAll({
303
+ token,
304
+ organizationId,
305
+ params: {
306
+ ...restParams,
307
+ ...paginationParams
308
+ },
309
+ options: {
310
+ signal,
311
+ ...requestOpts
312
+ }
313
+ });
314
+ },
315
+ enabled: createEnabledRule(token, queryOpts),
316
+ initialPageParam: restParams.after ? restParams.after : 1,
317
+ getNextPageParam: (lastPage) => {
318
+ const page = lastPage;
319
+ if (isKeysetPagination(page)) return page.hasMore ? page.next : void 0;
320
+ if (isOffsetPagination(page)) return page.hasNext ? page.page + 1 : void 0;
321
+ const p = page;
322
+ if (typeof p.hasNext === "boolean" && typeof p.page === "number") return p.hasNext ? p.page + 1 : void 0;
323
+ },
324
+ options: {
325
+ staleTime: queryOpts.staleTime ?? config.staleTime,
326
+ gcTime: queryOpts.gcTime ?? config.gcTime,
327
+ refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,
328
+ structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing
329
+ }
330
+ });
331
+ }
332
+ function useNavigation() {
333
+ const queryClient = useQueryClient();
334
+ const router = (instanceNavigation ?? useRouterHook)?.();
335
+ return useCallback((href, item, options = {}) => {
336
+ const id = getItemId(item);
337
+ if (id) queryClient.setQueryData(KEYS.detail(id), { data: item });
338
+ if (!router) return;
339
+ const { scroll = true, replace = false } = options;
340
+ if (replace) router.replace(href, { scroll });
341
+ else router.push(href, { scroll });
342
+ }, [queryClient, router]);
343
+ }
344
+ return {
345
+ KEYS,
346
+ cache,
347
+ useList,
348
+ useDetail,
349
+ useInfiniteList,
350
+ useActions,
351
+ useNavigation
352
+ };
353
+ }
354
+
355
+ //#endregion
356
+ export { configureNavigation, createCrudHooks };
357
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["\"use client\";\n\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { useCallback } from \"react\";\nimport { createOptimisticMutation } from \"./mutation.js\";\nimport {\n createListQuery,\n createDetailQuery,\n createInfiniteListQuery,\n updateListCache,\n getItemId,\n createQueryKeys,\n createCacheUtils,\n DEFAULT_QUERY_CONFIG,\n} from \"./query.js\";\nimport type {\n QueryKeys,\n CacheUtils,\n ListQueryOptions,\n DetailQueryOptions,\n ListQueryResult,\n DetailQueryResult,\n InfiniteListQueryOptions,\n InfiniteListQueryResult,\n} from \"./query.js\";\nimport {\n isOffsetPagination,\n isKeysetPagination,\n} from \"./api.js\";\nimport type { PaginatedResponse } from \"./api.js\";\nimport type { MutationCallbacks } from \"./mutation.js\";\nimport { getAuthMode, getAuthContext } from \"./client.js\";\nimport type { ArcClient, ToastHandler, UseRouterHook } from \"./client.js\";\n\n// Re-export UseRouterHook for backward compatibility\nexport type { UseRouterHook } from \"./client.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CrudApi<T, TCreate = Partial<T>, TUpdate = Partial<T>> {\n getAll: (options: {\n token?: string | null;\n organizationId?: string | null;\n params?: Record<string, unknown>;\n options?: { signal?: AbortSignal; [key: string]: unknown };\n }) => Promise<unknown>;\n\n getById: (options: {\n id: string;\n token?: string | null;\n organizationId?: string | null;\n options?: { signal?: AbortSignal; [key: string]: unknown };\n }) => Promise<unknown>;\n\n create: (options: {\n token?: string | null;\n organizationId?: string | null;\n data: TCreate;\n }) => Promise<unknown>;\n\n update: (options: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n data: TUpdate;\n }) => Promise<unknown>;\n\n delete: (options: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n }) => Promise<unknown>;\n}\n\nexport interface CrudHooksConfig<T, TCreate = Partial<T>, TUpdate = Partial<T>> {\n api: CrudApi<T, TCreate, TUpdate>;\n entityKey: string;\n singular: string;\n plural?: string;\n defaults?: {\n staleTime?: number;\n gcTime?: number;\n refetchOnWindowFocus?: boolean;\n structuralSharing?: boolean;\n messages?: {\n createSuccess?: string;\n createError?: string;\n updateSuccess?: string;\n updateError?: string;\n deleteSuccess?: string;\n deleteError?: string;\n };\n };\n callbacks?: {\n onCreate?: MutationCallbacks<T, { data: TCreate }>;\n onUpdate?: MutationCallbacks<T, { id: string; data: TUpdate }>;\n onDelete?: MutationCallbacks<unknown, { id: string }>;\n };\n client?: ArcClient;\n}\n\nexport interface MutationParams<TData> {\n token?: string | null;\n organizationId?: string | null;\n data: TData;\n}\n\nexport interface UpdateParams<TData> extends MutationParams<TData> {\n id: string;\n}\n\nexport interface DeleteParams {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n}\n\nexport interface CallOptions<TData = unknown> {\n onSuccess?: (data: TData) => void;\n onError?: (error: Error) => void;\n silent?: boolean;\n}\n\nexport interface CrudActions<T, TCreate, TUpdate> {\n create: (params: MutationParams<TCreate>, options?: CallOptions<T>) => Promise<T>;\n update: (params: UpdateParams<TUpdate>, options?: CallOptions<T>) => Promise<T>;\n remove: (params: DeleteParams, options?: CallOptions) => Promise<unknown>;\n isCreating: boolean;\n isUpdating: boolean;\n isDeleting: boolean;\n isMutating: boolean;\n}\n\nexport interface NavigationOptions {\n scroll?: boolean;\n replace?: boolean;\n}\n\nexport type NavigateFn<T> = (href: string, item: T, options?: NavigationOptions) => void;\n\nexport interface CrudHooksReturn<T, TCreate, TUpdate> {\n KEYS: QueryKeys;\n cache: CacheUtils<T>;\n useList: {\n /** New signature — auto-injects token/orgId from configureAuth() context */\n (params?: Record<string, unknown>, options?: ListQueryOptions): ListQueryResult<T>;\n /** Legacy signature — explicit token */\n (token: string | null, params?: Record<string, unknown>, options?: ListQueryOptions): ListQueryResult<T>;\n };\n useDetail: {\n /** New signature — auto-injects token from configureAuth() context */\n (id: string | null, options?: DetailQueryOptions): DetailQueryResult<T>;\n /** Legacy signature — explicit token */\n (id: string | null, token: string | null, options?: DetailQueryOptions): DetailQueryResult<T>;\n };\n useInfiniteList: {\n /** New signature — auto-injects token/orgId from configureAuth() context */\n (params?: Record<string, unknown>, options?: InfiniteListQueryOptions): InfiniteListQueryResult<T>;\n /** Legacy signature — explicit token */\n (token: string | null, params?: Record<string, unknown>, options?: InfiniteListQueryOptions): InfiniteListQueryResult<T>;\n };\n useActions: () => CrudActions<T, TCreate, TUpdate>;\n useNavigation: () => NavigateFn<T>;\n}\n\n// ============================================================================\n// Navigation Configuration (Global)\n// ============================================================================\n\nlet useRouterHook: UseRouterHook | null = null;\n\n/**\n * Configure the router hook for useNavigation. Call once at app init.\n *\n * @example\n * import { useRouter } from \"next/navigation\";\n * configureNavigation(useRouter);\n */\nexport function configureNavigation(hook: UseRouterHook): void {\n useRouterHook = hook;\n}\n\n// ============================================================================\n// Enabled Rule\n// ============================================================================\n\nfunction createEnabledRule(token: string | null, options: { public?: boolean; enabled?: boolean }): boolean {\n // Cookie-based auth: no token needed, queries always enabled (cookies sent via credentials: 'include')\n if (getAuthMode() === 'cookie' || options.public) {\n return options.enabled ?? true;\n }\n // Bearer token auth: require token to enable queries\n return options.enabled !== undefined ? options.enabled && !!token : !!token;\n}\n\n// ============================================================================\n// Create CRUD Hooks Factory\n// ============================================================================\n\nexport function createCrudHooks<T, TCreate = Partial<T>, TUpdate = Partial<T>>({\n api,\n entityKey,\n singular,\n defaults = {},\n callbacks = {},\n client,\n}: CrudHooksConfig<T, TCreate, TUpdate>): CrudHooksReturn<T, TCreate, TUpdate> {\n const KEYS = createQueryKeys(entityKey);\n const cache = createCacheUtils<T>(KEYS);\n\n // Resolve toast handler: client instance → global\n const instanceToast: ToastHandler | undefined = client?.toast;\n // Resolve navigation hook: client instance → global\n const instanceNavigation: UseRouterHook | null = client?.navigation ?? null;\n\n const config = {\n ...DEFAULT_QUERY_CONFIG,\n ...defaults,\n structuralSharing: defaults.structuralSharing,\n messages: {\n createSuccess: `${singular} created successfully`,\n createError: `Failed to create ${singular.toLowerCase()}`,\n updateSuccess: `${singular} updated successfully`,\n updateError: `Failed to update ${singular.toLowerCase()}`,\n deleteSuccess: `${singular} deleted successfully`,\n deleteError: `Failed to delete ${singular.toLowerCase()}`,\n ...defaults.messages,\n },\n };\n\n // ========== useList ==========\n\n function useList(\n tokenOrParams?: string | null | Record<string, unknown>,\n paramsOrOptions?: Record<string, unknown> | ListQueryOptions,\n maybeOptions?: ListQueryOptions,\n ): ListQueryResult<T> {\n let token: string | null;\n let params: Record<string, unknown>;\n let options: ListQueryOptions;\n\n // Detect which overload: first arg is string|null = legacy, object/undefined = new\n if (tokenOrParams === null || typeof tokenOrParams === 'string') {\n token = tokenOrParams;\n params = (paramsOrOptions as Record<string, unknown>) ?? {};\n options = maybeOptions ?? {};\n } else {\n const auth = getAuthContext();\n token = auth.token;\n params = (tokenOrParams as Record<string, unknown>) ?? {};\n options = (paramsOrOptions as ListQueryOptions) ?? {};\n if (auth.organizationId && !params.organizationId) {\n params = { ...params, organizationId: auth.organizationId };\n }\n }\n\n const { organizationId, ...restParams } = params;\n const scope = options._scope || (organizationId ? \"tenant\" : \"super-admin\");\n const { request: requestOpts, ...queryOpts } = options;\n\n return createListQuery<T>({\n queryKey: KEYS.scopedList(scope, { organizationId, ...restParams }),\n queryFn: ({ signal }) => api.getAll({ token, organizationId: organizationId as string | null, params: restParams, options: { signal, ...requestOpts } }),\n enabled: createEnabledRule(token, queryOpts),\n options: {\n staleTime: queryOpts.staleTime ?? config.staleTime,\n gcTime: queryOpts.gcTime ?? config.gcTime,\n refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,\n structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing,\n refetchInterval: queryOpts.refetchInterval,\n refetchIntervalInBackground: queryOpts.refetchIntervalInBackground,\n },\n prefillDetailCache: queryOpts.prefillDetailCache ?? true,\n detailKeyBuilder: (id) => KEYS.detail(id),\n });\n }\n\n // ========== useDetail ==========\n\n function useDetail(\n id: string | null,\n tokenOrOptions?: string | null | DetailQueryOptions,\n maybeOptions?: DetailQueryOptions,\n ): DetailQueryResult<T> {\n let token: string | null;\n let options: DetailQueryOptions;\n\n // Detect which overload: second arg is string|null = legacy, object/undefined = new\n if (tokenOrOptions === null || typeof tokenOrOptions === 'string') {\n token = tokenOrOptions;\n options = maybeOptions ?? {};\n } else {\n const auth = getAuthContext();\n token = auth.token;\n options = (tokenOrOptions as DetailQueryOptions) ?? {};\n if (auth.organizationId && !options.organizationId) {\n options = { ...options, organizationId: auth.organizationId };\n }\n }\n\n const { organizationId, request: requestOpts, ...restOptions } = options;\n\n return createDetailQuery<T>({\n queryKey: KEYS.detail(id || \"\"),\n queryFn: ({ signal }) => api.getById({ id: id!, token, organizationId, options: { signal, ...requestOpts } }),\n enabled: !!id && createEnabledRule(token, restOptions),\n options: {\n staleTime: restOptions.staleTime ?? config.staleTime,\n gcTime: restOptions.gcTime ?? config.gcTime,\n structuralSharing: restOptions.structuralSharing ?? config.structuralSharing,\n refetchInterval: restOptions.refetchInterval,\n refetchIntervalInBackground: restOptions.refetchIntervalInBackground,\n },\n });\n }\n\n // ========== useActions ==========\n\n function useActions(): CrudActions<T, TCreate, TUpdate> {\n const queryClient = useQueryClient();\n\n const createMutation = createOptimisticMutation({\n mutationFn: ({ token, organizationId, data }: MutationParams<TCreate>) =>\n api.create({ token, organizationId, data }),\n queryClient,\n queryKeys: [KEYS.lists()],\n optimisticUpdate: (oldData, { data }) => {\n const optimisticItem = {\n ...(data as object),\n _optimistic: true,\n [getItemId(data) ? \"id\" : \"_id\"]: getItemId(data) ?? `temp-${Date.now()}`,\n };\n return updateListCache(oldData, (arr: unknown[]) => [optimisticItem, ...(arr || [])]);\n },\n onSuccess: (data, variables) => {\n callbacks.onCreate?.onSuccess?.(data as T, { data: variables.data }, undefined);\n },\n onError: (error, variables) => {\n callbacks.onCreate?.onError?.(error, { data: variables.data }, undefined);\n },\n messages: { success: config.messages.createSuccess, error: config.messages.createError },\n toastHandler: instanceToast,\n });\n\n const updateMutation = createOptimisticMutation({\n mutationFn: ({ token, organizationId, id, data }: UpdateParams<TUpdate>) =>\n api.update({ token, organizationId, id, data }),\n queryClient,\n queryKeys: [KEYS.lists()],\n optimisticUpdate: (oldData, { id, data }) => {\n const updated = updateListCache(oldData, (arr: unknown[]) =>\n (arr || []).map((item) => (getItemId(item) === id ? { ...(item as object), ...(data as object) } : item))\n );\n queryClient.setQueryData(KEYS.detail(id), (current: unknown) =>\n current ? { ...(current as object), data: { ...((current as { data?: object }).data || {}), ...(data as object) } } : current\n );\n return updated;\n },\n onSuccess: (data, { id }) => {\n queryClient.invalidateQueries({ queryKey: KEYS.detail(id) });\n callbacks.onUpdate?.onSuccess?.(data as T, { id, data: {} as TUpdate }, undefined);\n },\n onError: (error, { id, data }) => {\n callbacks.onUpdate?.onError?.(error, { id, data }, undefined);\n },\n messages: { success: config.messages.updateSuccess, error: config.messages.updateError },\n toastHandler: instanceToast,\n });\n\n const deleteMutation = createOptimisticMutation({\n mutationFn: ({ token, organizationId, id }: DeleteParams) => api.delete({ token, organizationId, id }),\n queryClient,\n queryKeys: [KEYS.lists()],\n optimisticUpdate: (oldData, { id }) => {\n queryClient.removeQueries({ queryKey: KEYS.detail(id) });\n return updateListCache(oldData, (arr: unknown[]) => (arr || []).filter((item) => getItemId(item) !== id));\n },\n onSuccess: (data, { id }) => {\n callbacks.onDelete?.onSuccess?.(data, { id }, undefined);\n },\n onError: (error, { id }) => {\n callbacks.onDelete?.onError?.(error, { id }, undefined);\n },\n messages: { success: config.messages.deleteSuccess, error: config.messages.deleteError },\n toastHandler: instanceToast,\n });\n\n const resolveAuth = <P extends { token?: string | null; organizationId?: string | null }>(params: P): P => {\n const auth = getAuthContext();\n return {\n ...params,\n token: params.token ?? auth.token,\n organizationId: params.organizationId ?? auth.organizationId,\n };\n };\n\n const create = async (params: MutationParams<TCreate>, options?: CallOptions<T>): Promise<T> => {\n try {\n const result = await createMutation.mutateAsync(resolveAuth(params));\n options?.onSuccess?.(result as T);\n return result as T;\n } catch (error) {\n options?.onError?.(error as Error);\n throw error;\n }\n };\n\n const update = async (params: UpdateParams<TUpdate>, options?: CallOptions<T>): Promise<T> => {\n try {\n const result = await updateMutation.mutateAsync(resolveAuth(params));\n options?.onSuccess?.(result as T);\n return result as T;\n } catch (error) {\n options?.onError?.(error as Error);\n throw error;\n }\n };\n\n const remove = async (params: DeleteParams, options?: CallOptions): Promise<unknown> => {\n try {\n const result = await deleteMutation.mutateAsync(resolveAuth(params));\n options?.onSuccess?.(result);\n return result;\n } catch (error) {\n options?.onError?.(error as Error);\n throw error;\n }\n };\n\n return {\n create,\n update,\n remove,\n isCreating: createMutation.isPending,\n isUpdating: updateMutation.isPending,\n isDeleting: deleteMutation.isPending,\n isMutating: createMutation.isPending || updateMutation.isPending || deleteMutation.isPending,\n };\n }\n\n // ========== useInfiniteList ==========\n\n function useInfiniteList(\n tokenOrParams?: string | null | Record<string, unknown>,\n paramsOrOptions?: Record<string, unknown> | InfiniteListQueryOptions,\n maybeOptions?: InfiniteListQueryOptions,\n ): InfiniteListQueryResult<T> {\n let token: string | null;\n let params: Record<string, unknown>;\n let options: InfiniteListQueryOptions;\n\n if (tokenOrParams === null || typeof tokenOrParams === 'string') {\n token = tokenOrParams;\n params = (paramsOrOptions as Record<string, unknown>) ?? {};\n options = maybeOptions ?? {};\n } else {\n const auth = getAuthContext();\n token = auth.token;\n params = (tokenOrParams as Record<string, unknown>) ?? {};\n options = (paramsOrOptions as InfiniteListQueryOptions) ?? {};\n if (auth.organizationId && !params.organizationId) {\n params = { ...params, organizationId: auth.organizationId };\n }\n }\n\n const { organizationId, ...restParams } = params;\n const scope = options._scope || (organizationId ? \"tenant\" : \"super-admin\");\n const { request: requestOpts, ...queryOpts } = options;\n\n return createInfiniteListQuery<T>({\n queryKey: [...KEYS.scopedList(scope, { organizationId, ...restParams }), 'infinite'],\n queryFn: ({ signal, pageParam }) => {\n const paginationParams = typeof pageParam === 'string'\n ? { after: pageParam }\n : { page: pageParam };\n\n return api.getAll({\n token,\n organizationId: organizationId as string | null,\n params: { ...restParams, ...paginationParams },\n options: { signal, ...requestOpts },\n });\n },\n enabled: createEnabledRule(token, queryOpts),\n initialPageParam: restParams.after ? restParams.after : 1,\n getNextPageParam: (lastPage) => {\n const page = lastPage as PaginatedResponse<T>;\n if (isKeysetPagination(page)) {\n return page.hasMore ? page.next : undefined;\n }\n if (isOffsetPagination(page)) {\n return page.hasNext ? page.page + 1 : undefined;\n }\n // Fallback: check common pagination fields\n const p = page as unknown as Record<string, unknown>;\n if (typeof p.hasNext === 'boolean' && typeof p.page === 'number') {\n return p.hasNext ? (p.page as number) + 1 : undefined;\n }\n return undefined;\n },\n options: {\n staleTime: queryOpts.staleTime ?? config.staleTime,\n gcTime: queryOpts.gcTime ?? config.gcTime,\n refetchOnWindowFocus: queryOpts.refetchOnWindowFocus ?? config.refetchOnWindowFocus,\n structuralSharing: queryOpts.structuralSharing ?? config.structuralSharing,\n },\n });\n }\n\n // ========== useNavigation ==========\n\n function useNavigation(): NavigateFn<T> {\n const queryClient = useQueryClient();\n const activeRouterHook = instanceNavigation ?? useRouterHook;\n const router = activeRouterHook?.();\n\n return useCallback(\n (href: string, item: T, options: NavigationOptions = {}) => {\n const id = getItemId(item);\n if (id) {\n queryClient.setQueryData(KEYS.detail(id), { data: item });\n }\n\n if (!router) return;\n\n const { scroll = true, replace = false } = options;\n if (replace) {\n router.replace(href, { scroll });\n } else {\n router.push(href, { scroll });\n }\n },\n [queryClient, router]\n );\n }\n\n return {\n KEYS,\n cache,\n useList,\n useDetail,\n useInfiniteList,\n useActions,\n useNavigation,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ import { ToastHandler } from "./client.js";
2
+ import * as _tanstack_react_query0 from "@tanstack/react-query";
3
+ import { QueryClient, QueryKey } from "@tanstack/react-query";
4
+
5
+ //#region src/mutation.d.ts
6
+ interface MutationMessages {
7
+ success?: string | ((data: unknown, variables: unknown) => string);
8
+ error?: string | ((error: Error, variables: unknown) => string);
9
+ }
10
+ interface MutationCallbacks<TData, TVariables, TContext = unknown> {
11
+ onMutate?: (variables: TVariables) => TContext | Promise<TContext>;
12
+ onSuccess?: (data: TData, variables: TVariables, context: TContext) => void | Promise<void>;
13
+ onError?: (error: Error, variables: TVariables, context: TContext) => void | Promise<void>;
14
+ onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables, context: TContext) => void | Promise<void>;
15
+ }
16
+ /**
17
+ * Configure toast handler. Call once at app init.
18
+ *
19
+ * @example
20
+ * import { toast } from "sonner";
21
+ * configureToast({ success: toast.success, error: toast.error });
22
+ */
23
+ declare function configureToast(handler: ToastHandler): void;
24
+ interface TransitionMutationConfig<TData, TVariables> {
25
+ mutationFn: (variables: TVariables) => Promise<TData>;
26
+ invalidateQueries?: QueryKey[];
27
+ onSuccess?: (data: TData, variables: TVariables) => void;
28
+ onError?: (error: Error, variables: TVariables) => void;
29
+ onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;
30
+ messages?: MutationMessages;
31
+ useTransition?: boolean;
32
+ showToast?: boolean;
33
+ toastHandler?: ToastHandler;
34
+ }
35
+ declare function useMutationWithTransition<TData, TVariables>(config: TransitionMutationConfig<TData, TVariables>): {
36
+ mutate: _tanstack_react_query0.UseMutateFunction<TData, Error, TVariables, unknown>;
37
+ mutateAsync: _tanstack_react_query0.UseMutateAsyncFunction<TData, Error, TVariables, unknown>;
38
+ isPending: boolean;
39
+ isSuccess: boolean;
40
+ isError: boolean;
41
+ error: Error | null;
42
+ data: TData | undefined;
43
+ reset: () => void;
44
+ };
45
+ interface OptimisticMutationConfig<TData, TVariables> {
46
+ mutationFn: (variables: TVariables) => Promise<TData>;
47
+ queryKeys?: QueryKey[];
48
+ optimisticUpdate?: (oldData: unknown, variables: TVariables) => unknown;
49
+ onSuccess?: (data: TData, variables: TVariables) => void;
50
+ onError?: (error: Error, variables: TVariables) => void;
51
+ onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;
52
+ messages?: MutationMessages;
53
+ showToast?: boolean;
54
+ toastHandler?: ToastHandler;
55
+ }
56
+ declare function useMutationWithOptimistic<TData, TVariables>(config: OptimisticMutationConfig<TData, TVariables>): {
57
+ mutate: _tanstack_react_query0.UseMutateFunction<TData, Error, TVariables, {
58
+ previous: {
59
+ key: readonly unknown[];
60
+ data: unknown;
61
+ }[];
62
+ }>;
63
+ mutateAsync: _tanstack_react_query0.UseMutateAsyncFunction<TData, Error, TVariables, {
64
+ previous: {
65
+ key: readonly unknown[];
66
+ data: unknown;
67
+ }[];
68
+ }>;
69
+ isPending: boolean;
70
+ isSuccess: boolean;
71
+ isError: boolean;
72
+ error: Error | null;
73
+ data: TData | undefined;
74
+ reset: () => void;
75
+ };
76
+ interface CreateOptimisticMutationConfig<TData, TVariables> {
77
+ mutationFn: (variables: TVariables) => Promise<TData>;
78
+ queryClient: QueryClient;
79
+ queryKeys: QueryKey[];
80
+ optimisticUpdate?: (oldData: unknown, variables: TVariables) => unknown;
81
+ onSuccess?: (data: TData, variables: TVariables) => void;
82
+ onError?: (error: Error, variables: TVariables) => void;
83
+ messages?: MutationMessages;
84
+ toastHandler?: ToastHandler;
85
+ }
86
+ declare function createOptimisticMutation<TData, TVariables>({
87
+ mutationFn,
88
+ queryClient,
89
+ queryKeys,
90
+ optimisticUpdate,
91
+ onSuccess,
92
+ onError,
93
+ messages,
94
+ toastHandler: instanceToast
95
+ }: CreateOptimisticMutationConfig<TData, TVariables>): _tanstack_react_query0.UseMutationResult<TData, Error, TVariables, {
96
+ previous: {
97
+ key: readonly unknown[];
98
+ data: [readonly unknown[], unknown][];
99
+ }[];
100
+ }>;
101
+ declare const QUERY_CONFIGS: {
102
+ readonly realtime: {
103
+ readonly staleTime: 20000;
104
+ readonly refetchInterval: 30000;
105
+ };
106
+ readonly frequent: {
107
+ readonly staleTime: 60000;
108
+ };
109
+ readonly stable: {
110
+ readonly staleTime: 300000;
111
+ };
112
+ readonly static: {
113
+ readonly staleTime: 600000;
114
+ };
115
+ };
116
+ //#endregion
117
+ export { CreateOptimisticMutationConfig, MutationCallbacks, MutationMessages, OptimisticMutationConfig, QUERY_CONFIGS, type ToastHandler, TransitionMutationConfig, configureToast, createOptimisticMutation, useMutationWithOptimistic, useMutationWithTransition };
118
+ //# sourceMappingURL=mutation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutation.d.ts","names":[],"sources":["../src/mutation.ts"],"mappings":";;;;;UAciB,gBAAA;EACf,OAAA,cAAqB,IAAA,WAAe,SAAA;EACpC,KAAA,cAAmB,KAAA,EAAO,KAAA,EAAO,SAAA;AAAA;AAAA,UAGlB,iBAAA;EACf,QAAA,IAAY,SAAA,EAAW,UAAA,KAAe,QAAA,GAAW,OAAA,CAAQ,QAAA;EACzD,SAAA,IAAa,IAAA,EAAM,KAAA,EAAO,SAAA,EAAW,UAAA,EAAY,OAAA,EAAS,QAAA,YAAoB,OAAA;EAC9E,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,UAAA,EAAY,OAAA,EAAS,QAAA,YAAoB,OAAA;EAC7E,SAAA,IAAa,IAAA,EAAM,KAAA,cAAmB,KAAA,EAAO,KAAA,SAAc,SAAA,EAAW,UAAA,EAAY,OAAA,EAAS,QAAA,YAAoB,OAAA;AAAA;;;;;;AAJjH;;iBAuBgB,cAAA,CAAe,OAAA,EAAS,YAAA;AAAA,UAyCvB,wBAAA;EACf,UAAA,GAAa,SAAA,EAAW,UAAA,KAAe,OAAA,CAAQ,KAAA;EAC/C,iBAAA,GAAoB,QAAA;EACpB,SAAA,IAAa,IAAA,EAAM,KAAA,EAAO,SAAA,EAAW,UAAA;EACrC,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,UAAA;EACpC,SAAA,IAAa,IAAA,EAAM,KAAA,cAAmB,KAAA,EAAO,KAAA,SAAc,SAAA,EAAW,UAAA;EACtE,QAAA,GAAW,gBAAA;EACX,aAAA;EACA,SAAA;EACA,YAAA,GAAe,YAAA;AAAA;AAAA,iBAGD,yBAAA,mBAAA,CAA6C,MAAA,EAAQ,wBAAA,CAAyB,KAAA,EAAO,UAAA;;;;;;SAkDxE,KAAA;;;;UAUZ,wBAAA;EACf,UAAA,GAAa,SAAA,EAAW,UAAA,KAAe,OAAA,CAAQ,KAAA;EAC/C,SAAA,GAAY,QAAA;EACZ,gBAAA,IAAoB,OAAA,WAAkB,SAAA,EAAW,UAAA;EACjD,SAAA,IAAa,IAAA,EAAM,KAAA,EAAO,SAAA,EAAW,UAAA;EACrC,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,UAAA;EACpC,SAAA,IAAa,IAAA,EAAM,KAAA,cAAmB,KAAA,EAAO,KAAA,SAAc,SAAA,EAAW,UAAA;EACtE,QAAA,GAAW,gBAAA;EACX,SAAA;EACA,YAAA,GAAe,YAAA;AAAA;AAAA,iBAGD,yBAAA,mBAAA,CAA6C,MAAA,EAAQ,wBAAA,CAAyB,KAAA,EAAO,UAAA;;;;;;;;;;;;;;;;SA4DxE,KAAA;;;;UAUZ,8BAAA;EACf,UAAA,GAAa,SAAA,EAAW,UAAA,KAAe,OAAA,CAAQ,KAAA;EAC/C,WAAA,EAAa,WAAA;EACb,SAAA,EAAW,QAAA;EACX,gBAAA,IAAoB,OAAA,WAAkB,SAAA,EAAW,UAAA;EACjD,SAAA,IAAa,IAAA,EAAM,KAAA,EAAO,SAAA,EAAW,UAAA;EACrC,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,UAAA;EACpC,QAAA,GAAW,gBAAA;EACX,YAAA,GAAe,YAAA;AAAA;AAAA,iBAGD,wBAAA,mBAAA,CAAA;EACd,UAAA;EACA,WAAA;EACA,SAAA;EACA,gBAAA;EACA,SAAA;EACA,OAAA;EACA,QAAA;EACA,YAAA,EAAc;AAAA,GACb,8BAAA,CAA+B,KAAA,EAAO,UAAA,IAAW,sBAAA,CAAA,iBAAA,CAAA,KAAA,EAAA,KAAA,EAAA,UAAA;;;;;;cA6CvC,aAAA;EAAA"}