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.
Files changed (54) hide show
  1. package/README.md +54 -55
  2. package/dist/adapters/angular/index.d.ts +1 -0
  3. package/dist/adapters/angular/index.d.ts.map +1 -1
  4. package/dist/adapters/angular/index.js +1 -0
  5. package/dist/adapters/angular/index.js.map +1 -1
  6. package/dist/adapters/angular/query.d.ts +56 -73
  7. package/dist/adapters/angular/query.d.ts.map +1 -1
  8. package/dist/adapters/angular/query.js +66 -129
  9. package/dist/adapters/angular/query.js.map +1 -1
  10. package/dist/adapters/react/index.d.ts +1 -0
  11. package/dist/adapters/react/index.d.ts.map +1 -1
  12. package/dist/adapters/react/index.js +1 -0
  13. package/dist/adapters/react/index.js.map +1 -1
  14. package/dist/adapters/react/query.d.ts +27 -72
  15. package/dist/adapters/react/query.d.ts.map +1 -1
  16. package/dist/adapters/react/query.js +51 -165
  17. package/dist/adapters/react/query.js.map +1 -1
  18. package/dist/adapters/solid/index.d.ts +1 -0
  19. package/dist/adapters/solid/index.d.ts.map +1 -1
  20. package/dist/adapters/solid/index.js +1 -0
  21. package/dist/adapters/solid/index.js.map +1 -1
  22. package/dist/adapters/solid/query.d.ts +32 -74
  23. package/dist/adapters/solid/query.d.ts.map +1 -1
  24. package/dist/adapters/solid/query.js +56 -131
  25. package/dist/adapters/solid/query.js.map +1 -1
  26. package/dist/adapters/svelte/index.d.ts +1 -0
  27. package/dist/adapters/svelte/index.d.ts.map +1 -1
  28. package/dist/adapters/svelte/index.js +1 -0
  29. package/dist/adapters/svelte/index.js.map +1 -1
  30. package/dist/adapters/svelte/query.d.ts +24 -72
  31. package/dist/adapters/svelte/query.d.ts.map +1 -1
  32. package/dist/adapters/svelte/query.js +41 -135
  33. package/dist/adapters/svelte/query.js.map +1 -1
  34. package/dist/adapters/vanilla/index.d.ts +3 -0
  35. package/dist/adapters/vanilla/index.d.ts.map +1 -0
  36. package/dist/adapters/vanilla/index.js +3 -0
  37. package/dist/adapters/vanilla/index.js.map +1 -0
  38. package/dist/adapters/vanilla/query.d.ts +69 -0
  39. package/dist/adapters/vanilla/query.d.ts.map +1 -0
  40. package/dist/adapters/vanilla/query.js +76 -0
  41. package/dist/adapters/vanilla/query.js.map +1 -0
  42. package/dist/adapters/vue/index.d.ts +1 -0
  43. package/dist/adapters/vue/index.d.ts.map +1 -1
  44. package/dist/adapters/vue/index.js +1 -0
  45. package/dist/adapters/vue/index.js.map +1 -1
  46. package/dist/adapters/vue/query.d.ts +35 -86
  47. package/dist/adapters/vue/query.d.ts.map +1 -1
  48. package/dist/adapters/vue/query.js +57 -168
  49. package/dist/adapters/vue/query.js.map +1 -1
  50. package/dist/core/services/query.service.d.ts +87 -134
  51. package/dist/core/services/query.service.d.ts.map +1 -1
  52. package/dist/core/services/query.service.js +99 -378
  53. package/dist/core/services/query.service.js.map +1 -1
  54. package/package.json +10 -3
