@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/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/api.d.ts +225 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +167 -0
- package/dist/api.js.map +1 -0
- package/dist/client.d.ts +172 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +242 -0
- package/dist/client.js.map +1 -0
- package/dist/hooks.d.ts +143 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +357 -0
- package/dist/hooks.js.map +1 -0
- package/dist/mutation.d.ts +118 -0
- package/dist/mutation.d.ts.map +1 -0
- package/dist/mutation.js +160 -0
- package/dist/mutation.js.map +1 -0
- package/dist/prefetch.d.ts +64 -0
- package/dist/prefetch.d.ts.map +1 -0
- package/dist/prefetch.js +76 -0
- package/dist/prefetch.js.map +1 -0
- package/dist/query-client.d.ts +25 -0
- package/dist/query-client.d.ts.map +1 -0
- package/dist/query-client.js +46 -0
- package/dist/query-client.js.map +1 -0
- package/dist/query.d.ts +177 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +203 -0
- package/dist/query.js.map +1 -0
- package/package.json +91 -0
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"}
|