@wisemen/vue-core-api-utils 1.2.0 → 2.0.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/index.d.mts +254 -281
- package/dist/index.mjs +246 -307
- package/package.json +3 -2
- package/skills/asyncresult-handling/SKILL.md +0 -79
- package/skills/cache-management/SKILL.md +14 -79
- package/skills/foundations/SKILL.md +8 -160
- package/skills/getting-started/SKILL.md +57 -109
- package/skills/optimistic-uis/SKILL.md +52 -273
- package/skills/writing-infinitequeries/SKILL.md +11 -143
- package/skills/writing-mutations/SKILL.md +11 -131
- package/skills/writing-queries/SKILL.md +1 -115
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { err, ok } from "neverthrow";
|
|
2
|
-
import { QueryClient as QueryClient$1, VueQueryPlugin, useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/vue-query";
|
|
1
|
+
import { ResultAsync, err, ok } from "neverthrow";
|
|
2
|
+
import { QueryClient as QueryClient$1, VueQueryPlugin, useInfiniteQuery, useMutation as useMutation$1, useQuery as useQuery$1, useQueryClient } from "@tanstack/vue-query";
|
|
3
3
|
import { computed } from "vue";
|
|
4
|
+
import z from "zod";
|
|
4
5
|
|
|
5
6
|
//#region src/async-result/asyncResult.ts
|
|
6
7
|
/**
|
|
@@ -139,13 +140,80 @@ function isAsyncResult(value) {
|
|
|
139
140
|
return value instanceof AsyncResultErr || value instanceof AsyncResultLoading || value instanceof AsyncResultOk;
|
|
140
141
|
}
|
|
141
142
|
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/composables/mutation/mutation.composable.ts
|
|
145
|
+
function useMutation(options) {
|
|
146
|
+
const isDebug = options.isDebug ?? false;
|
|
147
|
+
const queryClient = useQueryClient();
|
|
148
|
+
async function onSuccess(responseData, params) {
|
|
149
|
+
if (!options.queryKeysToInvalidate) return;
|
|
150
|
+
await Promise.all(Object.entries(options.queryKeysToInvalidate).map(async ([queryKey, queryKeyParams]) => {
|
|
151
|
+
if (!queryKeyParams) {
|
|
152
|
+
if (isDebug) console.log(`[MUTATION] Invalidating ${queryKey}`);
|
|
153
|
+
await queryClient.invalidateQueries({ queryKey: [queryKey] });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const qkp = queryKeyParams;
|
|
157
|
+
const paramEntries = Object.entries(qkp);
|
|
158
|
+
if (paramEntries.length === 0) {
|
|
159
|
+
if (isDebug) console.log(`[MUTATION] Invalidating ${queryKey}`);
|
|
160
|
+
await queryClient.invalidateQueries({ queryKey: [queryKey] });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const paramsWithValues = paramEntries.reduce((acc, [key, value]) => {
|
|
164
|
+
acc[key] = value(params, responseData);
|
|
165
|
+
return acc;
|
|
166
|
+
}, {});
|
|
167
|
+
if (isDebug) console.log(`[MUTATION] Invalidating ${queryKey}`, paramsWithValues);
|
|
168
|
+
await queryClient.invalidateQueries({
|
|
169
|
+
exact: false,
|
|
170
|
+
queryKey: [queryKey, paramsWithValues]
|
|
171
|
+
});
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
const mutation = useMutation$1({
|
|
175
|
+
mutationFn: options.queryFn,
|
|
176
|
+
onSuccess: async (result$1, variables) => {
|
|
177
|
+
if (!result$1.isOk()) return;
|
|
178
|
+
const data = result$1.value;
|
|
179
|
+
if (variables !== void 0 && "params" in variables) {
|
|
180
|
+
await onSuccess(data, variables.params);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
await onSuccess(data, {});
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
async function execute(data) {
|
|
187
|
+
return await mutation.mutateAsync(data);
|
|
188
|
+
}
|
|
189
|
+
const result = computed(() => {
|
|
190
|
+
if (mutation.isPending.value) return AsyncResult.loading();
|
|
191
|
+
if (mutation.isError.value) return AsyncResult.err(mutation.error.value);
|
|
192
|
+
if (mutation.isSuccess.value && mutation.data.value !== void 0) {
|
|
193
|
+
const apiResult = mutation.data.value;
|
|
194
|
+
if (apiResult.isOk()) return AsyncResult.ok(apiResult.value);
|
|
195
|
+
if (apiResult.isErr()) return AsyncResult.err(apiResult.error);
|
|
196
|
+
}
|
|
197
|
+
return AsyncResult.loading();
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
isLoading: computed(() => mutation.isPending.value),
|
|
201
|
+
data: computed(() => {
|
|
202
|
+
if (mutation.data.value?.isOk()) return mutation.data.value.value;
|
|
203
|
+
return null;
|
|
204
|
+
}),
|
|
205
|
+
execute,
|
|
206
|
+
result
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
142
210
|
//#endregion
|
|
143
211
|
//#region src/config/config.ts
|
|
144
|
-
const DEFAULT_LIMIT$
|
|
212
|
+
const DEFAULT_LIMIT$2 = 20;
|
|
145
213
|
const DEFAULT_PREFETCH_STALE_TIME = 60;
|
|
146
214
|
const QUERY_CONFIG = {
|
|
147
215
|
prefetchStaleTime: DEFAULT_PREFETCH_STALE_TIME,
|
|
148
|
-
limit: DEFAULT_LIMIT$
|
|
216
|
+
limit: DEFAULT_LIMIT$2
|
|
149
217
|
};
|
|
150
218
|
let globalQueryClient = null;
|
|
151
219
|
/**
|
|
@@ -182,12 +250,9 @@ function setQueryConfig(config) {
|
|
|
182
250
|
|
|
183
251
|
//#endregion
|
|
184
252
|
//#region src/composables/query/keysetInfiniteQuery.composable.ts
|
|
185
|
-
const DEFAULT_LIMIT$
|
|
186
|
-
function useKeysetInfiniteQuery(options) {
|
|
187
|
-
|
|
188
|
-
const [queryKey, params] = Object.entries(options.queryKey)[0];
|
|
189
|
-
return [queryKey, params];
|
|
190
|
-
}
|
|
253
|
+
const DEFAULT_LIMIT$1 = QUERY_CONFIG.limit;
|
|
254
|
+
function useKeysetInfiniteQuery(key, options) {
|
|
255
|
+
const queryKey = [key, options.params];
|
|
191
256
|
const infiniteQuery = useInfiniteQuery({
|
|
192
257
|
staleTime: options.staleTime,
|
|
193
258
|
enabled: options.isEnabled,
|
|
@@ -200,10 +265,10 @@ function useKeysetInfiniteQuery(options) {
|
|
|
200
265
|
queryFn: async ({ pageParam }) => {
|
|
201
266
|
return AsyncResult.fromResult(await options.queryFn({
|
|
202
267
|
key: pageParam,
|
|
203
|
-
limit: options.limit ?? DEFAULT_LIMIT$
|
|
268
|
+
limit: options.limit ?? DEFAULT_LIMIT$1
|
|
204
269
|
}));
|
|
205
270
|
},
|
|
206
|
-
queryKey
|
|
271
|
+
queryKey
|
|
207
272
|
});
|
|
208
273
|
const hasError = computed(() => {
|
|
209
274
|
return Boolean(infiniteQuery.data.value?.pages.find((page) => page.isErr()));
|
|
@@ -244,14 +309,9 @@ function useKeysetInfiniteQuery(options) {
|
|
|
244
309
|
|
|
245
310
|
//#endregion
|
|
246
311
|
//#region src/composables/query/offsetInfiniteQuery.composable.ts
|
|
247
|
-
const DEFAULT_LIMIT
|
|
248
|
-
function useOffsetInfiniteQuery(options) {
|
|
249
|
-
|
|
250
|
-
const [first] = Object.entries(options.queryKey);
|
|
251
|
-
if (!first) return [];
|
|
252
|
-
const [queryKey, params] = first;
|
|
253
|
-
return [queryKey, params];
|
|
254
|
-
}
|
|
312
|
+
const DEFAULT_LIMIT = QUERY_CONFIG.limit;
|
|
313
|
+
function useOffsetInfiniteQuery(key, options) {
|
|
314
|
+
const queryKey = [key, options.params];
|
|
255
315
|
const infiniteQuery = useInfiniteQuery({
|
|
256
316
|
staleTime: options.staleTime,
|
|
257
317
|
enabled: options.isEnabled,
|
|
@@ -264,10 +324,10 @@ function useOffsetInfiniteQuery(options) {
|
|
|
264
324
|
initialPageParam: 0,
|
|
265
325
|
placeholderData: (data) => data,
|
|
266
326
|
queryFn: async ({ pageParam }) => AsyncResult.fromResult(await options.queryFn({
|
|
267
|
-
limit: options.limit ?? DEFAULT_LIMIT
|
|
327
|
+
limit: options.limit ?? DEFAULT_LIMIT,
|
|
268
328
|
offset: pageParam ?? 0
|
|
269
329
|
})),
|
|
270
|
-
queryKey
|
|
330
|
+
queryKey
|
|
271
331
|
});
|
|
272
332
|
const hasError = computed(() => {
|
|
273
333
|
return Boolean(infiniteQuery.data.value?.pages.find((page) => page.isErr()));
|
|
@@ -311,188 +371,193 @@ function useOffsetInfiniteQuery(options) {
|
|
|
311
371
|
}
|
|
312
372
|
|
|
313
373
|
//#endregion
|
|
314
|
-
//#region src/
|
|
315
|
-
function
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
staleTime:
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
374
|
+
//#region src/composables/query/prefetchKeysetInfiniteQuery.composable.ts
|
|
375
|
+
function usePrefetchKeysetInfiniteQuery(key, options) {
|
|
376
|
+
const queryClient = useQueryClient();
|
|
377
|
+
const params = options.params;
|
|
378
|
+
async function execute() {
|
|
379
|
+
await queryClient.prefetchInfiniteQuery({
|
|
380
|
+
staleTime: options.staleTime ?? QUERY_CONFIG.prefetchStaleTime,
|
|
381
|
+
getNextPageParam: (lastPage) => {
|
|
382
|
+
if (!lastPage.isOk()) return null;
|
|
383
|
+
const next = lastPage.getValue().meta.next;
|
|
384
|
+
return next === null || next === void 0 ? null : next;
|
|
385
|
+
},
|
|
386
|
+
initialPageParam: void 0,
|
|
387
|
+
queryFn: async ({ pageParam }) => AsyncResult.fromResult(await options.queryFn({
|
|
388
|
+
key: pageParam,
|
|
389
|
+
limit: options.limit ?? QUERY_CONFIG.limit
|
|
390
|
+
})),
|
|
391
|
+
queryKey: [key, params]
|
|
325
392
|
});
|
|
326
393
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
394
|
+
return { execute };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
//#endregion
|
|
398
|
+
//#region src/composables/query/prefetchOffsetInfiniteQuery.composable.ts
|
|
399
|
+
function usePrefetchOffsetInfiniteQuery(key, options) {
|
|
400
|
+
const queryClient = useQueryClient();
|
|
401
|
+
const params = options.params;
|
|
402
|
+
async function execute() {
|
|
403
|
+
await queryClient.prefetchInfiniteQuery({
|
|
404
|
+
staleTime: options.staleTime ?? QUERY_CONFIG.prefetchStaleTime,
|
|
405
|
+
getNextPageParam: (lastPage) => {
|
|
406
|
+
if (!lastPage.isOk()) return null;
|
|
407
|
+
const total = lastPage.getValue().meta.offset + lastPage.getValue().meta.limit;
|
|
408
|
+
if (total >= lastPage.getValue().meta.total) return null;
|
|
409
|
+
return total;
|
|
410
|
+
},
|
|
411
|
+
initialPageParam: 0,
|
|
412
|
+
queryFn: async ({ pageParam }) => AsyncResult.fromResult(await options.queryFn({
|
|
413
|
+
limit: options.limit ?? QUERY_CONFIG.limit,
|
|
414
|
+
offset: pageParam ?? 0
|
|
415
|
+
})),
|
|
416
|
+
queryKey: [key, params]
|
|
336
417
|
});
|
|
337
418
|
}
|
|
338
|
-
return {
|
|
339
|
-
useKeysetInfiniteQuery: useKeysetInfiniteQuery$1,
|
|
340
|
-
useOffsetInfiniteQuery: useOffsetInfiniteQuery$1
|
|
341
|
-
};
|
|
419
|
+
return { execute };
|
|
342
420
|
}
|
|
343
421
|
|
|
344
422
|
//#endregion
|
|
345
|
-
//#region src/composables/
|
|
346
|
-
function
|
|
347
|
-
const isDebug = options.isDebug ?? false;
|
|
423
|
+
//#region src/composables/query/prefetchQuery.composable.ts
|
|
424
|
+
function usePrefetchQuery(key, options) {
|
|
348
425
|
const queryClient = useQueryClient();
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
await
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
const qkp = queryKeyParams;
|
|
358
|
-
const paramEntries = Object.entries(qkp);
|
|
359
|
-
if (paramEntries.length === 0) {
|
|
360
|
-
if (isDebug) console.log(`[MUTATION] Invalidating ${queryKey}`);
|
|
361
|
-
await queryClient.invalidateQueries({ queryKey: [queryKey] });
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
const paramsWithValues = paramEntries.reduce((acc, [key, value]) => {
|
|
365
|
-
acc[key] = value(params, responseData);
|
|
366
|
-
return acc;
|
|
367
|
-
}, {});
|
|
368
|
-
if (isDebug) console.log(`[MUTATION] Invalidating ${queryKey}`, paramsWithValues);
|
|
369
|
-
await queryClient.invalidateQueries({
|
|
370
|
-
exact: false,
|
|
371
|
-
queryKey: [queryKey, paramsWithValues]
|
|
372
|
-
});
|
|
373
|
-
}));
|
|
426
|
+
const params = options.params;
|
|
427
|
+
async function execute() {
|
|
428
|
+
await queryClient.prefetchQuery({
|
|
429
|
+
staleTime: options.staleTime ?? QUERY_CONFIG.prefetchStaleTime,
|
|
430
|
+
queryFn: async () => AsyncResult.fromResult(await options.queryFn()),
|
|
431
|
+
queryKey: [key, params]
|
|
432
|
+
});
|
|
374
433
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
434
|
+
return { execute };
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
//#endregion
|
|
438
|
+
//#region src/composables/query/query.composable.ts
|
|
439
|
+
function useQuery(key, options) {
|
|
440
|
+
const isDebug = options.isDebug ?? false;
|
|
441
|
+
const params = options.params;
|
|
442
|
+
const query = useQuery$1({
|
|
443
|
+
staleTime: options.staleTime,
|
|
444
|
+
enabled: options.isEnabled,
|
|
445
|
+
placeholderData: (data) => data,
|
|
446
|
+
queryFn: async () => {
|
|
447
|
+
return AsyncResult.fromResult(await options.queryFn());
|
|
448
|
+
},
|
|
449
|
+
queryKey: [key, params]
|
|
386
450
|
});
|
|
387
|
-
|
|
388
|
-
|
|
451
|
+
if (isDebug) console.debug(`Create query with key ${String(key)}`, params);
|
|
452
|
+
async function refetch() {
|
|
453
|
+
await query.refetch();
|
|
389
454
|
}
|
|
390
|
-
const result = computed(() => {
|
|
391
|
-
if (mutation.isPending.value) return AsyncResult.loading();
|
|
392
|
-
if (mutation.isError.value) return AsyncResult.err(mutation.error.value);
|
|
393
|
-
if (mutation.isSuccess.value && mutation.data.value !== void 0) {
|
|
394
|
-
const apiResult = mutation.data.value;
|
|
395
|
-
if (apiResult.isOk()) return AsyncResult.ok(apiResult.value);
|
|
396
|
-
if (apiResult.isErr()) return AsyncResult.err(apiResult.error);
|
|
397
|
-
}
|
|
398
|
-
return AsyncResult.loading();
|
|
399
|
-
});
|
|
400
455
|
return {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
456
|
+
isError: computed(() => query.data.value?.isErr() ?? false),
|
|
457
|
+
isFetching: computed(() => query.isFetching.value),
|
|
458
|
+
isLoading: computed(() => query.isLoading.value),
|
|
459
|
+
isSuccess: computed(() => query.data.value?.isOk() ?? false),
|
|
460
|
+
refetch,
|
|
461
|
+
result: computed(() => {
|
|
462
|
+
if (query.isLoading.value) return AsyncResult.loading();
|
|
463
|
+
if (query.data.value?.isOk()) return AsyncResult.ok(query.data.value.getValue());
|
|
464
|
+
if (query.data.value?.isErr()) return AsyncResult.err(query.data.value.getError());
|
|
465
|
+
return AsyncResult.loading();
|
|
466
|
+
})
|
|
408
467
|
};
|
|
409
468
|
}
|
|
410
469
|
|
|
411
470
|
//#endregion
|
|
412
|
-
//#region src/
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
471
|
+
//#region src/plugin/apiUtilsPlugin.ts
|
|
472
|
+
/**
|
|
473
|
+
* Create a Vue plugin that sets up TanStack Query and initializes API utilities.
|
|
474
|
+
*
|
|
475
|
+
* This plugin handles:
|
|
476
|
+
* - Creating a QueryClient with the provided config
|
|
477
|
+
* - Installing VueQueryPlugin on the app
|
|
478
|
+
* - Initializing the global QueryClient for api-utils
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* ```typescript
|
|
482
|
+
* import { apiUtilsPlugin } from '@wisemen/vue-core-api-utils'
|
|
483
|
+
* import { vueQueryClientConfig } from '@wisemen/vue-core-configs'
|
|
484
|
+
*
|
|
485
|
+
* app.use(apiUtilsPlugin(vueQueryClientConfig()))
|
|
486
|
+
* ```
|
|
487
|
+
*
|
|
488
|
+
* @param config - QueryClient configuration
|
|
489
|
+
* @returns A Vue plugin that can be used with app.use()
|
|
490
|
+
*/
|
|
491
|
+
function apiUtilsPlugin(config) {
|
|
492
|
+
const queryClient = new QueryClient$1(config);
|
|
493
|
+
return { install: (app) => {
|
|
494
|
+
app.use(VueQueryPlugin, { queryClient });
|
|
495
|
+
initializeApiUtils(queryClient);
|
|
496
|
+
} };
|
|
422
497
|
}
|
|
423
498
|
|
|
424
499
|
//#endregion
|
|
425
|
-
//#region src/
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
if (total >= lastPage.value.meta.total) return null;
|
|
438
|
-
return total;
|
|
439
|
-
},
|
|
440
|
-
initialPageParam: 0,
|
|
441
|
-
queryFn: ({ pageParam }) => queryOptions.queryFn({
|
|
442
|
-
limit: queryOptions.limit ?? DEFAULT_LIMIT,
|
|
443
|
-
offset: pageParam ?? 0
|
|
444
|
-
}),
|
|
445
|
-
queryKey
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
return { execute };
|
|
449
|
-
}
|
|
450
|
-
function usePrefetchKeysetInfiniteQuery(key, queryOptions) {
|
|
451
|
-
const queryKey = [key, queryOptions.params ?? {}];
|
|
452
|
-
async function execute() {
|
|
453
|
-
await getQueryClient().prefetchInfiniteQuery({
|
|
454
|
-
staleTime: queryOptions.staleTime ?? QUERY_CONFIG.prefetchStaleTime,
|
|
455
|
-
getNextPageParam: (lastPage) => {
|
|
456
|
-
if (lastPage.isErr()) return null;
|
|
457
|
-
const next = lastPage.value.meta.next;
|
|
458
|
-
if (next === null || next === void 0) return null;
|
|
459
|
-
return next;
|
|
460
|
-
},
|
|
461
|
-
initialPageParam: void 0,
|
|
462
|
-
queryFn: ({ pageParam }) => queryOptions.queryFn({
|
|
463
|
-
key: pageParam,
|
|
464
|
-
limit: queryOptions.limit ?? DEFAULT_LIMIT
|
|
465
|
-
}),
|
|
466
|
-
queryKey
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
return { execute };
|
|
500
|
+
//#region src/types/sort.type.ts
|
|
501
|
+
let SortDirection = /* @__PURE__ */ function(SortDirection$1) {
|
|
502
|
+
SortDirection$1["ASC"] = "asc";
|
|
503
|
+
SortDirection$1["DESC"] = "desc";
|
|
504
|
+
return SortDirection$1;
|
|
505
|
+
}({});
|
|
506
|
+
|
|
507
|
+
//#endregion
|
|
508
|
+
//#region src/utils/api-error/apiError.util.ts
|
|
509
|
+
var ApiErrorUtil = class ApiErrorUtil {
|
|
510
|
+
static getApiErrorCode(error) {
|
|
511
|
+
return error.errors?.[0]?.code ?? null;
|
|
470
512
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
513
|
+
static getApiErrorMessage(error) {
|
|
514
|
+
return error.errors?.[0]?.detail ?? null;
|
|
515
|
+
}
|
|
516
|
+
static getMessage(error) {
|
|
517
|
+
return error.errors?.[0]?.detail ?? null;
|
|
518
|
+
}
|
|
519
|
+
static handleApiError({ error, message }) {
|
|
520
|
+
if (ApiErrorUtil.isExpectedApiError(error)) return error;
|
|
521
|
+
console.error(`Unexpected API error: ${error}`);
|
|
522
|
+
if (error instanceof Error) return error;
|
|
523
|
+
return new Error(message ?? "An unknown error occurred");
|
|
524
|
+
}
|
|
525
|
+
static isExpectedApiError(error) {
|
|
526
|
+
return error?.errors !== void 0;
|
|
527
|
+
}
|
|
528
|
+
static isZodError(error) {
|
|
529
|
+
return error instanceof z.ZodError;
|
|
530
|
+
}
|
|
531
|
+
};
|
|
476
532
|
|
|
477
533
|
//#endregion
|
|
478
|
-
//#region src/
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
staleTime: queryOptions.staleTime ?? QUERY_CONFIG.prefetchStaleTime,
|
|
486
|
-
queryFn: async () => {
|
|
487
|
-
return AsyncResult.fromResult(await queryOptions.queryFn());
|
|
488
|
-
},
|
|
489
|
-
queryKey
|
|
534
|
+
//#region src/utils/api/api.util.ts
|
|
535
|
+
var ApiUtil = class ApiUtil {
|
|
536
|
+
static async fromPromise(promise, message) {
|
|
537
|
+
return await ResultAsync.fromPromise(promise, (error) => {
|
|
538
|
+
return ApiErrorUtil.handleApiError({
|
|
539
|
+
error,
|
|
540
|
+
message
|
|
490
541
|
});
|
|
491
|
-
}
|
|
492
|
-
return { execute };
|
|
542
|
+
});
|
|
493
543
|
}
|
|
494
|
-
|
|
495
|
-
|
|
544
|
+
static getKeysetPaginationNextOffset(keysetPaginationMeta) {
|
|
545
|
+
return keysetPaginationMeta.next?.offset ?? null;
|
|
546
|
+
}
|
|
547
|
+
static getResultError(result) {
|
|
548
|
+
if (result === null) return null;
|
|
549
|
+
if (!result.isErr()) return null;
|
|
550
|
+
if (ApiUtil.isAsyncResult(result)) return result.getError();
|
|
551
|
+
return result.error;
|
|
552
|
+
}
|
|
553
|
+
static isAsyncResult(value) {
|
|
554
|
+
return value.getResult !== void 0;
|
|
555
|
+
}
|
|
556
|
+
static void(result) {
|
|
557
|
+
if (result.isErr()) return err(result.error);
|
|
558
|
+
return ok();
|
|
559
|
+
}
|
|
560
|
+
};
|
|
496
561
|
|
|
497
562
|
//#endregion
|
|
498
563
|
//#region src/utils/query-client/queryClient.ts
|
|
@@ -632,132 +697,6 @@ var QueryClient = class {
|
|
|
632
697
|
}
|
|
633
698
|
};
|
|
634
699
|
|
|
635
|
-
//#endregion
|
|
636
|
-
//#region src/factory/createApiQueryClientUtils.ts
|
|
637
|
-
function createApiQueryClientUtils() {
|
|
638
|
-
function useQueryClient$1() {
|
|
639
|
-
return new QueryClient(getQueryClient());
|
|
640
|
-
}
|
|
641
|
-
return { useQueryClient: useQueryClient$1 };
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
//#endregion
|
|
645
|
-
//#region src/composables/query/query.composable.ts
|
|
646
|
-
function useQuery$1(options) {
|
|
647
|
-
const isDebug = options.isDebug ?? false;
|
|
648
|
-
const query = useQuery({
|
|
649
|
-
staleTime: options.staleTime,
|
|
650
|
-
enabled: options.isEnabled,
|
|
651
|
-
placeholderData: (data) => data,
|
|
652
|
-
queryFn: async () => {
|
|
653
|
-
return AsyncResult.fromResult(await options.queryFn());
|
|
654
|
-
},
|
|
655
|
-
queryKey: getQueryKey()
|
|
656
|
-
});
|
|
657
|
-
function getQueryKey() {
|
|
658
|
-
const [queryKey, params] = Object.entries(options.queryKey)[0];
|
|
659
|
-
if (isDebug) console.debug(`Create query with key ${queryKey}`, params);
|
|
660
|
-
return [queryKey, params];
|
|
661
|
-
}
|
|
662
|
-
async function refetch() {
|
|
663
|
-
await query.refetch();
|
|
664
|
-
}
|
|
665
|
-
return {
|
|
666
|
-
isError: computed(() => query.data.value?.isErr() ?? false),
|
|
667
|
-
isFetching: computed(() => query.isFetching.value),
|
|
668
|
-
isLoading: computed(() => query.isLoading.value),
|
|
669
|
-
isSuccess: computed(() => query.data.value?.isOk() ?? false),
|
|
670
|
-
refetch,
|
|
671
|
-
result: computed(() => {
|
|
672
|
-
if (query.isLoading.value) return AsyncResult.loading();
|
|
673
|
-
if (query.data.value?.isOk()) return AsyncResult.ok(query.data.value.getValue());
|
|
674
|
-
if (query.data.value?.isErr()) return AsyncResult.err(query.data.value.getError());
|
|
675
|
-
return AsyncResult.loading();
|
|
676
|
-
})
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
//#endregion
|
|
681
|
-
//#region src/factory/createApiQueryUtils.ts
|
|
682
|
-
function createApiQueryUtils() {
|
|
683
|
-
function useQuery$2(key, queryOptions) {
|
|
684
|
-
const params = queryOptions.params ?? {};
|
|
685
|
-
const queryKey = { [key]: params };
|
|
686
|
-
return useQuery$1({
|
|
687
|
-
staleTime: queryOptions.staleTime,
|
|
688
|
-
isDebug: queryOptions.isDebug,
|
|
689
|
-
isEnabled: queryOptions.isEnabled,
|
|
690
|
-
queryFn: queryOptions.queryFn,
|
|
691
|
-
queryKey
|
|
692
|
-
});
|
|
693
|
-
}
|
|
694
|
-
return { useQuery: useQuery$2 };
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
//#endregion
|
|
698
|
-
//#region src/factory/createApiUtils.ts
|
|
699
|
-
/**
|
|
700
|
-
* Factory that creates typed composables based on a user-provided query-keys config.
|
|
701
|
-
*
|
|
702
|
-
* Requires `initializeApiUtils(queryClient)` to be called first.
|
|
703
|
-
*
|
|
704
|
-
* @example
|
|
705
|
-
* ```typescript
|
|
706
|
-
* // In app setup (plugin or main.ts):
|
|
707
|
-
* initializeApiUtils(queryClient)
|
|
708
|
-
*
|
|
709
|
-
* // In your api lib:
|
|
710
|
-
* export const { useQuery, useMutation, useQueryClient } = createApiUtils<MyQueryKeys>()
|
|
711
|
-
* ```
|
|
712
|
-
*/
|
|
713
|
-
function createApiUtils() {
|
|
714
|
-
return {
|
|
715
|
-
...createApiQueryUtils(),
|
|
716
|
-
...createApiPrefetchQueryUtils(),
|
|
717
|
-
...createApiPrefetchInfiniteQueryUtils(),
|
|
718
|
-
...createApiInfiniteQueryUtils(),
|
|
719
|
-
...createApiMutationUtils(),
|
|
720
|
-
...createApiQueryClientUtils()
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
//#endregion
|
|
725
|
-
//#region src/plugin/apiUtilsPlugin.ts
|
|
726
|
-
/**
|
|
727
|
-
* Create a Vue plugin that sets up TanStack Query and initializes API utilities.
|
|
728
|
-
*
|
|
729
|
-
* This plugin handles:
|
|
730
|
-
* - Creating a QueryClient with the provided config
|
|
731
|
-
* - Installing VueQueryPlugin on the app
|
|
732
|
-
* - Initializing the global QueryClient for api-utils
|
|
733
|
-
*
|
|
734
|
-
* @example
|
|
735
|
-
* ```typescript
|
|
736
|
-
* import { apiUtilsPlugin } from '@wisemen/vue-core-api-utils'
|
|
737
|
-
* import { vueQueryClientConfig } from '@wisemen/vue-core-configs'
|
|
738
|
-
*
|
|
739
|
-
* app.use(apiUtilsPlugin(vueQueryClientConfig()))
|
|
740
|
-
* ```
|
|
741
|
-
*
|
|
742
|
-
* @param config - QueryClient configuration
|
|
743
|
-
* @returns A Vue plugin that can be used with app.use()
|
|
744
|
-
*/
|
|
745
|
-
function apiUtilsPlugin(config) {
|
|
746
|
-
const queryClient = new QueryClient$1(config);
|
|
747
|
-
return { install: (app) => {
|
|
748
|
-
app.use(VueQueryPlugin, { queryClient });
|
|
749
|
-
initializeApiUtils(queryClient);
|
|
750
|
-
} };
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
//#endregion
|
|
754
|
-
//#region src/types/sort.type.ts
|
|
755
|
-
let SortDirection = /* @__PURE__ */ function(SortDirection$1) {
|
|
756
|
-
SortDirection$1["ASC"] = "asc";
|
|
757
|
-
SortDirection$1["DESC"] = "desc";
|
|
758
|
-
return SortDirection$1;
|
|
759
|
-
}({});
|
|
760
|
-
|
|
761
700
|
//#endregion
|
|
762
701
|
//#region src/utils/sort/sort.utils.ts
|
|
763
702
|
var SortUtil = class {
|
|
@@ -770,4 +709,4 @@ var SortUtil = class {
|
|
|
770
709
|
};
|
|
771
710
|
|
|
772
711
|
//#endregion
|
|
773
|
-
export { AsyncResult, AsyncResultErr, AsyncResultLoading, AsyncResultOk, QueryClient, SortDirection, SortUtil, apiUtilsPlugin,
|
|
712
|
+
export { ApiErrorUtil, ApiUtil, AsyncResult, AsyncResultErr, AsyncResultLoading, AsyncResultOk, QueryClient, SortDirection, SortUtil, apiUtilsPlugin, getQueryClient as getTanstackQueryClient, initializeApiUtils, setQueryConfig, useKeysetInfiniteQuery, useMutation, useOffsetInfiniteQuery, usePrefetchKeysetInfiniteQuery, usePrefetchOffsetInfiniteQuery, usePrefetchQuery, useQuery };
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "
|
|
7
|
+
"version": "2.0.1",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@tanstack/vue-query": ">=5.90.5",
|
|
37
37
|
"neverthrow": ">=8.2.0",
|
|
38
|
+
"zod": ">=4.3.5",
|
|
38
39
|
"vue": ">=3.5.22"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
"typescript": "5.9.3",
|
|
46
47
|
"vue": "3.5.27",
|
|
47
48
|
"vitest": "4.1.0",
|
|
48
|
-
"@wisemen/eslint-config-vue": "2.1.
|
|
49
|
+
"@wisemen/eslint-config-vue": "2.1.3"
|
|
49
50
|
},
|
|
50
51
|
"scripts": {
|
|
51
52
|
"build": "tsdown",
|