@@ -1,93 +1,60 @@
1
- import { createEffect, createSignal, onCleanup } from "solid-js";
2
- import { useQueryClient, } from "../../core/services/query.service.js";
1
+ import { MutationObserver, QueryObserver, } from "@tanstack/query-core";
2
+ import { createEffect, onCleanup } from "solid-js";
3
+ import { createStore } from "solid-js/store";
4
+ import { useQueryClient } from "../../core/services/query.service.js";
3
5
  /**
4
- * Solid primitive that wraps the {@link QueryClient} with fine-grained signals.
5
- * Integrates with the API manager — your `queryFn` typically calls `useGetApi`
6
- * or `useFetch` and returns the Safe Result.
6
+ * Solid primitive for a cached query, backed by TanStack Query Core.
7
7
  *
8
- * @param config - Query configuration.
9
- * @param client - Optional QueryClient instance (uses global singleton by default).
10
- * @returns Signal accessors for `{ data, error, isLoading, isSuccess, isError, isStale, status }` plus `refetch`.
8
+ * Returns a reactive {@link QueryObserverResult} store — read `query.data`,
9
+ * `query.isPending`, `query.isError`, `query.status`, etc. directly. Pass a
10
+ * getter (`() => ({ queryKey, queryFn })`) to react to key changes.
11
+ *
12
+ * Call it inside a component or `createRoot` so `onCleanup` disposes the observer.
13
+ *
14
+ * @param options - TanStack query options, or a getter returning them.
15
+ * @param client - Optional {@link QueryClient} (defaults to the shared singleton).
16
+ * @returns A reactive {@link QueryObserverResult} store.
11
17
  *
12
18
  * @example
13
19
  * ```tsx
14
- * import { useQuery } from "katanakit-js/adapters/solid";
20
+ * import { Show } from "solid-js";
21
+ * import { useQuery, useSafeQueryFn } from "katanakit-js/adapters/solid";
15
22
  * import { useGetApi } from "katanakit-js";
16
23
  *
17
24
  * function Pokemon() {
18
- * const { data, isLoading, error } = useQuery({
25
+ * const query = useQuery(() => ({
19
26
  * queryKey: ["pokemon", 25],
20
- * queryFn: () => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } }),
21
- * });
22
- * return <Show when={!isLoading() && !error()} fallback={<div>Loading…</div>}>
23
- * <div>{data()?.name}</div>
24
- * </Show>;
27
+ * queryFn: useSafeQueryFn(() => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } })),
28
+ * }));
29
+ * return (
30
+ * <Show when={!query.isPending} fallback={<div>Loading…</div>}>
31
+ * <div>{query.data?.name}</div>
32
+ * </Show>
33
+ * );
25
34
  * }
26
35
  * ```
27
36
  */
