katanakit-js 4.0.2 → 4.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -55
- package/dist/adapters/angular/index.d.ts +1 -0
- package/dist/adapters/angular/index.d.ts.map +1 -1
- package/dist/adapters/angular/index.js +1 -0
- package/dist/adapters/angular/index.js.map +1 -1
- package/dist/adapters/angular/query.d.ts +56 -73
- package/dist/adapters/angular/query.d.ts.map +1 -1
- package/dist/adapters/angular/query.js +66 -129
- package/dist/adapters/angular/query.js.map +1 -1
- package/dist/adapters/react/index.d.ts +1 -0
- package/dist/adapters/react/index.d.ts.map +1 -1
- package/dist/adapters/react/index.js +1 -0
- package/dist/adapters/react/index.js.map +1 -1
- package/dist/adapters/react/query.d.ts +27 -72
- package/dist/adapters/react/query.d.ts.map +1 -1
- package/dist/adapters/react/query.js +51 -165
- package/dist/adapters/react/query.js.map +1 -1
- package/dist/adapters/solid/index.d.ts +1 -0
- package/dist/adapters/solid/index.d.ts.map +1 -1
- package/dist/adapters/solid/index.js +1 -0
- package/dist/adapters/solid/index.js.map +1 -1
- package/dist/adapters/solid/query.d.ts +32 -74
- package/dist/adapters/solid/query.d.ts.map +1 -1
- package/dist/adapters/solid/query.js +56 -131
- package/dist/adapters/solid/query.js.map +1 -1
- package/dist/adapters/svelte/index.d.ts +1 -0
- package/dist/adapters/svelte/index.d.ts.map +1 -1
- package/dist/adapters/svelte/index.js +1 -0
- package/dist/adapters/svelte/index.js.map +1 -1
- package/dist/adapters/svelte/query.d.ts +24 -72
- package/dist/adapters/svelte/query.d.ts.map +1 -1
- package/dist/adapters/svelte/query.js +41 -135
- package/dist/adapters/svelte/query.js.map +1 -1
- package/dist/adapters/vanilla/index.d.ts +3 -0
- package/dist/adapters/vanilla/index.d.ts.map +1 -0
- package/dist/adapters/vanilla/index.js +3 -0
- package/dist/adapters/vanilla/index.js.map +1 -0
- package/dist/adapters/vanilla/query.d.ts +69 -0
- package/dist/adapters/vanilla/query.d.ts.map +1 -0
- package/dist/adapters/vanilla/query.js +76 -0
- package/dist/adapters/vanilla/query.js.map +1 -0
- package/dist/adapters/vue/index.d.ts +1 -0
- package/dist/adapters/vue/index.d.ts.map +1 -1
- package/dist/adapters/vue/index.js +1 -0
- package/dist/adapters/vue/index.js.map +1 -1
- package/dist/adapters/vue/query.d.ts +35 -86
- package/dist/adapters/vue/query.d.ts.map +1 -1
- package/dist/adapters/vue/query.js +57 -168
- package/dist/adapters/vue/query.js.map +1 -1
- package/dist/core/services/query.service.d.ts +87 -134
- package/dist/core/services/query.service.d.ts.map +1 -1
- package/dist/core/services/query.service.js +99 -378
- package/dist/core/services/query.service.js.map +1 -1
- package/package.json +10 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/adapters/svelte/query.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/adapters/svelte/query.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,gBAAgB,EAIhB,aAAa,GAGb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAiB,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,QAAQ,CACvB,OAA0D,EAC1D,MAAoB;IAEpB,MAAM,WAAW,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;IAE1F,OAAO,QAAQ,CAAqC,QAAQ,CAAC,gBAAgB,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;QACxF,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAChE,GAAG,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACjC,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,WAAW,CAC1B,OAAqE,EACrE,MAAoB;IAEpB,MAAM,WAAW,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAE5D,OAAO,QAAQ,CACd,QAAQ,CAAC,gBAAgB,EAAE,EAC3B,CAAC,GAAG,EAAE,EAAE;QACP,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAChE,qEAAqE;QACrE,GAAG,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACjC,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/vanilla/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,cAAc,GACd,MAAM,sCAAsC,CAAC;AAC9C,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/vanilla/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,cAAc,GACd,MAAM,sCAAsC,CAAC;AAC9C,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { MutationObserver, type MutationObserverOptions, type QueryClient, QueryObserver, type QueryObserverOptions } from "@tanstack/query-core";
|
|
2
|
+
/**
|
|
3
|
+
* Vanilla (framework-free) query binding — plain TypeScript / JavaScript, no framework.
|
|
4
|
+
*
|
|
5
|
+
* Returns a raw TanStack {@link QueryObserver}. The framework adapters are this
|
|
6
|
+
* plus a reactivity bridge (React `useSyncExternalStore`, Vue `shallowReactive`,
|
|
7
|
+
* Solid store, Svelte store, Angular signals); here **you** own the bridge:
|
|
8
|
+
* subscribe, read `getCurrentResult()`, and re-render however you want (DOM,
|
|
9
|
+
* canvas, CLI, worker, terminal UI).
|
|
10
|
+
*
|
|
11
|
+
* The observer does not start fetching until you `subscribe()` (or call
|
|
12
|
+
* `refetch()`); it stops when the last subscriber unsubscribes or you call
|
|
13
|
+
* `destroy()`.
|
|
14
|
+
*
|
|
15
|
+
* @param options - TanStack query options (`queryKey`, `queryFn`, `staleTime`, …).
|
|
16
|
+
* @param client - Optional {@link QueryClient} (defaults to the shared singleton).
|
|
17
|
+
* @returns A {@link QueryObserver} — `subscribe`, `getCurrentResult`, `setOptions`, `refetch`, `destroy`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { useQuery, useSafeQueryFn } from "katanakit-js/adapters/vanilla";
|
|
22
|
+
* import { useGetApi } from "katanakit-js";
|
|
23
|
+
*
|
|
24
|
+
* const observer = useQuery({
|
|
25
|
+
* queryKey: ["pokemon", 25],
|
|
26
|
+
* queryFn: useSafeQueryFn(() => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } })),
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* const render = () => {
|
|
30
|
+
* const { data, isPending, isError, error } = observer.getCurrentResult();
|
|
31
|
+
* // …paint `data` / `isPending` / `error` wherever you want
|
|
32
|
+
* };
|
|
33
|
+
*
|
|
34
|
+
* const unsubscribe = observer.subscribe(render);
|
|
35
|
+
* render(); // paint the current (pending) state immediately
|
|
36
|
+
*
|
|
37
|
+
* // later: unsubscribe(); observer.destroy();
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData>(options: QueryObserverOptions<TQueryFnData, TError, TData>, client?: QueryClient): QueryObserver<TQueryFnData, TError, TData>;
|
|
41
|
+
/**
|
|
42
|
+
* Vanilla (framework-free) mutation binding.
|
|
43
|
+
*
|
|
44
|
+
* Returns a raw TanStack {@link MutationObserver}. Call `observer.mutate(vars)`,
|
|
45
|
+
* read `getCurrentResult()`, and `subscribe()` if you want to react to the
|
|
46
|
+
* `isPending` → `isSuccess` / `isError` transitions.
|
|
47
|
+
*
|
|
48
|
+
* @param options - TanStack mutation options (`mutationFn`, `onSuccess`, …).
|
|
49
|
+
* @param client - Optional {@link QueryClient} (defaults to the shared singleton).
|
|
50
|
+
* @returns A {@link MutationObserver} — `mutate`, `reset`, `getCurrentResult`, `subscribe`.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { useMutation } from "katanakit-js/adapters/vanilla";
|
|
55
|
+
* import { usePost } from "katanakit-js";
|
|
56
|
+
*
|
|
57
|
+
* const mutation = useMutation({
|
|
58
|
+
* mutationFn: (name: string) => usePost("api", "createUser", { name }),
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* const unsubscribe = mutation.subscribe(({ isPending, isSuccess, error }) => {
|
|
62
|
+
* // …paint the mutation state
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* await mutation.mutate("Ada");
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function useMutation<TData = unknown, TError = Error, TVariables = void>(options: MutationObserverOptions<TData, TError, TVariables>, client?: QueryClient): MutationObserver<TData, TError, TVariables>;
|
|
69
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/adapters/vanilla/query.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EAChB,aAAa,EACb,KAAK,oBAAoB,EACzB,MAAM,sBAAsB,CAAC;AAI9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,QAAQ,CAAC,YAAY,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,KAAK,GAAG,YAAY,EACpF,OAAO,EAAE,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAC1D,MAAM,CAAC,EAAE,WAAW,GAClB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,CAG5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,WAAW,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,UAAU,GAAG,IAAI,EAC7E,OAAO,EAAE,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAC3D,MAAM,CAAC,EAAE,WAAW,GAClB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAG7C"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { MutationObserver, QueryObserver, } from "@tanstack/query-core";
|
|
2
|
+
import { useQueryClient } from "../../core/services/query.service.js";
|
|
3
|
+
/**
|
|
4
|
+
* Vanilla (framework-free) query binding — plain TypeScript / JavaScript, no framework.
|
|
5
|
+
*
|
|
6
|
+
* Returns a raw TanStack {@link QueryObserver}. The framework adapters are this
|
|
7
|
+
* plus a reactivity bridge (React `useSyncExternalStore`, Vue `shallowReactive`,
|
|
8
|
+
* Solid store, Svelte store, Angular signals); here **you** own the bridge:
|
|
9
|
+
* subscribe, read `getCurrentResult()`, and re-render however you want (DOM,
|
|
10
|
+
* canvas, CLI, worker, terminal UI).
|
|
11
|
+
*
|
|
12
|
+
* The observer does not start fetching until you `subscribe()` (or call
|
|
13
|
+
* `refetch()`); it stops when the last subscriber unsubscribes or you call
|
|
14
|
+
* `destroy()`.
|
|
15
|
+
*
|
|
16
|
+
* @param options - TanStack query options (`queryKey`, `queryFn`, `staleTime`, …).
|
|
17
|
+
* @param client - Optional {@link QueryClient} (defaults to the shared singleton).
|
|
18
|
+
* @returns A {@link QueryObserver} — `subscribe`, `getCurrentResult`, `setOptions`, `refetch`, `destroy`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { useQuery, useSafeQueryFn } from "katanakit-js/adapters/vanilla";
|
|
23
|
+
* import { useGetApi } from "katanakit-js";
|
|
24
|
+
*
|
|
25
|
+
* const observer = useQuery({
|
|
26
|
+
* queryKey: ["pokemon", 25],
|
|
27
|
+
* queryFn: useSafeQueryFn(() => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } })),
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* const render = () => {
|
|
31
|
+
* const { data, isPending, isError, error } = observer.getCurrentResult();
|
|
32
|
+
* // …paint `data` / `isPending` / `error` wherever you want
|
|
33
|
+
* };
|
|
34
|
+
*
|
|
35
|
+
* const unsubscribe = observer.subscribe(render);
|
|
36
|
+
* render(); // paint the current (pending) state immediately
|
|
37
|
+
*
|
|
38
|
+
* // later: unsubscribe(); observer.destroy();
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function useQuery(options, client) {
|
|
42
|
+
const queryClient = client ?? useQueryClient();
|
|
43
|
+
return new QueryObserver(queryClient, queryClient.defaultQueryOptions(options));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Vanilla (framework-free) mutation binding.
|
|
47
|
+
*
|
|
48
|
+
* Returns a raw TanStack {@link MutationObserver}. Call `observer.mutate(vars)`,
|
|
49
|
+
* read `getCurrentResult()`, and `subscribe()` if you want to react to the
|
|
50
|
+
* `isPending` → `isSuccess` / `isError` transitions.
|
|
51
|
+
*
|
|
52
|
+
* @param options - TanStack mutation options (`mutationFn`, `onSuccess`, …).
|
|
53
|
+
* @param client - Optional {@link QueryClient} (defaults to the shared singleton).
|
|
54
|
+
* @returns A {@link MutationObserver} — `mutate`, `reset`, `getCurrentResult`, `subscribe`.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { useMutation } from "katanakit-js/adapters/vanilla";
|
|
59
|
+
* import { usePost } from "katanakit-js";
|
|
60
|
+
*
|
|
61
|
+
* const mutation = useMutation({
|
|
62
|
+
* mutationFn: (name: string) => usePost("api", "createUser", { name }),
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* const unsubscribe = mutation.subscribe(({ isPending, isSuccess, error }) => {
|
|
66
|
+
* // …paint the mutation state
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* await mutation.mutate("Ada");
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export function useMutation(options, client) {
|
|
73
|
+
const queryClient = client ?? useQueryClient();
|
|
74
|
+
return new MutationObserver(queryClient, options);
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/adapters/vanilla/query.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,gBAAgB,EAGhB,aAAa,GAEb,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,UAAU,QAAQ,CACvB,OAA0D,EAC1D,MAAoB;IAEpB,MAAM,WAAW,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC;IAC/C,OAAO,IAAI,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;AACjF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,WAAW,CAC1B,OAA2D,EAC3D,MAAoB;IAEpB,MAAM,WAAW,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC;IAC/C,OAAO,IAAI,gBAAgB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,cAAc,GACd,MAAM,sCAAsC,CAAC;AAC9C,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/vue/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,cAAc,GACd,MAAM,sCAAsC,CAAC;AAC9C,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
|
@@ -1,100 +1,45 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type
|
|
3
|
-
import type { ApiError, FetchResult } from "../../types/index.js";
|
|
4
|
-
/** Reactive return value of `useQuery`. */
|
|
5
|
-
export interface UseQueryReturn<T> {
|
|
6
|
-
/** The resolved data on success, `null` otherwise. */
|
|
7
|
-
data: Ref<T | null>;
|
|
8
|
-
/** The Safe Result error on failure, `null` otherwise. */
|
|
9
|
-
error: Ref<ApiError | null>;
|
|
10
|
-
/** Whether the query is currently fetching. */
|
|
11
|
-
isLoading: Ref<boolean>;
|
|
12
|
-
/** Whether the query succeeded with data. */
|
|
13
|
-
isSuccess: Ref<boolean>;
|
|
14
|
-
/** Whether the query failed with an error. */
|
|
15
|
-
isError: Ref<boolean>;
|
|
16
|
-
/** Whether the cached data is stale. */
|
|
17
|
-
isStale: Ref<boolean>;
|
|
18
|
-
/** Current status of the query. */
|
|
19
|
-
status: Ref<"idle" | "loading" | "success" | "error">;
|
|
20
|
-
/** Manually refetch the query. */
|
|
21
|
-
refetch: () => Promise<void>;
|
|
22
|
-
}
|
|
23
|
-
/** Configuration for `useQuery` (Vue reactive version). */
|
|
24
|
-
export interface UseQueryConfig<T = unknown> {
|
|
25
|
-
/** Reactive query key — the query refetches when it changes. */
|
|
26
|
-
queryKey: MaybeRef<QueryKey>;
|
|
27
|
-
/** Fetcher function returning a Safe Result. */
|
|
28
|
-
queryFn: () => Promise<FetchResult<T>>;
|
|
29
|
-
/** Time in ms before cached data is stale (default: 0). */
|
|
30
|
-
staleTime?: MaybeRef<number>;
|
|
31
|
-
/** Time in ms to keep unused data (default: 5 min). */
|
|
32
|
-
cacheTime?: number;
|
|
33
|
-
/** Retry count on failure (default: 3). */
|
|
34
|
-
retry?: number;
|
|
35
|
-
/** Base delay for exponential backoff (default: 1000). */
|
|
36
|
-
retryDelay?: number;
|
|
37
|
-
/** Refetch on window focus (default: true). */
|
|
38
|
-
refetchOnWindowFocus?: MaybeRef<boolean>;
|
|
39
|
-
/** Whether the query is enabled (default: true). */
|
|
40
|
-
enabled?: MaybeRef<boolean>;
|
|
41
|
-
}
|
|
42
|
-
/** Configuration for `useMutation`. */
|
|
43
|
-
export interface UseMutationConfig<TData = unknown, TVariables = unknown> {
|
|
44
|
-
mutationFn: (variables: TVariables) => Promise<FetchResult<TData>>;
|
|
45
|
-
onSuccess?: (data: TData, variables: TVariables) => void;
|
|
46
|
-
onError?: (error: ApiError, variables: TVariables) => void;
|
|
47
|
-
onSettled?: (data: TData | null, error: ApiError | null, variables: TVariables) => void;
|
|
48
|
-
}
|
|
49
|
-
/** Reactive return value of `useMutation`. */
|
|
50
|
-
export interface UseMutationReturn<TData, TVariables> {
|
|
51
|
-
/** The resolved data from the last mutation. */
|
|
52
|
-
data: Ref<TData | null>;
|
|
53
|
-
/** The error from the last mutation. */
|
|
54
|
-
error: Ref<ApiError | null>;
|
|
55
|
-
/** Whether a mutation is in flight. */
|
|
56
|
-
isLoading: Ref<boolean>;
|
|
57
|
-
/** Whether the last mutation succeeded. */
|
|
58
|
-
isSuccess: Ref<boolean>;
|
|
59
|
-
/** Whether the last mutation failed. */
|
|
60
|
-
isError: Ref<boolean>;
|
|
61
|
-
/** Current status of the mutation. */
|
|
62
|
-
status: Ref<"idle" | "loading" | "success" | "error">;
|
|
63
|
-
/** Execute the mutation. */
|
|
64
|
-
mutate: (variables: TVariables) => Promise<void>;
|
|
65
|
-
/** Reset the mutation state. */
|
|
66
|
-
reset: () => void;
|
|
67
|
-
}
|
|
1
|
+
import { type MutationObserverOptions, type MutationObserverResult, type QueryClient, type QueryObserverOptions, type QueryObserverResult } from "@tanstack/query-core";
|
|
2
|
+
import { type MaybeRef } from "vue";
|
|
68
3
|
/**
|
|
69
|
-
* Vue composable
|
|
70
|
-
* Integrates with the API manager — your `queryFn` typically calls
|
|
71
|
-
* `useGetApi` or `useFetch` and returns the Safe Result.
|
|
4
|
+
* Vue composable for a cached query, backed by TanStack Query Core.
|
|
72
5
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
6
|
+
* Returns a reactive {@link QueryObserverResult} — read `query.data`,
|
|
7
|
+
* `query.isPending`, `query.isError`, `query.status`, etc. directly.
|
|
8
|
+
* Pass a `ref`/`computed` for `options` to react to key changes.
|
|
9
|
+
*
|
|
10
|
+
* Call it inside a component `setup` (or an active effect scope) so the
|
|
11
|
+
* observer and the options watcher are disposed automatically.
|
|
12
|
+
*
|
|
13
|
+
* @param options - TanStack query options, plain or inside a `ref`/`computed`.
|
|
14
|
+
* @param client - Optional {@link QueryClient} (defaults to the shared singleton).
|
|
15
|
+
* @returns A reactive {@link QueryObserverResult}.
|
|
76
16
|
*
|
|
77
17
|
* @example
|
|
78
18
|
* ```vue
|
|
79
19
|
* <script setup>
|
|
80
|
-
* import { useQuery } from "katanakit-js/adapters/vue";
|
|
20
|
+
* import { useQuery, useSafeQueryFn } from "katanakit-js/adapters/vue";
|
|
81
21
|
* import { useGetApi } from "katanakit-js";
|
|
82
22
|
*
|
|
83
|
-
* const
|
|
84
|
-
* queryKey:
|
|
85
|
-
* queryFn: () => useGetApi("pokeapi", "pokemonById", { params: { id:
|
|
86
|
-
* staleTime: 60_000,
|
|
23
|
+
* const query = useQuery({
|
|
24
|
+
* queryKey: ["pokemon", 25],
|
|
25
|
+
* queryFn: useSafeQueryFn(() => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } })),
|
|
87
26
|
* });
|
|
88
27
|
* </script>
|
|
28
|
+
*
|
|
29
|
+
* <template>
|
|
30
|
+
* <span v-if="query.isPending">Loading…</span>
|
|
31
|
+
* <span v-else-if="query.isError">{{ query.error?.message }}</span>
|
|
32
|
+
* <span v-else>{{ query.data?.name }}</span>
|
|
33
|
+
* </template>
|
|
89
34
|
* ```
|
|
90
35
|
*/
|
|
91
|
-
export declare function useQuery<
|
|
36
|
+
export declare function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData>(options: MaybeRef<QueryObserverOptions<TQueryFnData, TError, TData>>, client?: QueryClient): QueryObserverResult<TData, TError>;
|
|
92
37
|
/**
|
|
93
|
-
* Vue composable for
|
|
94
|
-
* Does not cache — returns a `mutate` function that executes the mutation.
|
|
38
|
+
* Vue composable for a mutation, backed by TanStack Query Core.
|
|
95
39
|
*
|
|
96
|
-
* @param
|
|
97
|
-
* @
|
|
40
|
+
* @param options - TanStack mutation options, plain or inside a `ref`/`computed`.
|
|
41
|
+
* @param client - Optional {@link QueryClient} (defaults to the shared singleton).
|
|
42
|
+
* @returns A reactive {@link MutationObserverResult}.
|
|
98
43
|
*
|
|
99
44
|
* @example
|
|
100
45
|
* ```vue
|
|
@@ -103,12 +48,16 @@ export declare function useQuery<T>(config: UseQueryConfig<T>, client?: QueryCli
|
|
|
103
48
|
* import { usePost } from "katanakit-js";
|
|
104
49
|
*
|
|
105
50
|
* const qc = useQueryClient();
|
|
106
|
-
* const
|
|
107
|
-
* mutationFn: (name: string) => usePost("
|
|
51
|
+
* const mutation = useMutation({
|
|
52
|
+
* mutationFn: (name: string) => usePost("api", "createUser", { name }),
|
|
108
53
|
* onSuccess: () => qc.invalidateQueries({ queryKey: ["users"] }),
|
|
109
54
|
* });
|
|
110
55
|
* </script>
|
|
56
|
+
*
|
|
57
|
+
* <template>
|
|
58
|
+
* <button :disabled="mutation.isPending" @click="mutation.mutate('Ada')">Create</button>
|
|
59
|
+
* </template>
|
|
111
60
|
* ```
|
|
112
61
|
*/
|
|
113
|
-
export declare function useMutation<TData = unknown, TVariables = unknown>(
|
|
62
|
+
export declare function useMutation<TData = unknown, TError = Error, TVariables = void, TContext = unknown>(options: MaybeRef<MutationObserverOptions<TData, TError, TVariables, TContext>>, client?: QueryClient): MutationObserverResult<TData, TError, TVariables, TContext>;
|
|
114
63
|
//# sourceMappingURL=query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAEhB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEN,KAAK,QAAQ,EAKb,MAAM,KAAK,CAAC;AAIb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,QAAQ,CAAC,YAAY,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,KAAK,GAAG,YAAY,EACpF,OAAO,EAAE,QAAQ,CAAC,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,EACpE,MAAM,CAAC,EAAE,WAAW,GAClB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAwBpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,WAAW,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,UAAU,GAAG,IAAI,EAAE,QAAQ,GAAG,OAAO,EACjG,OAAO,EAAE,QAAQ,CAAC,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,EAC/E,MAAM,CAAC,EAAE,WAAW,GAClB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CA0B7D"}
|
|
@@ -1,130 +1,58 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
// useQuery
|
|
5
|
-
// ============================================================
|
|
1
|
+
import { MutationObserver, QueryObserver, } from "@tanstack/query-core";
|
|
2
|
+
import { getCurrentScope, onScopeDispose, shallowReactive, toValue, watch, } from "vue";
|
|
3
|
+
import { useQueryClient } from "../../core/services/query.service.js";
|
|
6
4
|
/**
|
|
7
|
-
* Vue composable
|
|
8
|
-
* Integrates with the API manager — your `queryFn` typically calls
|
|
9
|
-
* `useGetApi` or `useFetch` and returns the Safe Result.
|
|
5
|
+
* Vue composable for a cached query, backed by TanStack Query Core.
|
|
10
6
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* Returns a reactive {@link QueryObserverResult} — read `query.data`,
|
|
8
|
+
* `query.isPending`, `query.isError`, `query.status`, etc. directly.
|
|
9
|
+
* Pass a `ref`/`computed` for `options` to react to key changes.
|
|
10
|
+
*
|
|
11
|
+
* Call it inside a component `setup` (or an active effect scope) so the
|
|
12
|
+
* observer and the options watcher are disposed automatically.
|
|
13
|
+
*
|
|
14
|
+
* @param options - TanStack query options, plain or inside a `ref`/`computed`.
|
|
15
|
+
* @param client - Optional {@link QueryClient} (defaults to the shared singleton).
|
|
16
|
+
* @returns A reactive {@link QueryObserverResult}.
|
|
14
17
|
*
|
|
15
18
|
* @example
|
|
16
19
|
* ```vue
|
|
17
20
|
* <script setup>
|
|
18
|
-
* import { useQuery } from "katanakit-js/adapters/vue";
|
|
21
|
+
* import { useQuery, useSafeQueryFn } from "katanakit-js/adapters/vue";
|
|
19
22
|
* import { useGetApi } from "katanakit-js";
|
|
20
23
|
*
|
|
21
|
-
* const
|
|
22
|
-
* queryKey:
|
|
23
|
-
* queryFn: () => useGetApi("pokeapi", "pokemonById", { params: { id:
|
|
24
|
-
* staleTime: 60_000,
|
|
24
|
+
* const query = useQuery({
|
|
25
|
+
* queryKey: ["pokemon", 25],
|
|
26
|
+
* queryFn: useSafeQueryFn(() => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } })),
|
|
25
27
|
* });
|
|
26
28
|
* </script>
|
|
29
|
+
*
|
|
30
|
+
* <template>
|
|
31
|
+
* <span v-if="query.isPending">Loading…</span>
|
|
32
|
+
* <span v-else-if="query.isError">{{ query.error?.message }}</span>
|
|
33
|
+
* <span v-else>{{ query.data?.name }}</span>
|
|
34
|
+
* </template>
|
|
27
35
|
* ```
|
|
28
36
|
*/
|
|
29
|
-
export function useQuery(
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
let stopSubscription = null;
|
|
40
|
-
const syncFromState = (state) => {
|
|
41
|
-
if (disposed)
|
|
42
|
-
return;
|
|
43
|
-
data.value = state.data;
|
|
44
|
-
error.value = state.error;
|
|
45
|
-
isLoading.value = state.isLoading;
|
|
46
|
-
isSuccess.value = state.isSuccess;
|
|
47
|
-
isError.value = state.isError;
|
|
48
|
-
isStale.value = state.isStale;
|
|
49
|
-
status.value = state.status;
|
|
50
|
-
};
|
|
51
|
-
const runQuery = async () => {
|
|
52
|
-
if (disposed)
|
|
53
|
-
return;
|
|
54
|
-
const enabled = toValue(config.enabled) ?? true;
|
|
55
|
-
if (!enabled)
|
|
56
|
-
return;
|
|
57
|
-
const qKey = toValue(config.queryKey);
|
|
58
|
-
const staleTime = toValue(config.staleTime) ?? 0;
|
|
59
|
-
const refetchOnFocus = toValue(config.refetchOnWindowFocus) ?? true;
|
|
60
|
-
// Unsubscribe from previous key.
|
|
61
|
-
stopSubscription?.();
|
|
62
|
-
// Subscribe to state updates.
|
|
63
|
-
stopSubscription = qc.subscribe(qKey, (state) => {
|
|
64
|
-
syncFromState(state);
|
|
65
|
-
});
|
|
66
|
-
// Sync initial state.
|
|
67
|
-
const existing = qc.getQueryState(qKey);
|
|
68
|
-
if (existing)
|
|
69
|
-
syncFromState(existing);
|
|
70
|
-
// Fetch if needed.
|
|
71
|
-
try {
|
|
72
|
-
await qc.fetchQuery({
|
|
73
|
-
queryKey: qKey,
|
|
74
|
-
queryFn: config.queryFn,
|
|
75
|
-
staleTime,
|
|
76
|
-
cacheTime: config.cacheTime,
|
|
77
|
-
retry: config.retry,
|
|
78
|
-
retryDelay: config.retryDelay,
|
|
79
|
-
refetchOnWindowFocus: refetchOnFocus,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
// Error is in state; no need to throw.
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
// Watch reactive query key for changes.
|
|
87
|
-
watch(() => toValue(config.queryKey), () => {
|
|
88
|
-
void runQuery();
|
|
89
|
-
}, { deep: true });
|
|
90
|
-
// Watch enabled flag.
|
|
91
|
-
if (typeof config.enabled === "object" && "value" in config.enabled) {
|
|
92
|
-
watch(() => toValue(config.enabled), (enabled) => {
|
|
93
|
-
if (enabled)
|
|
94
|
-
void runQuery();
|
|
95
|
-
});
|
|
37
|
+
export function useQuery(options, client) {
|
|
38
|
+
const queryClient = client ?? useQueryClient();
|
|
39
|
+
const observer = new QueryObserver(queryClient, queryClient.defaultQueryOptions(toValue(options)));
|
|
40
|
+
const state = shallowReactive({ ...observer.getCurrentResult() });
|
|
41
|
+
const unsubscribe = observer.subscribe((result) => {
|
|
42
|
+
Object.assign(state, result);
|
|
43
|
+
});
|
|
44
|
+
watch(() => toValue(options), (next) => observer.setOptions(queryClient.defaultQueryOptions(next)), { deep: true });
|
|
45
|
+
if (getCurrentScope()) {
|
|
46
|
+
onScopeDispose(unsubscribe);
|
|
96
47
|
}
|
|
97
|
-
|
|
98
|
-
void runQuery();
|
|
99
|
-
// Cleanup on unmount (only inside a component instance; skipped in SSR).
|
|
100
|
-
if (getCurrentInstance()) {
|
|
101
|
-
onUnmounted(() => {
|
|
102
|
-
disposed = true;
|
|
103
|
-
stopSubscription?.();
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
const refetch = async () => {
|
|
107
|
-
const qKey = toValue(config.queryKey);
|
|
108
|
-
await qc.fetchQuery({
|
|
109
|
-
queryKey: qKey,
|
|
110
|
-
queryFn: config.queryFn,
|
|
111
|
-
staleTime: 0, // Force refetch.
|
|
112
|
-
cacheTime: config.cacheTime,
|
|
113
|
-
retry: config.retry,
|
|
114
|
-
retryDelay: config.retryDelay,
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
return { data, error, isLoading, isSuccess, isError, isStale, status, refetch };
|
|
48
|
+
return state;
|
|
118
49
|
}
|
|
119
|
-
// ============================================================
|
|
120
|
-
// useMutation
|
|
121
|
-
// ============================================================
|
|
122
50
|
/**
|
|
123
|
-
* Vue composable for
|
|
124
|
-
* Does not cache — returns a `mutate` function that executes the mutation.
|
|
51
|
+
* Vue composable for a mutation, backed by TanStack Query Core.
|
|
125
52
|
*
|
|
126
|
-
* @param
|
|
127
|
-
* @
|
|
53
|
+
* @param options - TanStack mutation options, plain or inside a `ref`/`computed`.
|
|
54
|
+
* @param client - Optional {@link QueryClient} (defaults to the shared singleton).
|
|
55
|
+
* @returns A reactive {@link MutationObserverResult}.
|
|
128
56
|
*
|
|
129
57
|
* @example
|
|
130
58
|
* ```vue
|
|
@@ -133,67 +61,28 @@ export function useQuery(config, client) {
|
|
|
133
61
|
* import { usePost } from "katanakit-js";
|
|
134
62
|
*
|
|
135
63
|
* const qc = useQueryClient();
|
|
136
|
-
* const
|
|
137
|
-
* mutationFn: (name: string) => usePost("
|
|
64
|
+
* const mutation = useMutation({
|
|
65
|
+
* mutationFn: (name: string) => usePost("api", "createUser", { name }),
|
|
138
66
|
* onSuccess: () => qc.invalidateQueries({ queryKey: ["users"] }),
|
|
139
67
|
* });
|
|
140
68
|
* </script>
|
|
69
|
+
*
|
|
70
|
+
* <template>
|
|
71
|
+
* <button :disabled="mutation.isPending" @click="mutation.mutate('Ada')">Create</button>
|
|
72
|
+
* </template>
|
|
141
73
|
* ```
|
|
142
74
|
*/
|
|
143
|
-
export function useMutation(
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
try {
|
|
156
|
-
const result = await config.mutationFn(variables);
|
|
157
|
-
if (result.ok) {
|
|
158
|
-
data.value = result.data;
|
|
159
|
-
error.value = null;
|
|
160
|
-
isSuccess.value = true;
|
|
161
|
-
status.value = "success";
|
|
162
|
-
config.onSuccess?.(result.data, variables);
|
|
163
|
-
config.onSettled?.(result.data, null, variables);
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
data.value = null;
|
|
167
|
-
error.value = result.error;
|
|
168
|
-
isError.value = true;
|
|
169
|
-
status.value = "error";
|
|
170
|
-
config.onError?.(result.error, variables);
|
|
171
|
-
config.onSettled?.(null, result.error, variables);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
catch (err) {
|
|
175
|
-
const apiError = err instanceof Error
|
|
176
|
-
? { message: err.message, status: 0 }
|
|
177
|
-
: { message: String(err), status: 0 };
|
|
178
|
-
data.value = null;
|
|
179
|
-
error.value = apiError;
|
|
180
|
-
isError.value = true;
|
|
181
|
-
status.value = "error";
|
|
182
|
-
config.onError?.(apiError, variables);
|
|
183
|
-
config.onSettled?.(null, apiError, variables);
|
|
184
|
-
}
|
|
185
|
-
finally {
|
|
186
|
-
isLoading.value = false;
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
const reset = () => {
|
|
190
|
-
data.value = null;
|
|
191
|
-
error.value = null;
|
|
192
|
-
isLoading.value = false;
|
|
193
|
-
isSuccess.value = false;
|
|
194
|
-
isError.value = false;
|
|
195
|
-
status.value = "idle";
|
|
196
|
-
};
|
|
197
|
-
return { data, error, isLoading, isSuccess, isError, status, mutate, reset };
|
|
75
|
+
export function useMutation(options, client) {
|
|
76
|
+
const queryClient = client ?? useQueryClient();
|
|
77
|
+
const observer = new MutationObserver(queryClient, toValue(options));
|
|
78
|
+
const state = shallowReactive({ ...observer.getCurrentResult() });
|
|
79
|
+
const unsubscribe = observer.subscribe((result) => {
|
|
80
|
+
Object.assign(state, result);
|
|
81
|
+
});
|
|
82
|
+
watch(() => toValue(options), (next) => observer.setOptions(next), { deep: true });
|
|
83
|
+
if (getCurrentScope()) {
|
|
84
|
+
onScopeDispose(unsubscribe);
|
|
85
|
+
}
|
|
86
|
+
return state;
|
|
198
87
|
}
|
|
199
88
|
//# sourceMappingURL=query.js.map
|