@tanstack/angular-query-experimental 5.103.2 → 5.103.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/dist/create-base-query.d.mts +169 -0
- package/dist/create-base-query.d.mts.map +1 -0
- package/dist/create-base-query.mjs +91 -0
- package/dist/create-base-query.mjs.map +1 -0
- package/dist/devtools/index.d.mts +3 -0
- package/dist/devtools/index.mjs +2 -0
- package/dist/devtools/production/index.d.mts +4 -0
- package/dist/devtools/production/index.mjs +2 -0
- package/dist/devtools/stub.d.mts +6 -0
- package/dist/devtools/stub.d.mts.map +1 -0
- package/dist/devtools/stub.mjs +9 -0
- package/dist/devtools/stub.mjs.map +1 -0
- package/dist/devtools/types.d.mts +107 -0
- package/dist/devtools/types.d.mts.map +1 -0
- package/dist/devtools/types.mjs +1 -0
- package/{devtools/with-devtools.d.ts → dist/devtools/with-devtools.d.mts} +6 -2
- package/dist/devtools/with-devtools.d.mts.map +1 -0
- package/dist/devtools/with-devtools.mjs +110 -0
- package/dist/devtools/with-devtools.mjs.map +1 -0
- package/dist/devtools-panel/index.d.mts +3 -0
- package/dist/devtools-panel/index.mjs +2 -0
- package/{devtools-panel/inject-devtools-panel.d.ts → dist/devtools-panel/inject-devtools-panel.d.mts} +6 -2
- package/dist/devtools-panel/inject-devtools-panel.d.mts.map +1 -0
- package/dist/devtools-panel/inject-devtools-panel.mjs +67 -0
- package/dist/devtools-panel/inject-devtools-panel.mjs.map +1 -0
- package/dist/devtools-panel/production/index.d.mts +4 -0
- package/dist/devtools-panel/production/index.mjs +2 -0
- package/dist/devtools-panel/stub.d.mts +6 -0
- package/dist/devtools-panel/stub.d.mts.map +1 -0
- package/dist/devtools-panel/stub.mjs +7 -0
- package/dist/devtools-panel/stub.mjs.map +1 -0
- package/dist/devtools-panel/types.d.mts +52 -0
- package/dist/devtools-panel/types.d.mts.map +1 -0
- package/dist/devtools-panel/types.mjs +1 -0
- package/dist/index.d.mts +16 -0
- package/{index.mjs → dist/index.mjs} +8 -21
- package/dist/index.mjs.map +1 -0
- package/{infinite-query-options.d.ts → dist/infinite-query-options.d.mts} +35 -31
- package/dist/infinite-query-options.d.mts.map +1 -0
- package/dist/infinite-query-options.mjs +8 -0
- package/dist/infinite-query-options.mjs.map +1 -0
- package/{inject-infinite-query.d.ts → dist/inject-infinite-query.d.mts} +18 -14
- package/dist/inject-infinite-query.d.mts.map +1 -0
- package/dist/inject-infinite-query.mjs +13 -0
- package/dist/inject-infinite-query.mjs.map +1 -0
- package/{inject-is-fetching.d.ts → dist/inject-is-fetching.d.mts} +14 -10
- package/dist/inject-is-fetching.d.mts.map +1 -0
- package/dist/inject-is-fetching.mjs +69 -0
- package/dist/inject-is-fetching.mjs.map +1 -0
- package/{inject-is-mutating.d.ts → dist/inject-is-mutating.d.mts} +14 -10
- package/dist/inject-is-mutating.d.mts.map +1 -0
- package/dist/inject-is-mutating.mjs +52 -0
- package/dist/inject-is-mutating.mjs.map +1 -0
- package/{inject-is-restoring.d.ts → dist/inject-is-restoring.d.mts} +13 -10
- package/dist/inject-is-restoring.d.mts.map +1 -0
- package/dist/inject-is-restoring.mjs +35 -0
- package/dist/inject-is-restoring.mjs.map +1 -0
- package/{inject-mutation-state.d.ts → dist/inject-mutation-state.d.mts} +16 -13
- package/dist/inject-mutation-state.d.mts.map +1 -0
- package/dist/inject-mutation-state.mjs +103 -0
- package/dist/inject-mutation-state.mjs.map +1 -0
- package/{inject-mutation.d.ts → dist/inject-mutation.d.mts} +15 -11
- package/dist/inject-mutation.d.mts.map +1 -0
- package/dist/inject-mutation.mjs +226 -0
- package/dist/inject-mutation.mjs.map +1 -0
- package/dist/inject-queries-experimental/index.d.mts +2 -0
- package/dist/inject-queries-experimental/index.mjs +2 -0
- package/{inject-queries.d.ts → dist/inject-queries.d.mts} +36 -55
- package/dist/inject-queries.d.mts.map +1 -0
- package/dist/inject-queries.mjs +203 -0
- package/dist/inject-queries.mjs.map +1 -0
- package/{inject-query-client.d.ts → dist/inject-query-client.d.mts} +8 -4
- package/dist/inject-query-client.d.mts.map +1 -0
- package/dist/inject-query-client.mjs +23 -0
- package/dist/inject-query-client.mjs.map +1 -0
- package/{inject-query.d.ts → dist/inject-query.d.mts} +18 -14
- package/dist/inject-query.d.mts.map +1 -0
- package/dist/inject-query.mjs +12 -0
- package/dist/inject-query.mjs.map +1 -0
- package/{mutation-options.d.ts → dist/mutation-options.d.mts} +8 -4
- package/dist/mutation-options.d.mts.map +1 -0
- package/dist/mutation-options.mjs +8 -0
- package/dist/mutation-options.mjs.map +1 -0
- package/dist/pending-tasks-compat.d.mts +10 -0
- package/dist/pending-tasks-compat.d.mts.map +1 -0
- package/dist/pending-tasks-compat.mjs +13 -0
- package/dist/pending-tasks-compat.mjs.map +1 -0
- package/{providers.d.ts → dist/providers.d.mts} +16 -13
- package/dist/providers.d.mts.map +1 -0
- package/dist/providers.mjs +124 -0
- package/dist/providers.mjs.map +1 -0
- package/{query-options.d.ts → dist/query-options.d.mts} +41 -37
- package/dist/query-options.d.mts.map +1 -0
- package/dist/query-options.mjs +8 -0
- package/dist/query-options.mjs.map +1 -0
- package/dist/signal-proxy.d.mts +13 -0
- package/dist/signal-proxy.d.mts.map +1 -0
- package/dist/signal-proxy.mjs +35 -0
- package/dist/signal-proxy.mjs.map +1 -0
- package/{types.d.ts → dist/types.d.mts} +36 -37
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +6 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +48 -20
- package/src/__tests__/infinite-query-options.test-d.ts +314 -0
- package/src/__tests__/infinite-query-options.test.ts +19 -0
- package/src/__tests__/inject-devtools-panel.test.ts +196 -0
- package/src/__tests__/inject-infinite-query.test-d.ts +66 -0
- package/src/__tests__/inject-infinite-query.test.ts +227 -0
- package/src/__tests__/inject-is-fetching.test.ts +108 -0
- package/src/__tests__/inject-is-mutating.test.ts +113 -0
- package/src/__tests__/inject-is-restoring.test.ts +93 -0
- package/src/__tests__/inject-mutation-state.test-d.ts +22 -0
- package/src/__tests__/inject-mutation-state.test.ts +198 -0
- package/src/__tests__/inject-mutation.test-d.ts +158 -0
- package/src/__tests__/inject-mutation.test.ts +1161 -0
- package/src/__tests__/inject-queries.test-d.ts +196 -0
- package/src/__tests__/inject-queries.test.ts +240 -0
- package/src/__tests__/inject-query.test-d.ts +357 -0
- package/src/__tests__/inject-query.test.ts +700 -0
- package/src/__tests__/mutation-options.test-d.ts +234 -0
- package/src/__tests__/mutation-options.test.ts +344 -0
- package/src/__tests__/pending-tasks.test.ts +644 -0
- package/src/__tests__/provide-query-client.test.ts +38 -0
- package/src/__tests__/provide-tanstack-query.test.ts +38 -0
- package/src/__tests__/query-options.test-d.ts +262 -0
- package/src/__tests__/query-options.test.ts +14 -0
- package/src/__tests__/signal-proxy.test.ts +27 -0
- package/src/__tests__/test-utils.ts +77 -0
- package/src/__tests__/with-devtools.test.ts +674 -0
- package/src/create-base-query.ts +175 -0
- package/src/devtools/index.ts +8 -0
- package/src/devtools/production/index.ts +1 -0
- package/src/devtools/stub.ts +7 -0
- package/src/devtools/types.ts +116 -0
- package/src/devtools/with-devtools.ts +182 -0
- package/src/devtools-panel/index.ts +8 -0
- package/src/devtools-panel/inject-devtools-panel.ts +110 -0
- package/src/devtools-panel/production/index.ts +1 -0
- package/src/devtools-panel/stub.ts +7 -0
- package/src/devtools-panel/types.ts +57 -0
- package/src/index.ts +60 -0
- package/src/infinite-query-options.ts +354 -0
- package/src/inject-infinite-query.ts +296 -0
- package/src/inject-is-fetching.ts +97 -0
- package/src/inject-is-mutating.ts +80 -0
- package/src/inject-is-restoring.ts +53 -0
- package/src/inject-mutation-state.ts +167 -0
- package/src/inject-mutation.ts +328 -0
- package/src/inject-queries-experimental/index.ts +1 -0
- package/src/inject-queries.ts +479 -0
- package/src/inject-query-client.ts +22 -0
- package/src/inject-query.ts +208 -0
- package/src/mutation-options.ts +121 -0
- package/src/pending-tasks-compat.ts +27 -0
- package/src/providers.ts +170 -0
- package/src/query-options.ts +292 -0
- package/src/signal-proxy.ts +46 -0
- package/src/types.ts +429 -0
- package/create-base-query.d.ts +0 -164
- package/create-base-query.mjs +0 -99
- package/create-base-query.mjs.map +0 -1
- package/devtools/index.d.ts +0 -2
- package/devtools/index.mjs +0 -5
- package/devtools/index.mjs.map +0 -1
- package/devtools/production/index.d.ts +0 -1
- package/devtools/stub.d.ts +0 -2
- package/devtools/stub.mjs +0 -8
- package/devtools/stub.mjs.map +0 -1
- package/devtools/types.d.ts +0 -103
- package/devtools/with-devtools.mjs +0 -106
- package/devtools/with-devtools.mjs.map +0 -1
- package/devtools-panel/index.d.ts +0 -2
- package/devtools-panel/index.mjs +0 -5
- package/devtools-panel/index.mjs.map +0 -1
- package/devtools-panel/inject-devtools-panel.mjs +0 -72
- package/devtools-panel/inject-devtools-panel.mjs.map +0 -1
- package/devtools-panel/production/index.d.ts +0 -1
- package/devtools-panel/stub.d.ts +0 -2
- package/devtools-panel/stub.mjs +0 -8
- package/devtools-panel/stub.mjs.map +0 -1
- package/devtools-panel/types.d.ts +0 -48
- package/index.d.ts +0 -25
- package/index.mjs.map +0 -1
- package/infinite-query-options.mjs +0 -7
- package/infinite-query-options.mjs.map +0 -1
- package/inject-infinite-query.mjs +0 -18
- package/inject-infinite-query.mjs.map +0 -1
- package/inject-is-fetching.mjs +0 -31
- package/inject-is-fetching.mjs.map +0 -1
- package/inject-is-mutating.mjs +0 -31
- package/inject-is-mutating.mjs.map +0 -1
- package/inject-is-restoring.mjs +0 -21
- package/inject-is-restoring.mjs.map +0 -1
- package/inject-mutation-state.mjs +0 -51
- package/inject-mutation-state.mjs.map +0 -1
- package/inject-mutation.mjs +0 -94
- package/inject-mutation.mjs.map +0 -1
- package/inject-queries-experimental/index.d.ts +0 -1
- package/inject-queries-experimental/index.mjs +0 -5
- package/inject-queries-experimental/index.mjs.map +0 -1
- package/inject-queries.mjs +0 -82
- package/inject-queries.mjs.map +0 -1
- package/inject-query-client.mjs +0 -9
- package/inject-query-client.mjs.map +0 -1
- package/inject-query.mjs +0 -14
- package/inject-query.mjs.map +0 -1
- package/mutation-options.mjs +0 -7
- package/mutation-options.mjs.map +0 -1
- package/pending-tasks-compat.d.ts +0 -7
- package/pending-tasks-compat.mjs +0 -19
- package/pending-tasks-compat.mjs.map +0 -1
- package/providers.mjs +0 -32
- package/providers.mjs.map +0 -1
- package/query-options.mjs +0 -7
- package/query-options.mjs.map +0 -1
- package/signal-proxy.d.ts +0 -11
- package/signal-proxy.mjs +0 -29
- package/signal-proxy.mjs.map +0 -1
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DefaultError,
|
|
3
|
+
InitialDataFunction,
|
|
4
|
+
NonUndefinedGuard,
|
|
5
|
+
OmitKeyof,
|
|
6
|
+
QueryFunction,
|
|
7
|
+
QueryKey,
|
|
8
|
+
QueryKeyWithDataTag,
|
|
9
|
+
SkipToken,
|
|
10
|
+
} from '@tanstack/query-core'
|
|
11
|
+
import type { CreateQueryOptions } from './types'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be
|
|
15
|
+
* `undefined` while the query is `pending`.
|
|
16
|
+
*
|
|
17
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
18
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
19
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
20
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
21
|
+
*/
|
|
22
|
+
export type UndefinedInitialDataOptions<
|
|
23
|
+
TQueryFnData = unknown,
|
|
24
|
+
TError = DefaultError,
|
|
25
|
+
TData = TQueryFnData,
|
|
26
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
27
|
+
> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
|
|
28
|
+
/**
|
|
29
|
+
* If set, this value will be used as the initial data for the query cache (as long as the query hasn't been
|
|
30
|
+
* created or cached yet). If set to a function, the function will be called **once** during the shared/root
|
|
31
|
+
* query initialization, and be expected to synchronously return the initial data. Initial data is
|
|
32
|
+
* considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the
|
|
33
|
+
* cache.
|
|
34
|
+
*/
|
|
35
|
+
initialData?:
|
|
36
|
+
| undefined
|
|
37
|
+
| InitialDataFunction<NonUndefinedGuard<TQueryFnData>>
|
|
38
|
+
| NonUndefinedGuard<TQueryFnData>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The options accepted by the `queryOptions` overload selected when no `initialData` is set and `queryFn` is
|
|
43
|
+
* not `skipToken` — same as {@link UndefinedInitialDataOptions}, but `queryFn` may not be `skipToken`.
|
|
44
|
+
*
|
|
45
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
46
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
47
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
48
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
49
|
+
*/
|
|
50
|
+
export type UnusedSkipTokenOptions<
|
|
51
|
+
TQueryFnData = unknown,
|
|
52
|
+
TError = DefaultError,
|
|
53
|
+
TData = TQueryFnData,
|
|
54
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
55
|
+
> = OmitKeyof<
|
|
56
|
+
CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
57
|
+
'queryFn'
|
|
58
|
+
> & {
|
|
59
|
+
/**
|
|
60
|
+
* `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If
|
|
61
|
+
* you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a
|
|
62
|
+
* fetch that fails with "Missing queryFn" unless `enabled` is `false` or a default query function has been
|
|
63
|
+
* defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own.
|
|
64
|
+
*/
|
|
65
|
+
queryFn?: Exclude<
|
|
66
|
+
CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],
|
|
67
|
+
SkipToken | undefined
|
|
68
|
+
>
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never
|
|
73
|
+
* `undefined` (unless a `select` changes `TData` to include `undefined`).
|
|
74
|
+
*
|
|
75
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
76
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
77
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
78
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
79
|
+
*/
|
|
80
|
+
export type DefinedInitialDataOptions<
|
|
81
|
+
TQueryFnData = unknown,
|
|
82
|
+
TError = DefaultError,
|
|
83
|
+
TData = TQueryFnData,
|
|
84
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
85
|
+
> = Omit<
|
|
86
|
+
CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
87
|
+
'queryFn'
|
|
88
|
+
> & {
|
|
89
|
+
/**
|
|
90
|
+
* If set, this value will be used as the initial data for the query cache (as long as the query hasn't been
|
|
91
|
+
* created or cached yet). If set to a function, the function will be called **once** during the shared/root
|
|
92
|
+
* query initialization, and be expected to synchronously return the initial data. Initial data is
|
|
93
|
+
* considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the
|
|
94
|
+
* cache.
|
|
95
|
+
*/
|
|
96
|
+
initialData:
|
|
97
|
+
NonUndefinedGuard<TQueryFnData> | (() => NonUndefinedGuard<TQueryFnData>)
|
|
98
|
+
/**
|
|
99
|
+
* Optional here, but omitting it is only safe when no fetch will be attempted — for example with
|
|
100
|
+
* `enabled: false`, or when a default query function has been defined. Otherwise, an enabled query with no
|
|
101
|
+
* `queryFn` still tries to fetch and fails with a "Missing queryFn" error; `initialData` does not prevent this.
|
|
102
|
+
*/
|
|
103
|
+
queryFn?: QueryFunction<TQueryFnData, TQueryKey>
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
|
|
108
|
+
* can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
|
|
109
|
+
* required and is the query key to generate options for.
|
|
110
|
+
*
|
|
111
|
+
* This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless
|
|
112
|
+
* a `select` changes `TData` to include `undefined`).
|
|
113
|
+
*
|
|
114
|
+
* @see {@link injectQuery} to run a query with these options.
|
|
115
|
+
* @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
|
|
116
|
+
* @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `injectQuery`,
|
|
117
|
+
* with `initialData` set.
|
|
118
|
+
* @returns The same options object, typed so that `queryKey` carries the inferred data type.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```angular-ts
|
|
122
|
+
* import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
|
|
123
|
+
*
|
|
124
|
+
* export const postsOptions = queryOptions({
|
|
125
|
+
* queryKey: ['posts'],
|
|
126
|
+
* queryFn: fetchPosts,
|
|
127
|
+
* initialData: [],
|
|
128
|
+
* })
|
|
129
|
+
*
|
|
130
|
+
* @Component({
|
|
131
|
+
* selector: 'posts',
|
|
132
|
+
* template: `
|
|
133
|
+
* <!-- `postsQuery.data()` is never `undefined`, thanks to `initialData` — even if a refetch
|
|
134
|
+
* fails, so the list stays visible alongside the error. -->
|
|
135
|
+
* @if (postsQuery.isError()) {
|
|
136
|
+
* <span>Error: {{ postsQuery.error()?.message }}</span>
|
|
137
|
+
* }
|
|
138
|
+
* <ul>
|
|
139
|
+
* @for (post of postsQuery.data(); track post.id) {
|
|
140
|
+
* <li>{{ post.title }}</li>
|
|
141
|
+
* }
|
|
142
|
+
* </ul>
|
|
143
|
+
* `,
|
|
144
|
+
* })
|
|
145
|
+
* export class Posts {
|
|
146
|
+
* readonly postsQuery = injectQuery(() => postsOptions)
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export function queryOptions<
|
|
151
|
+
TQueryFnData = unknown,
|
|
152
|
+
TError = DefaultError,
|
|
153
|
+
TData = TQueryFnData,
|
|
154
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
155
|
+
>(
|
|
156
|
+
options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
157
|
+
): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> &
|
|
158
|
+
QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
|
|
162
|
+
* can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
|
|
163
|
+
* required and is the query key to generate options for.
|
|
164
|
+
*
|
|
165
|
+
* @see {@link injectQuery} to run a query with these options.
|
|
166
|
+
* @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
|
|
167
|
+
* @param options - The {@link UnusedSkipTokenOptions} to use — everything you can pass to `injectQuery`.
|
|
168
|
+
* @returns The same options object, typed so that `queryKey` carries the inferred data type.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* A parameterized factory, so the same options object can be reused per `id`:
|
|
172
|
+
* ```angular-ts
|
|
173
|
+
* import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
|
|
174
|
+
*
|
|
175
|
+
* export const postOptions = (id: string) =>
|
|
176
|
+
* queryOptions({
|
|
177
|
+
* queryKey: ['post', id],
|
|
178
|
+
* queryFn: () => fetchPost(id),
|
|
179
|
+
* })
|
|
180
|
+
*
|
|
181
|
+
* @Component({
|
|
182
|
+
* selector: 'post',
|
|
183
|
+
* template: `
|
|
184
|
+
* @if (postQuery.isPending()) {
|
|
185
|
+
* Loading...
|
|
186
|
+
* } @else if (postQuery.isError()) {
|
|
187
|
+
* <span>Error: {{ postQuery.error()?.message }}</span>
|
|
188
|
+
* } @else {
|
|
189
|
+
* <h1>{{ postQuery.data().title }}</h1>
|
|
190
|
+
* }
|
|
191
|
+
* `,
|
|
192
|
+
* })
|
|
193
|
+
* export class Post {
|
|
194
|
+
* readonly id = signal('1')
|
|
195
|
+
* readonly postQuery = injectQuery(() => postOptions(this.id()))
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export function queryOptions<
|
|
200
|
+
TQueryFnData = unknown,
|
|
201
|
+
TError = DefaultError,
|
|
202
|
+
TData = TQueryFnData,
|
|
203
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
204
|
+
>(
|
|
205
|
+
options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
206
|
+
): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> &
|
|
207
|
+
QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
|
|
211
|
+
* can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
|
|
212
|
+
* required and is the query key to generate options for.
|
|
213
|
+
*
|
|
214
|
+
* @see {@link injectQuery} to run a query with these options.
|
|
215
|
+
* @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
|
|
216
|
+
* @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `injectQuery`.
|
|
217
|
+
* @returns The same options object, typed so that `queryKey` carries the inferred data type.
|
|
218
|
+
* @remarks This is the only overload that accepts `queryFn: skipToken`, shown below.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* A parameterized factory, so the same options object can be reused per `id`:
|
|
222
|
+
* ```angular-ts
|
|
223
|
+
* import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
|
|
224
|
+
*
|
|
225
|
+
* export const postOptions = (id: string) =>
|
|
226
|
+
* queryOptions({
|
|
227
|
+
* queryKey: ['post', id],
|
|
228
|
+
* queryFn: () => fetchPost(id),
|
|
229
|
+
* })
|
|
230
|
+
*
|
|
231
|
+
* @Component({
|
|
232
|
+
* selector: 'post',
|
|
233
|
+
* template: `
|
|
234
|
+
* @if (postQuery.isPending()) {
|
|
235
|
+
* Loading...
|
|
236
|
+
* } @else if (postQuery.isError()) {
|
|
237
|
+
* <span>Error: {{ postQuery.error()?.message }}</span>
|
|
238
|
+
* } @else {
|
|
239
|
+
* <h1>{{ postQuery.data().title }}</h1>
|
|
240
|
+
* }
|
|
241
|
+
* `,
|
|
242
|
+
* })
|
|
243
|
+
* export class Post {
|
|
244
|
+
* readonly id = signal('1')
|
|
245
|
+
* readonly postQuery = injectQuery(() => postOptions(this.id()))
|
|
246
|
+
* }
|
|
247
|
+
* ```
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* A factory that disables the query, type safe, until `postId` is set:
|
|
251
|
+
* ```angular-ts
|
|
252
|
+
* import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query-experimental'
|
|
253
|
+
*
|
|
254
|
+
* export const postOptions = (postId: number | undefined) =>
|
|
255
|
+
* queryOptions({
|
|
256
|
+
* queryKey: ['post', postId],
|
|
257
|
+
* queryFn: postId != null ? () => fetchPost(postId) : skipToken,
|
|
258
|
+
* })
|
|
259
|
+
*
|
|
260
|
+
* @Component({
|
|
261
|
+
* selector: 'post',
|
|
262
|
+
* template: `
|
|
263
|
+
* @if (postId() == null) {
|
|
264
|
+
* Select a post
|
|
265
|
+
* } @else if (postQuery.isPending()) {
|
|
266
|
+
* Loading...
|
|
267
|
+
* } @else if (postQuery.isError()) {
|
|
268
|
+
* <span>Error: {{ postQuery.error()?.message }}</span>
|
|
269
|
+
* } @else {
|
|
270
|
+
* <h1>{{ postQuery.data().title }}</h1>
|
|
271
|
+
* }
|
|
272
|
+
* `,
|
|
273
|
+
* })
|
|
274
|
+
* export class Post {
|
|
275
|
+
* readonly postId = signal<number | undefined>(undefined)
|
|
276
|
+
* readonly postQuery = injectQuery(() => postOptions(this.postId()))
|
|
277
|
+
* }
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
export function queryOptions<
|
|
281
|
+
TQueryFnData = unknown,
|
|
282
|
+
TError = DefaultError,
|
|
283
|
+
TData = TQueryFnData,
|
|
284
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
285
|
+
>(
|
|
286
|
+
options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
287
|
+
): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> &
|
|
288
|
+
QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>
|
|
289
|
+
|
|
290
|
+
export function queryOptions(options: unknown) {
|
|
291
|
+
return options
|
|
292
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { computed, untracked } from '@angular/core'
|
|
2
|
+
import type { Signal } from '@angular/core'
|
|
3
|
+
|
|
4
|
+
export type MapToSignals<T> = {
|
|
5
|
+
[K in keyof T]: T[K] extends Function ? T[K] : Signal<T[K]>
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Exposes fields of an object passed via an Angular `Signal` as `Computed` signals.
|
|
10
|
+
* Functions on the object are passed through as-is.
|
|
11
|
+
* @param inputSignal - `Signal` that must return an object.
|
|
12
|
+
* @returns A proxy object with the same fields as the input object, but with each field wrapped in a `Computed` signal.
|
|
13
|
+
*/
|
|
14
|
+
export function signalProxy<TInput extends Record<string | symbol, any>>(
|
|
15
|
+
inputSignal: Signal<TInput>,
|
|
16
|
+
) {
|
|
17
|
+
const internalState = {} as MapToSignals<TInput>
|
|
18
|
+
|
|
19
|
+
return new Proxy<MapToSignals<TInput>>(internalState, {
|
|
20
|
+
get(target, prop) {
|
|
21
|
+
// first check if we have it in our internal state and return it
|
|
22
|
+
const computedField = target[prop]
|
|
23
|
+
if (computedField) return computedField
|
|
24
|
+
|
|
25
|
+
// then, check if it's a function on the resultState and return it
|
|
26
|
+
const targetField = untracked(inputSignal)[prop]
|
|
27
|
+
if (typeof targetField === 'function') return targetField
|
|
28
|
+
|
|
29
|
+
// finally, create a computed field, store it and return it
|
|
30
|
+
// @ts-expect-error
|
|
31
|
+
return (target[prop] = computed(() => inputSignal()[prop]))
|
|
32
|
+
},
|
|
33
|
+
has(_, prop) {
|
|
34
|
+
return !!untracked(inputSignal)[prop]
|
|
35
|
+
},
|
|
36
|
+
ownKeys() {
|
|
37
|
+
return Reflect.ownKeys(untracked(inputSignal))
|
|
38
|
+
},
|
|
39
|
+
getOwnPropertyDescriptor() {
|
|
40
|
+
return {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
}
|