28
- export function useQuery(config, client) {
29
- const qc = client ?? useQueryClient();
30
- const [data, setData] = createSignal(null);
31
- const [error, setError] = createSignal(null);
32
- const [isLoading, setIsLoading] = createSignal(false);
33
- const [isSuccess, setIsSuccess] = createSignal(false);
34
- const [isError, setIsError] = createSignal(false);
35
- const [isStale, setIsStale] = createSignal(true);
36
- const [status, setStatus] = createSignal("idle");
37
- const sync = (state) => {
38
- // Updater form avoids Solid's "function as value" ambiguity for generic T.
39
- setData(() => state.data);
40
- setError(state.error);
41
- setIsLoading(state.isLoading);
42
- setIsSuccess(state.isSuccess);
43
- setIsError(state.isError);
44
- setIsStale(state.isStale);
45
- setStatus(state.status);
46
- };
37
+ export function useQuery(options, client) {
38
+ const queryClient = client ?? useQueryClient();
39
+ const getOptions = typeof options === "function" ? options : () => options;
40
+ const observer = new QueryObserver(queryClient, queryClient.defaultQueryOptions(getOptions()));
41
+ const [state, setState] = createStore(observer.getCurrentResult());
42
+ const unsubscribe = observer.subscribe((result) => {
43
+ setState(result);
44
+ });
45
+ // Re-apply options whenever the reactive getter's dependencies change.
47
46
  createEffect(() => {
48
- const qKey = config.queryKey;
49
- const unsubscribe = qc.subscribe(qKey, (next) => sync(next));
50
- const existing = qc.getQueryState(qKey);
51
- if (existing)
52
- sync(existing);
53
- if (config.enabled !== false) {
54
- void qc
55
- .fetchQuery({
56
- queryKey: qKey,
57
- queryFn: config.queryFn,
58
- staleTime: config.staleTime,
59
- cacheTime: config.cacheTime,
60
- retry: config.retry,
61
- retryDelay: config.retryDelay,
62
- })
63
- .catch(() => {
64
- // Error is already reflected in the cache state.
65
- });
66
- }
67
- onCleanup(unsubscribe);
47
+ observer.setOptions(queryClient.defaultQueryOptions(getOptions()));
68
48
  });
69
- const refetch = async () => {
70
- await qc
71
- .fetchQuery({
72
- queryKey: config.queryKey,
73
- queryFn: config.queryFn,
74
- staleTime: 0,
75
- cacheTime: config.cacheTime,
76
- retry: config.retry,
77
- retryDelay: config.retryDelay,
78
- })
79
- .catch(() => {
80
- // Error is already reflected in the cache state.
81
- });
82
- };
83
- return { data, error, isLoading, isSuccess, isError, isStale, status, refetch };
49
+ onCleanup(unsubscribe);
50
+ return state;
84
51
  }
85
52
  /**
86
- * Solid primitive for mutations (POST/PUT/PATCH/DELETE).
87
- * Does not cache — returns a `mutate` function that executes the mutation.
53
+ * Solid primitive for a mutation, backed by TanStack Query Core.
88
54
  *
89
- * @param config - Mutation configuration.
90
- * @returns Signal accessors plus `{ mutate, reset }`.
55
+ * @param options - TanStack mutation options, or a getter returning them.
56
+ * @param client - Optional {@link QueryClient} (defaults to the shared singleton).
57
+ * @returns A reactive {@link MutationObserverResult} store.
91
58
  *
92
59
  * @example
93
60
  * ```tsx
@@ -96,68 +63,26 @@ export function useQuery(config, client) {
96
63
  *
97
64
  * function CreateUser() {
98
65
  * const qc = useQueryClient();
99
- * const { mutate, isLoading } = useMutation({
66
+ * const mutation = useMutation(() => ({
100
67
  * mutationFn: (name: string) => usePost("api", "createUser", { name }),
101
68
  * onSuccess: () => qc.invalidateQueries({ queryKey: ["users"] }),
102
- * });
103
- * return <button disabled={isLoading()} onClick={() => mutate("Ada")}>Create</button>;
69
+ * }));
70
+ * return <button disabled={mutation.isPending} onClick={() => mutation.mutate("Ada")}>Create</button>;
104
71
  * }
105
72
  * ```
106
73
  */
107
- export function useMutation(config) {
108
- const [data, setData] = createSignal(null);
109
- const [error, setError] = createSignal(null);
110
- const [isLoading, setIsLoading] = createSignal(false);
111
- const [isSuccess, setIsSuccess] = createSignal(false);
112
- const [isError, setIsError] = createSignal(false);
113
- const [status, setStatus] = createSignal("idle");
114
- const mutate = async (variables) => {
115
- setIsLoading(true);
116
- setIsSuccess(false);
117
- setIsError(false);
118
- setStatus("loading");
119
- try {
120
- const result = await config.mutationFn(variables);
121
- if (result.ok) {
122
- setData(() => result.data);
123
- setError(null);
124
- setIsSuccess(true);
125
- setStatus("success");
126
- config.onSuccess?.(result.data, variables);
127
- config.onSettled?.(result.data, null, variables);
128
- }
129
- else {
130
- setData(null);
131
- setError(result.error);
132
- setIsError(true);
133
- setStatus("error");
134
- config.onError?.(result.error, variables);
135
- config.onSettled?.(null, result.error, variables);
136
- }
137
- }
138
- catch (caught) {
139
- const apiError = caught instanceof Error
140
- ? { message: caught.message, status: 0 }
141
- : { message: String(caught), status: 0 };
142
- setData(null);
143
- setError(apiError);
144
- setIsError(true);
145
- setStatus("error");
146
- config.onError?.(apiError, variables);
147
- config.onSettled?.(null, apiError, variables);
148
- }
149
- finally {
150
- setIsLoading(false);
151
- }
152
- };
153
- const reset = () => {
154
- setData(null);
155
- setError(null);
156
- setIsLoading(false);
157
- setIsSuccess(false);
158
- setIsError(false);
159
- setStatus("idle");
160
- };
161
- return { data, error, isLoading, isSuccess, isError, status, mutate, reset };
74
+ export function useMutation(options, client) {
75
+ const queryClient = client ?? useQueryClient();
76
+ const getOptions = typeof options === "function" ? options : () => options;
77
+ const observer = new MutationObserver(queryClient, getOptions());
78
+ const [state, setState] = createStore(observer.getCurrentResult());
79
+ const unsubscribe = observer.subscribe((result) => {
80
+ setState(result);
81
+ });
82
+ createEffect(() => {
83
+ observer.setOptions(getOptions());
84
+ });
85
+ onCleanup(unsubscribe);
86
+ return state;
162
87
  }
163
88
  //# sourceMappingURL=query.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/adapters/solid/query.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/adapters/solid/query.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,gBAAgB,EAIhB,aAAa,GAGb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAOtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,QAAQ,CACvB,OAAuD,EACvD,MAAoB;IAEpB,MAAM,WAAW,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC;IAC/C,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAmB,EAAE,CAAC,OAAO,CAAC;IAE3F,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,mBAAmB,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAE/F,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,WAAW,CACpC,QAAQ,CAAC,gBAAgB,EAAE,CAC3B,CAAC;IAEF,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE;QACjD,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,uEAAuE;IACvE,YAAY,CAAC,GAAG,EAAE;QACjB,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,mBAAmB,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,WAAW,CAAC,CAAC;IAEvB,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,WAAW,CAC1B,OAEuE,EACvE,MAAoB;IAEpB,MAAM,WAAW,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC;IAC/C,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAmB,EAAE,CAAC,OAAO,CAAC;IAE3F,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;IAEjE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,WAAW,CACpC,QAAQ,CAAC,gBAAgB,EAAE,CAC3B,CAAC;IAEF,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE;QACjD,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,GAAG,EAAE;QACjB,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,WAAW,CAAC,CAAC;IAEvB,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -1,3 +1,4 @@
1
+ export { useCreateQueryClient, useInitQueryClient, useQueryClient, useSafeQueryFn, } from "../../core/services/query.service.js";
1
2
  export * from "./fetch.js";
2
3
  export * from "./query.js";
3
4
  export * from "./watch.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/svelte/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,cAAc,GACd,MAAM,sCAAsC,CAAC;AAC9C,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
@@ -1,3 +1,4 @@
1
+ export { useCreateQueryClient, useInitQueryClient, useQueryClient, useSafeQueryFn, } from "../../core/services/query.service.js";
1
2
  export * from "./fetch.js";
2
3
  export * from "./query.js";
3
4
  export * from "./watch.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/svelte/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,cAAc,GACd,MAAM,sCAAsC,CAAC;AAC9C,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
@@ -1,94 +1,44 @@
1
+ import { type MutationObserverOptions, type MutationObserverResult, type QueryClient, type QueryObserverOptions, type QueryObserverResult } from "@tanstack/query-core";
1
2
  import { type Readable } from "svelte/store";
2
- import { type QueryClient, type QueryKey, type QueryState } from "../../core/services/query.service.js";
3
- import type { ApiError, FetchResult } from "../../types/index.js";
4
- /** Configuration for `useQuery` (Svelte store factory). */
5
- export interface UseQueryConfig<T = unknown> {
6
- /** Cache key (stable array). */
7
- queryKey: QueryKey;
8
- /** Fetcher function returning a Safe Result. */
9
- queryFn: () => Promise<FetchResult<T>>;
10
- /** Time in ms before cached data is stale (default: 0). */
11
- staleTime?: number;
12
- /** Time in ms to keep unused data (default: 5 min). */
13
- cacheTime?: number;
14
- /** Retry count on failure (default: 3). */
15
- retry?: number;
16
- /** Base delay for exponential backoff (default: 1000). */
17
- retryDelay?: number;
18
- /** Whether the query is enabled (default: true). */
19
- enabled?: boolean;
20
- }
21
- /** Reactive return value of `useQuery` (Svelte readable stores). */
22
- export interface UseQueryReturn<T = unknown> {
23
- data: Readable<T | null>;
24
- error: Readable<ApiError | null>;
25
- isLoading: Readable<boolean>;
26
- isSuccess: Readable<boolean>;
27
- isError: Readable<boolean>;
28
- isStale: Readable<boolean>;
29
- status: Readable<QueryState<T>["status"]>;
30
- /** Manually refetch the query. */
31
- refetch: () => Promise<void>;
32
- }
33
- /** Configuration for `useMutation`. */
34
- export interface UseMutationConfig<TData = unknown, TVariables = unknown> {
35
- mutationFn: (variables: TVariables) => Promise<FetchResult<TData>>;
36
- onSuccess?: (data: TData, variables: TVariables) => void;
37
- onError?: (error: ApiError, variables: TVariables) => void;
38
- onSettled?: (data: TData | null, error: ApiError | null, variables: TVariables) => void;
39
- }
40
- /** Reactive return value of `useMutation`. */
41
- export interface UseMutationReturn<TData = unknown, TVariables = unknown> {
42
- data: Readable<TData | null>;
43
- error: Readable<ApiError | null>;
44
- isLoading: Readable<boolean>;
45
- isSuccess: Readable<boolean>;
46
- isError: Readable<boolean>;
47
- status: Readable<"idle" | "loading" | "success" | "error">;
48
- /** Execute the mutation. */
49
- mutate: (variables: TVariables) => Promise<void>;
50
- /** Reset the mutation state. */
51
- reset: () => void;
52
- }
53
3
  /**
54
- * Svelte store factory that wraps the {@link QueryClient}.
55
- * Integrates with the API manager — your `queryFn` typically calls `useGetApi`
56
- * or `useFetch` and returns the Safe Result.
4
+ * Svelte store factory for a cached query, backed by TanStack Query Core.
57
5
  *
58
- * Unsubscribes automatically on component destroy when called during init.
6
+ * Returns a `Readable` of TanStack's {@link QueryObserverResult}. Subscribe
7
+ * with `$query` — `$query.data`, `$query.isPending`, `$query.isError`,
8
+ * `$query.status`, etc.
59
9
  *
60
- * @param config - Query configuration.
61
- * @param client - Optional QueryClient instance (uses global singleton by default).
62
- * @returns Readable stores `{ data, error, isLoading, isSuccess, isError, isStale, status }` plus `refetch`.
10
+ * @param options - TanStack query options (`queryKey`, `queryFn`, `staleTime`, …).
11
+ * @param client - Optional {@link QueryClient} (defaults to the shared singleton).
12
+ * @returns A `Readable` of the TanStack {@link QueryObserverResult}.
63
13
  *
64
14
  * @example
65
15
  * ```svelte
66
16
  * <script lang="ts">
67
- * import { useQuery } from "katanakit-js/adapters/svelte";
17
+ * import { useQuery, useSafeQueryFn } from "katanakit-js/adapters/svelte";
68
18
  * import { useGetApi } from "katanakit-js";
69
19
  *
70
- * const { data, isLoading, error } = useQuery({
20
+ * const query = useQuery({
71
21
  * queryKey: ["pokemon", 25],
72
- * queryFn: () => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } }),
22
+ * queryFn: useSafeQueryFn(() => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } })),
73
23
  * });
74
24
  * </script>
75
25
  *
76
- * {#if $isLoading}
26
+ * {#if $query.isPending}
77
27
  * <div>Loading…</div>
78
- * {:else if $error}
79
- * <div>{$error.message}</div>
28
+ * {:else if $query.isError}
29
+ * <div>{$query.error?.message}</div>
80
30
  * {:else}
81
- * <div>{$data?.name}</div>
31
+ * <div>{$query.data?.name}</div>
82
32
  * {/if}
83
33
  * ```
84
34
  */
85
- export declare function useQuery<T>(config: UseQueryConfig<T>, client?: QueryClient): UseQueryReturn<T>;
35
+ export declare function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData>(options: QueryObserverOptions<TQueryFnData, TError, TData>, client?: QueryClient): Readable<QueryObserverResult<TData, TError>>;
86
36
  /**
87
- * Svelte store factory for mutations (POST/PUT/PATCH/DELETE).
88
- * Does not cache — returns a `mutate` function that executes the mutation.
37
+ * Svelte store factory for a mutation, backed by TanStack Query Core.
89
38
  *
90
- * @param config - Mutation configuration.
91
- * @returns Readable stores plus `{ mutate, reset }`.
39
+ * @param options - TanStack mutation options (`mutationFn`, `onSuccess`, …).
40
+ * @param client - Optional {@link QueryClient} (defaults to the shared singleton).
41
+ * @returns A `Readable` of the TanStack {@link MutationObserverResult}.
92
42
  *
93
43
  * @example
94
44
  * ```svelte
@@ -97,12 +47,14 @@ export declare function useQuery<T>(config: UseQueryConfig<T>, client?: QueryCli
97
47
  * import { usePost } from "katanakit-js";
98
48
  *
99
49
  * const qc = useQueryClient();
100
- * const { mutate, isLoading } = useMutation({
50
+ * const mutation = useMutation({
101
51
  * mutationFn: (name: string) => usePost("api", "createUser", { name }),
102
52
  * onSuccess: () => qc.invalidateQueries({ queryKey: ["users"] }),
103
53
  * });
104
54
  * </script>
55
+ *
56
+ * <button disabled={$mutation.isPending} on:click={() => $mutation.mutate("Ada")}>Create</button>
105
57
  * ```
106
58
  */
107
- export declare function useMutation<TData = unknown, TVariables = unknown>(config: UseMutationConfig<TData, TVariables>): UseMutationReturn<TData, TVariables>;
59
+ export declare function useMutation<TData = unknown, TError = Error, TVariables = void, TContext = unknown>(options: MutationObserverOptions<TData, TError, TVariables, TContext>, client?: QueryClient): Readable<MutationObserverResult<TData, TError, TVariables, TContext>>;
108
60
  //# sourceMappingURL=query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/adapters/svelte/query.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/adapters/svelte/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,EAAE,KAAK,QAAQ,EAAY,MAAM,cAAc,CAAC;AAIvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;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,QAAQ,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAS9C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,UAAU,GAAG,IAAI,EAAE,QAAQ,GAAG,OAAO,EACjG,OAAO,EAAE,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,EACrE,MAAM,CAAC,EAAE,WAAW,GAClB,QAAQ,CAAC,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAavE"}
@@ -1,103 +1,53 @@
1
- import { onDestroy } from "svelte";
2
- import { writable } from "svelte/store";
3
- import { useQueryClient, } from "../../core/services/query.service.js";
1
+ import { MutationObserver, QueryObserver, } from "@tanstack/query-core";
2
+ import { readable } from "svelte/store";
3
+ import { useQueryClient } from "../../core/services/query.service.js";
4
4
  /**
5
- * Svelte store factory that wraps the {@link QueryClient}.
6
- * Integrates with the API manager — your `queryFn` typically calls `useGetApi`
7
- * or `useFetch` and returns the Safe Result.
5
+ * Svelte store factory for a cached query, backed by TanStack Query Core.
8
6
  *
9
- * Unsubscribes automatically on component destroy when called during init.
7
+ * Returns a `Readable` of TanStack's {@link QueryObserverResult}. Subscribe
8
+ * with `$query` — `$query.data`, `$query.isPending`, `$query.isError`,
9
+ * `$query.status`, etc.
10
10
  *
11
- * @param config - Query configuration.
12
- * @param client - Optional QueryClient instance (uses global singleton by default).
13
- * @returns Readable stores `{ data, error, isLoading, isSuccess, isError, isStale, status }` plus `refetch`.
11
+ * @param options - TanStack query options (`queryKey`, `queryFn`, `staleTime`, …).
12
+ * @param client - Optional {@link QueryClient} (defaults to the shared singleton).
13
+ * @returns A `Readable` of the TanStack {@link QueryObserverResult}.
14
14
  *
15
15
  * @example
16
16
  * ```svelte
17
17
  * <script lang="ts">
18
- * import { useQuery } from "katanakit-js/adapters/svelte";
18
+ * import { useQuery, useSafeQueryFn } from "katanakit-js/adapters/svelte";
19
19
  * import { useGetApi } from "katanakit-js";
20
20
  *
21
- * const { data, isLoading, error } = useQuery({
21
+ * const query = useQuery({
22
22
  * queryKey: ["pokemon", 25],
23
- * queryFn: () => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } }),
23
+ * queryFn: useSafeQueryFn(() => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } })),
24
24
  * });
25
25
  * </script>
26
26
  *
27
- * {#if $isLoading}
27
+ * {#if $query.isPending}
28
28
  * <div>Loading…</div>
29
- * {:else if $error}
30
- * <div>{$error.message}</div>
29
+ * {:else if $query.isError}
30
+ * <div>{$query.error?.message}</div>
31
31
  * {:else}
32
- * <div>{$data?.name}</div>
32
+ * <div>{$query.data?.name}</div>
33
33
  * {/if}
34
34
  * ```
35
35
  */
36
- export function useQuery(config, client) {
37
- const qc = client ?? useQueryClient();
38
- const data = writable(null);
39
- const error = writable(null);
40
- const isLoading = writable(false);
41
- const isSuccess = writable(false);
42
- const isError = writable(false);
43
- const isStale = writable(true);
44
- const status = writable("idle");
45
- const sync = (state) => {
46
- data.set(state.data);
47
- error.set(state.error);
48
- isLoading.set(state.isLoading);
49
- isSuccess.set(state.isSuccess);
50
- isError.set(state.isError);
51
- isStale.set(state.isStale);
52
- status.set(state.status);
53
- };
54
- const qKey = config.queryKey;
55
- const unsubscribe = qc.subscribe(qKey, (next) => sync(next));
56
- const existing = qc.getQueryState(qKey);
57
- if (existing)
58
- sync(existing);
59
- if (config.enabled !== false) {
60
- void qc
61
- .fetchQuery({
62
- queryKey: qKey,
63
- queryFn: config.queryFn,
64
- staleTime: config.staleTime,
65
- cacheTime: config.cacheTime,
66
- retry: config.retry,
67
- retryDelay: config.retryDelay,
68
- })
69
- .catch(() => {
70
- // Error is already reflected in the cache state.
71
- });
72
- }
73
- try {
74
- onDestroy(unsubscribe);
75
- }
76
- catch {
77
- // Not inside a component init — the caller owns teardown.
78
- }
79
- const refetch = async () => {
80
- await qc
81
- .fetchQuery({
82
- queryKey: config.queryKey,
83
- queryFn: config.queryFn,
84
- staleTime: 0,
85
- cacheTime: config.cacheTime,
86
- retry: config.retry,
87
- retryDelay: config.retryDelay,
88
- })
89
- .catch(() => {
90
- // Error is already reflected in the cache state.
91
- });
92
- };
93
- return { data, error, isLoading, isSuccess, isError, isStale, status, refetch };
36
+ export function useQuery(options, client) {
37
+ const queryClient = client ?? useQueryClient();
38
+ const observer = new QueryObserver(queryClient, queryClient.defaultQueryOptions(options));
39
+ return readable(observer.getCurrentResult(), (set) => {
40
+ const unsubscribe = observer.subscribe((result) => set(result));
41
+ set(observer.getCurrentResult());
42
+ return () => unsubscribe();
43
+ });
94
44
  }
95
45
  /**
96
- * Svelte store factory for mutations (POST/PUT/PATCH/DELETE).
97
- * Does not cache — returns a `mutate` function that executes the mutation.
46
+ * Svelte store factory for a mutation, backed by TanStack Query Core.
98
47
  *
99
- * @param config - Mutation configuration.
100
- * @returns Readable stores plus `{ mutate, reset }`.
48
+ * @param options - TanStack mutation options (`mutationFn`, `onSuccess`, …).
49
+ * @param client - Optional {@link QueryClient} (defaults to the shared singleton).
50
+ * @returns A `Readable` of the TanStack {@link MutationObserverResult}.
101
51
  *
102
52
  * @example
103
53
  * ```svelte
@@ -106,67 +56,23 @@ export function useQuery(config, client) {
106
56
  * import { usePost } from "katanakit-js";
107
57
  *
108
58
  * const qc = useQueryClient();
109
- * const { mutate, isLoading } = useMutation({
59
+ * const mutation = useMutation({
110
60
  * mutationFn: (name: string) => usePost("api", "createUser", { name }),
111
61
  * onSuccess: () => qc.invalidateQueries({ queryKey: ["users"] }),
112
62
  * });
113
63
  * </script>
64
+ *
65
+ * <button disabled={$mutation.isPending} on:click={() => $mutation.mutate("Ada")}>Create</button>
114
66
  * ```
115
67
  */
116
- export function useMutation(config) {
117
- const data = writable(null);
118
- const error = writable(null);
119
- const isLoading = writable(false);
120
- const isSuccess = writable(false);
121
- const isError = writable(false);
122
- const status = writable("idle");
123
- const mutate = async (variables) => {
124
- isLoading.set(true);
125
- isSuccess.set(false);
126
- isError.set(false);
127
- status.set("loading");
128
- try {
129
- const result = await config.mutationFn(variables);
130
- if (result.ok) {
131
- data.set(result.data);
132
- error.set(null);
133
- isSuccess.set(true);
134
- status.set("success");
135
- config.onSuccess?.(result.data, variables);
136
- config.onSettled?.(result.data, null, variables);
137
- }
138
- else {
139
- data.set(null);
140
- error.set(result.error);
141
- isError.set(true);
142
- status.set("error");
143
- config.onError?.(result.error, variables);
144
- config.onSettled?.(null, result.error, variables);
145
- }
146
- }
147
- catch (caught) {
148
- const apiError = caught instanceof Error
149
- ? { message: caught.message, status: 0 }
150
- : { message: String(caught), status: 0 };
151
- data.set(null);
152
- error.set(apiError);
153
- isError.set(true);
154
- status.set("error");
155
- config.onError?.(apiError, variables);
156
- config.onSettled?.(null, apiError, variables);
157
- }
158
- finally {
159
- isLoading.set(false);
160
- }
161
- };
162
- const reset = () => {
163
- data.set(null);
164
- error.set(null);
165
- isLoading.set(false);
166
- isSuccess.set(false);
167
- isError.set(false);
168
- status.set("idle");
169
- };
170
- return { data, error, isLoading, isSuccess, isError, status, mutate, reset };
68
+ export function useMutation(options, client) {
69
+ const queryClient = client ?? useQueryClient();
70
+ const observer = new MutationObserver(queryClient, options);
71
+ return readable(observer.getCurrentResult(), (set) => {
72
+ const unsubscribe = observer.subscribe((result) => set(result));
73
+ // Stores are lazy: re-sync the latest result on every (re)subscribe.
74
+ set(observer.getCurrentResult());
75
+ return () => unsubscribe();
76
+ });
171
77
  }
172
78
  //# sourceMappingURL=query.js.map