@tanstack/angular-query-experimental 5.102.8 → 5.103.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,78 +1,221 @@
1
1
  import { DefaultError, InitialDataFunction, NonUndefinedGuard, OmitKeyof, QueryFunction, QueryKey, QueryKeyWithDataTag, SkipToken } from '@tanstack/query-core';
2
2
  import { CreateQueryOptions } from './types.js';
3
+ /**
4
+ * The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be
5
+ * `undefined` while the query is `pending`.
6
+ *
7
+ * @template TQueryFnData - The type your `queryFn` resolves to.
8
+ * @template TError - The type of errors your `queryFn` may throw.
9
+ * @template TData - The type `data` ends up as after `select` runs.
10
+ * @template TQueryKey - The type of your `queryKey`.
11
+ */
3
12
  export type UndefinedInitialDataOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
13
+ /**
14
+ * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been
15
+ * created or cached yet). If set to a function, the function will be called **once** during the shared/root
16
+ * query initialization, and be expected to synchronously return the initial data. Initial data is
17
+ * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the
18
+ * cache.
19
+ */
4
20
  initialData?: undefined | InitialDataFunction<NonUndefinedGuard<TQueryFnData>> | NonUndefinedGuard<TQueryFnData>;
5
21
  };
22
+ /**
23
+ * The options accepted by the `queryOptions` overload selected when no `initialData` is set and `queryFn` is
24
+ * not `skipToken` — same as {@link UndefinedInitialDataOptions}, but `queryFn` may not be `skipToken`.
25
+ *
26
+ * @template TQueryFnData - The type your `queryFn` resolves to.
27
+ * @template TError - The type of errors your `queryFn` may throw.
28
+ * @template TData - The type `data` ends up as after `select` runs.
29
+ * @template TQueryKey - The type of your `queryKey`.
30
+ */
6
31
  export type UnusedSkipTokenOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> = OmitKeyof<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryFn'> & {
32
+ /**
33
+ * `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If
34
+ * you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a
35
+ * fetch that fails with "Missing queryFn" unless `enabled` is `false` or a default query function has been
36
+ * defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own.
37
+ */
7
38
  queryFn?: Exclude<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'], SkipToken | undefined>;
8
39
  };
40
+ /**
41
+ * The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never
42
+ * `undefined` (unless a `select` changes `TData` to include `undefined`).
43
+ *
44
+ * @template TQueryFnData - The type your `queryFn` resolves to.
45
+ * @template TError - The type of errors your `queryFn` may throw.
46
+ * @template TData - The type `data` ends up as after `select` runs.
47
+ * @template TQueryKey - The type of your `queryKey`.
48
+ */
9
49
  export type DefinedInitialDataOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> = Omit<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryFn'> & {
50
+ /**
51
+ * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been
52
+ * created or cached yet). If set to a function, the function will be called **once** during the shared/root
53
+ * query initialization, and be expected to synchronously return the initial data. Initial data is
54
+ * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the
55
+ * cache.
56
+ */
10
57
  initialData: NonUndefinedGuard<TQueryFnData> | (() => NonUndefinedGuard<TQueryFnData>);
58
+ /**
59
+ * Optional here, but omitting it is only safe when no fetch will be attempted — for example with
60
+ * `enabled: false`, or when a default query function has been defined. Otherwise, an enabled query with no
61
+ * `queryFn` still tries to fetch and fails with a "Missing queryFn" error; `initialData` does not prevent this.
62
+ */
11
63
  queryFn?: QueryFunction<TQueryFnData, TQueryKey>;
12
64
  };
13
65
  /**
14
- * Allows sharing and re-using query options in a type-safe way.
66
+ * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
67
+ * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
68
+ * required and is the query key to generate options for.
15
69
  *
16
- * The `queryKey` will be tagged with the type from `queryFn`.
70
+ * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless
71
+ * a `select` changes `TData` to include `undefined`).
17
72
  *
18
- * **Example**
73
+ * @see {@link injectQuery} to run a query with these options.
74
+ * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
75
+ * @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `injectQuery`,
76
+ * with `initialData` set.
77
+ * @returns The same options object, typed so that `queryKey` carries the inferred data type.
19
78
  *
20
- * ```ts
21
- * const { queryKey } = queryOptions({
22
- * queryKey: ['key'],
23
- * queryFn: () => Promise.resolve(5),
24
- * // ^? Promise<number>
25
- * })
79
+ * @example
80
+ * ```angular-ts
81
+ * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
26
82
  *
27
- * const queryClient = new QueryClient()
28
- * const data = queryClient.getQueryData(queryKey)
29
- * // ^? number | undefined
83
+ * export const postsOptions = queryOptions({
84
+ * queryKey: ['posts'],
85
+ * queryFn: fetchPosts,
86
+ * initialData: [],
87
+ * })
88
+ *
89
+ * @Component({
90
+ * selector: 'posts',
91
+ * template: `
92
+ * <!-- `postsQuery.data()` is never `undefined`, thanks to `initialData` — even if a refetch
93
+ * fails, so the list stays visible alongside the error. -->
94
+ * @if (postsQuery.isError()) {
95
+ * <span>Error: {{ postsQuery.error()?.message }}</span>
96
+ * }
97
+ * <ul>
98
+ * @for (post of postsQuery.data(); track post.id) {
99
+ * <li>{{ post.title }}</li>
100
+ * }
101
+ * </ul>
102
+ * `,
103
+ * })
104
+ * export class Posts {
105
+ * readonly postsQuery = injectQuery(() => postsOptions)
106
+ * }
30
107
  * ```
31
- * @param options - The query options to tag with the type from `queryFn`.
32
- * @returns The tagged query options.
33
108
  */
34
109
  export declare function queryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;
35
110
  /**
36
- * Allows sharing and re-using query options in a type-safe way.
111
+ * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
112
+ * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
113
+ * required and is the query key to generate options for.
37
114
  *
38
- * The `queryKey` will be tagged with the type from `queryFn`.
115
+ * @see {@link injectQuery} to run a query with these options.
116
+ * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
117
+ * @param options - The {@link UnusedSkipTokenOptions} to use — everything you can pass to `injectQuery`.
118
+ * @returns The same options object, typed so that `queryKey` carries the inferred data type.
39
119
  *
40
- * **Example**
120
+ * @example
121
+ * A parameterized factory, so the same options object can be reused per `id`:
122
+ * ```angular-ts
123
+ * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
41
124
  *
42
- * ```ts
43
- * const { queryKey } = queryOptions({
44
- * queryKey: ['key'],
45
- * queryFn: () => Promise.resolve(5),
46
- * // ^? Promise<number>
125
+ * export const postOptions = (id: string) =>
126
+ * queryOptions({
127
+ * queryKey: ['post', id],
128
+ * queryFn: () => fetchPost(id),
47
129
  * })
48
130
  *
49
- * const queryClient = new QueryClient()
50
- * const data = queryClient.getQueryData(queryKey)
51
- * // ^? number | undefined
131
+ * @Component({
132
+ * selector: 'post',
133
+ * template: `
134
+ * @if (postQuery.isPending()) {
135
+ * Loading...
136
+ * } @else if (postQuery.isError()) {
137
+ * <span>Error: {{ postQuery.error()?.message }}</span>
138
+ * } @else {
139
+ * <h1>{{ postQuery.data().title }}</h1>
140
+ * }
141
+ * `,
142
+ * })
143
+ * export class Post {
144
+ * readonly id = signal('1')
145
+ * readonly postQuery = injectQuery(() => postOptions(this.id()))
146
+ * }
52
147
  * ```
53
- * @param options - The query options to tag with the type from `queryFn`.
54
- * @returns The tagged query options.
55
148
  */
56
149
  export declare function queryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;
57
150
  /**
58
- * Allows sharing and re-using query options in a type-safe way.
151
+ * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
152
+ * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
153
+ * required and is the query key to generate options for.
154
+ *
155
+ * @see {@link injectQuery} to run a query with these options.
156
+ * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
157
+ * @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `injectQuery`.
158
+ * @returns The same options object, typed so that `queryKey` carries the inferred data type.
159
+ * @remarks This is the only overload that accepts `queryFn: skipToken`, shown below.
59
160
  *
60
- * The `queryKey` will be tagged with the type from `queryFn`.
161
+ * @example
162
+ * A parameterized factory, so the same options object can be reused per `id`:
163
+ * ```angular-ts
164
+ * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
165
+ *
166
+ * export const postOptions = (id: string) =>
167
+ * queryOptions({
168
+ * queryKey: ['post', id],
169
+ * queryFn: () => fetchPost(id),
170
+ * })
171
+ *
172
+ * @Component({
173
+ * selector: 'post',
174
+ * template: `
175
+ * @if (postQuery.isPending()) {
176
+ * Loading...
177
+ * } @else if (postQuery.isError()) {
178
+ * <span>Error: {{ postQuery.error()?.message }}</span>
179
+ * } @else {
180
+ * <h1>{{ postQuery.data().title }}</h1>
181
+ * }
182
+ * `,
183
+ * })
184
+ * export class Post {
185
+ * readonly id = signal('1')
186
+ * readonly postQuery = injectQuery(() => postOptions(this.id()))
187
+ * }
188
+ * ```
61
189
  *
62
- * **Example**
190
+ * @example
191
+ * A factory that disables the query, type safe, until `postId` is set:
192
+ * ```angular-ts
193
+ * import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query-experimental'
63
194
  *
64
- * ```ts
65
- * const { queryKey } = queryOptions({
66
- * queryKey: ['key'],
67
- * queryFn: () => Promise.resolve(5),
68
- * // ^? Promise<number>
195
+ * export const postOptions = (postId: number | undefined) =>
196
+ * queryOptions({
197
+ * queryKey: ['post', postId],
198
+ * queryFn: postId != null ? () => fetchPost(postId) : skipToken,
69
199
  * })
70
200
  *
71
- * const queryClient = new QueryClient()
72
- * const data = queryClient.getQueryData(queryKey)
73
- * // ^? number | undefined
201
+ * @Component({
202
+ * selector: 'post',
203
+ * template: `
204
+ * @if (postId() == null) {
205
+ * Select a post
206
+ * } @else if (postQuery.isPending()) {
207
+ * Loading...
208
+ * } @else if (postQuery.isError()) {
209
+ * <span>Error: {{ postQuery.error()?.message }}</span>
210
+ * } @else {
211
+ * <h1>{{ postQuery.data().title }}</h1>
212
+ * }
213
+ * `,
214
+ * })
215
+ * export class Post {
216
+ * readonly postId = signal<number | undefined>(undefined)
217
+ * readonly postQuery = injectQuery(() => postOptions(this.postId()))
218
+ * }
74
219
  * ```
75
- * @param options - The query options to tag with the type from `queryFn`.
76
- * @returns The tagged query options.
77
220
  */
78
221
  export declare function queryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;
@@ -1 +1 @@
1
- {"version":3,"file":"query-options.mjs","sources":["../src/query-options.ts"],"sourcesContent":["import type {\n DefaultError,\n InitialDataFunction,\n NonUndefinedGuard,\n OmitKeyof,\n QueryFunction,\n QueryKey,\n QueryKeyWithDataTag,\n SkipToken,\n} from '@tanstack/query-core'\nimport type { CreateQueryOptions } from './types'\n\nexport type UndefinedInitialDataOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n initialData?:\n | undefined\n | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n | NonUndefinedGuard<TQueryFnData>\n}\n\nexport type UnusedSkipTokenOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n 'queryFn'\n> & {\n queryFn?: Exclude<\n CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n SkipToken | undefined\n >\n}\n\nexport type DefinedInitialDataOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = Omit<\n CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n 'queryFn'\n> & {\n initialData:\n | NonUndefinedGuard<TQueryFnData>\n | (() => NonUndefinedGuard<TQueryFnData>)\n queryFn?: QueryFunction<TQueryFnData, TQueryKey>\n}\n\n/**\n * Allows sharing and re-using query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n *\n * **Example**\n *\n * ```ts\n * const { queryKey } = queryOptions({\n * queryKey: ['key'],\n * queryFn: () => Promise.resolve(5),\n * // ^? Promise<number>\n * })\n *\n * const queryClient = new QueryClient()\n * const data = queryClient.getQueryData(queryKey)\n * // ^? number | undefined\n * ```\n * @param options - The query options to tag with the type from `queryFn`.\n * @returns The tagged query options.\n */\nexport function queryOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> &\n QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>\n\n/**\n * Allows sharing and re-using query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n *\n * **Example**\n *\n * ```ts\n * const { queryKey } = queryOptions({\n * queryKey: ['key'],\n * queryFn: () => Promise.resolve(5),\n * // ^? Promise<number>\n * })\n *\n * const queryClient = new QueryClient()\n * const data = queryClient.getQueryData(queryKey)\n * // ^? number | undefined\n * ```\n * @param options - The query options to tag with the type from `queryFn`.\n * @returns The tagged query options.\n */\nexport function queryOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> &\n QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>\n\n/**\n * Allows sharing and re-using query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n *\n * **Example**\n *\n * ```ts\n * const { queryKey } = queryOptions({\n * queryKey: ['key'],\n * queryFn: () => Promise.resolve(5),\n * // ^? Promise<number>\n * })\n *\n * const queryClient = new QueryClient()\n * const data = queryClient.getQueryData(queryKey)\n * // ^? number | undefined\n * ```\n * @param options - The query options to tag with the type from `queryFn`.\n * @returns The tagged query options.\n */\nexport function queryOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> &\n QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>\n\n/**\n * Allows sharing and re-using query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n *\n * **Example**\n *\n * ```ts\n * const { queryKey } = queryOptions({\n * queryKey: ['key'],\n * queryFn: () => Promise.resolve(5),\n * // ^? Promise<number>\n * })\n *\n * const queryClient = new QueryClient()\n * const data = queryClient.getQueryData(queryKey)\n * // ^? number | undefined\n * ```\n * @param options - The query options to tag with the type from `queryFn`.\n * @returns The tagged query options.\n */\nexport function queryOptions(options: unknown) {\n return options\n}\n"],"names":[],"mappings":"AAwKO,SAAS,aAAa,SAAkB;AAC7C,SAAO;AACT;"}
1
+ {"version":3,"file":"query-options.mjs","sources":["../src/query-options.ts"],"sourcesContent":["import type {\n DefaultError,\n InitialDataFunction,\n NonUndefinedGuard,\n OmitKeyof,\n QueryFunction,\n QueryKey,\n QueryKeyWithDataTag,\n SkipToken,\n} from '@tanstack/query-core'\nimport type { CreateQueryOptions } from './types'\n\n/**\n * The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be\n * `undefined` while the query is `pending`.\n *\n * @template TQueryFnData - The type your `queryFn` resolves to.\n * @template TError - The type of errors your `queryFn` may throw.\n * @template TData - The type `data` ends up as after `select` runs.\n * @template TQueryKey - The type of your `queryKey`.\n */\nexport type UndefinedInitialDataOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n /**\n * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been\n * created or cached yet). If set to a function, the function will be called **once** during the shared/root\n * query initialization, and be expected to synchronously return the initial data. Initial data is\n * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the\n * cache.\n */\n initialData?:\n | undefined\n | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n | NonUndefinedGuard<TQueryFnData>\n}\n\n/**\n * The options accepted by the `queryOptions` overload selected when no `initialData` is set and `queryFn` is\n * not `skipToken` — same as {@link UndefinedInitialDataOptions}, but `queryFn` may not be `skipToken`.\n *\n * @template TQueryFnData - The type your `queryFn` resolves to.\n * @template TError - The type of errors your `queryFn` may throw.\n * @template TData - The type `data` ends up as after `select` runs.\n * @template TQueryKey - The type of your `queryKey`.\n */\nexport type UnusedSkipTokenOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n 'queryFn'\n> & {\n /**\n * `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If\n * you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a\n * fetch that fails with \"Missing queryFn\" unless `enabled` is `false` or a default query function has been\n * defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own.\n */\n queryFn?: Exclude<\n CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n SkipToken | undefined\n >\n}\n\n/**\n * The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never\n * `undefined` (unless a `select` changes `TData` to include `undefined`).\n *\n * @template TQueryFnData - The type your `queryFn` resolves to.\n * @template TError - The type of errors your `queryFn` may throw.\n * @template TData - The type `data` ends up as after `select` runs.\n * @template TQueryKey - The type of your `queryKey`.\n */\nexport type DefinedInitialDataOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = Omit<\n CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n 'queryFn'\n> & {\n /**\n * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been\n * created or cached yet). If set to a function, the function will be called **once** during the shared/root\n * query initialization, and be expected to synchronously return the initial data. Initial data is\n * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the\n * cache.\n */\n initialData:\n | NonUndefinedGuard<TQueryFnData>\n | (() => NonUndefinedGuard<TQueryFnData>)\n /**\n * Optional here, but omitting it is only safe when no fetch will be attempted — for example with\n * `enabled: false`, or when a default query function has been defined. Otherwise, an enabled query with no\n * `queryFn` still tries to fetch and fails with a \"Missing queryFn\" error; `initialData` does not prevent this.\n */\n queryFn?: QueryFunction<TQueryFnData, TQueryKey>\n}\n\n/**\n * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options\n * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is\n * required and is the query key to generate options for.\n *\n * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless\n * a `select` changes `TData` to include `undefined`).\n *\n * @see {@link injectQuery} to run a query with these options.\n * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.\n * @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `injectQuery`,\n * with `initialData` set.\n * @returns The same options object, typed so that `queryKey` carries the inferred data type.\n *\n * @example\n * ```angular-ts\n * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'\n *\n * export const postsOptions = queryOptions({\n * queryKey: ['posts'],\n * queryFn: fetchPosts,\n * initialData: [],\n * })\n *\n * @Component({\n * selector: 'posts',\n * template: `\n * <!-- `postsQuery.data()` is never `undefined`, thanks to `initialData` — even if a refetch\n * fails, so the list stays visible alongside the error. -->\n * @if (postsQuery.isError()) {\n * <span>Error: {{ postsQuery.error()?.message }}</span>\n * }\n * <ul>\n * @for (post of postsQuery.data(); track post.id) {\n * <li>{{ post.title }}</li>\n * }\n * </ul>\n * `,\n * })\n * export class Posts {\n * readonly postsQuery = injectQuery(() => postsOptions)\n * }\n * ```\n */\nexport function queryOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> &\n QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>\n\n/**\n * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options\n * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is\n * required and is the query key to generate options for.\n *\n * @see {@link injectQuery} to run a query with these options.\n * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.\n * @param options - The {@link UnusedSkipTokenOptions} to use — everything you can pass to `injectQuery`.\n * @returns The same options object, typed so that `queryKey` carries the inferred data type.\n *\n * @example\n * A parameterized factory, so the same options object can be reused per `id`:\n * ```angular-ts\n * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'\n *\n * export const postOptions = (id: string) =>\n * queryOptions({\n * queryKey: ['post', id],\n * queryFn: () => fetchPost(id),\n * })\n *\n * @Component({\n * selector: 'post',\n * template: `\n * @if (postQuery.isPending()) {\n * Loading...\n * } @else if (postQuery.isError()) {\n * <span>Error: {{ postQuery.error()?.message }}</span>\n * } @else {\n * <h1>{{ postQuery.data().title }}</h1>\n * }\n * `,\n * })\n * export class Post {\n * readonly id = signal('1')\n * readonly postQuery = injectQuery(() => postOptions(this.id()))\n * }\n * ```\n */\nexport function queryOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> &\n QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>\n\n/**\n * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options\n * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is\n * required and is the query key to generate options for.\n *\n * @see {@link injectQuery} to run a query with these options.\n * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.\n * @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `injectQuery`.\n * @returns The same options object, typed so that `queryKey` carries the inferred data type.\n * @remarks This is the only overload that accepts `queryFn: skipToken`, shown below.\n *\n * @example\n * A parameterized factory, so the same options object can be reused per `id`:\n * ```angular-ts\n * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'\n *\n * export const postOptions = (id: string) =>\n * queryOptions({\n * queryKey: ['post', id],\n * queryFn: () => fetchPost(id),\n * })\n *\n * @Component({\n * selector: 'post',\n * template: `\n * @if (postQuery.isPending()) {\n * Loading...\n * } @else if (postQuery.isError()) {\n * <span>Error: {{ postQuery.error()?.message }}</span>\n * } @else {\n * <h1>{{ postQuery.data().title }}</h1>\n * }\n * `,\n * })\n * export class Post {\n * readonly id = signal('1')\n * readonly postQuery = injectQuery(() => postOptions(this.id()))\n * }\n * ```\n *\n * @example\n * A factory that disables the query, type safe, until `postId` is set:\n * ```angular-ts\n * import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query-experimental'\n *\n * export const postOptions = (postId: number | undefined) =>\n * queryOptions({\n * queryKey: ['post', postId],\n * queryFn: postId != null ? () => fetchPost(postId) : skipToken,\n * })\n *\n * @Component({\n * selector: 'post',\n * template: `\n * @if (postId() == null) {\n * Select a post\n * } @else if (postQuery.isPending()) {\n * Loading...\n * } @else if (postQuery.isError()) {\n * <span>Error: {{ postQuery.error()?.message }}</span>\n * } @else {\n * <h1>{{ postQuery.data().title }}</h1>\n * }\n * `,\n * })\n * export class Post {\n * readonly postId = signal<number | undefined>(undefined)\n * readonly postQuery = injectQuery(() => postOptions(this.postId()))\n * }\n * ```\n */\nexport function queryOptions<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> &\n QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>\n\nexport function queryOptions(options: unknown) {\n return options\n}\n"],"names":[],"mappings":"AAkSO,SAAS,aAAa,SAAkB;AAC7C,SAAO;AACT;"}
package/types.d.ts CHANGED
@@ -1,43 +1,199 @@
1
1
  import { DefaultError, DefinedInfiniteQueryObserverResult, DefinedQueryObserverResult, InfiniteQueryObserverOptions, InfiniteQueryObserverResult, MutateFunction, MutationObserverOptions, MutationObserverResult, OmitKeyof, Override, QueryKey, QueryObserverOptions, QueryObserverResult } from '@tanstack/query-core';
2
2
  import { Signal } from '@angular/core';
3
3
  import { MapToSignals } from './signal-proxy.js';
4
+ /**
5
+ * The options shared across `angular-query-experimental`'s query functions. Extends
6
+ * {@link QueryObserverOptions} from `@tanstack/query-core` as-is — unlike `react-query`,
7
+ * `angular-query-experimental` has no extra framework-specific option here.
8
+ *
9
+ * @template TQueryFnData - The type your `queryFn` resolves to.
10
+ * @template TError - The type of errors your `queryFn` may throw.
11
+ * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no
12
+ * `select` is used.
13
+ * @template TQueryData - The type of the data actually held in the query cache — the input to `select` and
14
+ * `placeholderData`. Defaults to, and is usually the same as, `TQueryFnData`.
15
+ * @template TQueryKey - The type of your `queryKey`.
16
+ */
4
17
  export interface CreateBaseQueryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> extends QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey> {
5
18
  }
19
+ /**
20
+ * The options accepted by `injectQuery`. Same as {@link CreateBaseQueryOptions}, minus `suspense` — which
21
+ * `angular-query-experimental` doesn't support, unlike `react-query`.
22
+ *
23
+ * @template TQueryFnData - The type your `queryFn` resolves to.
24
+ * @template TError - The type of errors your `queryFn` may throw.
25
+ * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no
26
+ * `select` is used.
27
+ * @template TQueryKey - The type of your `queryKey`.
28
+ */
6
29
  export interface CreateQueryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> extends OmitKeyof<CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, 'suspense'> {
7
30
  }
8
31
  type CreateStatusBasedQueryResult<TStatus extends QueryObserverResult['status'], TData = unknown, TError = DefaultError> = Extract<QueryObserverResult<TData, TError>, {
9
32
  status: TStatus;
10
33
  }>;
34
+ /**
35
+ * The `isSuccess`/`isError`/`isPending` methods on a query result. Unlike `react-query`'s derived booleans,
36
+ * these are type-guard methods you call — `if (query.isSuccess())` — so that `query.data` narrows away
37
+ * `undefined` inside the branch, the same way `status` narrowing works on the plain object `react-query`
38
+ * returns.
39
+ *
40
+ * @template TData - The type `data` ends up as after `select` runs.
41
+ * @template TError - The type of errors your `queryFn` may throw.
42
+ */
11
43
  export interface BaseQueryNarrowing<TData = unknown, TError = DefaultError> {
12
44
  isSuccess: (this: CreateBaseQueryResult<TData, TError>) => this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<'success', TData, TError>>;
13
45
  isError: (this: CreateBaseQueryResult<TData, TError>) => this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<'error', TData, TError>>;
14
46
  isPending: (this: CreateBaseQueryResult<TData, TError>) => this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<'pending', TData, TError>>;
15
47
  }
48
+ /**
49
+ * The options accepted by `injectInfiniteQuery`. Same as {@link CreateBaseQueryOptions}, minus `suspense` —
50
+ * which `angular-query-experimental` doesn't support, unlike `react-query` — extends
51
+ * {@link InfiniteQueryObserverOptions} from `@tanstack/query-core` for the infinite-query-specific options
52
+ * (`getNextPageParam`, `initialPageParam`, etc.).
53
+ *
54
+ * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
55
+ * @template TError - The type of errors your `queryFn` may throw.
56
+ * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` here, though
57
+ * `injectInfiniteQuery` itself defaults it to `InfiniteData<TQueryFnData>` — the shape `data` actually has
58
+ * when no `select` is used.
59
+ * @template TQueryKey - The type of your `queryKey`.
60
+ * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
61
+ */
16
62
  export interface CreateInfiniteQueryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown> extends OmitKeyof<InfiniteQueryObserverOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, 'suspense'> {
17
63
  }
64
+ /**
65
+ * The result of `injectQuery` when `initialData` isn't set — `data` may be `undefined` while the query is
66
+ * `pending`. Same shape as {@link QueryObserverResult} from `@tanstack/query-core`, but value fields (like
67
+ * `data`, `error`, `status`) are exposed as a `Signal` — read them with `query.data()`, not `query.data` —
68
+ * while function fields (like `refetch`) are called directly, unchanged. `isSuccess`/`isError`/`isPending`
69
+ * are {@link BaseQueryNarrowing} type-guard methods rather than plain booleans.
70
+ * `injectInfiniteQuery` returns {@link CreateInfiniteQueryResult} instead.
71
+ *
72
+ * @template TData - The type `data` ends up as after `select` runs.
73
+ * @template TError - The type of errors your `queryFn` may throw.
74
+ */
18
75
  export type CreateBaseQueryResult<TData = unknown, TError = DefaultError, TState = QueryObserverResult<TData, TError>> = BaseQueryNarrowing<TData, TError> & MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>;
76
+ /**
77
+ * The result of `injectQuery`. Same as {@link CreateBaseQueryResult}.
78
+ *
79
+ * @template TData - The type `data` ends up as after `select` runs.
80
+ * @template TError - The type of errors your `queryFn` may throw.
81
+ */
19
82
  export type CreateQueryResult<TData = unknown, TError = DefaultError> = CreateBaseQueryResult<TData, TError>;
83
+ /**
84
+ * The result of `injectQuery` when `initialData` is set — `data` is never `undefined`. Same shape as
85
+ * {@link DefinedQueryObserverResult} from `@tanstack/query-core`, but value fields are exposed as a
86
+ * `Signal` while function fields are called directly, unchanged.
87
+ *
88
+ * @template TData - The type `data` ends up as after `select` runs.
89
+ * @template TError - The type of errors your `queryFn` may throw.
90
+ */
20
91
  export type DefinedCreateQueryResult<TData = unknown, TError = DefaultError, TState = DefinedQueryObserverResult<TData, TError>> = BaseQueryNarrowing<TData, TError> & MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>;
92
+ /**
93
+ * The result of `injectInfiniteQuery` when `initialData` isn't set — `data` may be `undefined` while the
94
+ * query is `pending`. Same shape as {@link InfiniteQueryObserverResult} from `@tanstack/query-core`, but
95
+ * value fields are exposed as a `Signal` while function fields (like `fetchNextPage`) are called directly,
96
+ * unchanged.
97
+ *
98
+ * @template TData - The type `data` ends up as after `select` runs.
99
+ * @template TError - The type of errors your `queryFn` may throw.
100
+ */
21
101
  export type CreateInfiniteQueryResult<TData = unknown, TError = DefaultError> = BaseQueryNarrowing<TData, TError> & MapToSignals<InfiniteQueryObserverResult<TData, TError>>;
102
+ /**
103
+ * The result of `injectInfiniteQuery` when `initialData` is set — `data` is never `undefined`. Same shape as
104
+ * {@link DefinedInfiniteQueryObserverResult} from `@tanstack/query-core`, but value fields are exposed as a
105
+ * `Signal` while function fields are called directly, unchanged.
106
+ *
107
+ * @template TData - The type `data` ends up as after `select` runs.
108
+ * @template TError - The type of errors your `queryFn` may throw.
109
+ */
22
110
  export type DefinedCreateInfiniteQueryResult<TData = unknown, TError = DefaultError, TDefinedInfiniteQueryObserver = DefinedInfiniteQueryObserverResult<TData, TError>> = MapToSignals<TDefinedInfiniteQueryObserver>;
111
+ /**
112
+ * The options accepted by `injectMutation`. Same as {@link MutationObserverOptions} from
113
+ * `@tanstack/query-core`, minus the internal `_defaulted` flag.
114
+ *
115
+ * @template TData - The type your mutation function resolves to.
116
+ * @template TError - The type of errors your mutation function may throw.
117
+ * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`.
118
+ * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
119
+ * their `onMutateResult` parameter — useful for optimistic-update rollback data.
120
+ */
23
121
  export interface CreateMutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> extends OmitKeyof<MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>, '_defaulted'> {
24
122
  }
123
+ /**
124
+ * The type of `mutate`, as returned by `injectMutation`. Forwards the variables (and an optional per-call
125
+ * `onSuccess`/`onError`/`onSettled`) to the underlying `mutate` call. Fire-and-forget — errors are surfaced
126
+ * through the mutation result, not thrown.
127
+ *
128
+ * @template TData - The type your mutation function resolves to.
129
+ * @template TError - The type of errors your mutation function may throw.
130
+ * @template TVariables - The type of the variable passed to `mutate`.
131
+ * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
132
+ * their `onMutateResult` parameter — useful for optimistic-update rollback data.
133
+ */
25
134
  export type CreateMutateFunction<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = (...args: Parameters<MutateFunction<TData, TError, TVariables, TOnMutateResult>>) => void;
135
+ /**
136
+ * The type of `mutateAsync`, as returned by `injectMutation`. Similar to {@link CreateMutateFunction}, but
137
+ * returns a promise which can be awaited.
138
+ *
139
+ * @template TData - The type your mutation function resolves to.
140
+ * @template TError - The type of errors your mutation function may throw.
141
+ * @template TVariables - The type of the variable passed to `mutateAsync`.
142
+ * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
143
+ * their `onMutateResult` parameter — useful for optimistic-update rollback data.
144
+ */
26
145
  export type CreateMutateAsyncFunction<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = MutateFunction<TData, TError, TVariables, TOnMutateResult>;
146
+ /**
147
+ * The pre-`Signal` shape {@link CreateMutationResult} is built from — not what `injectMutation` actually
148
+ * returns. Same as {@link MutationObserverResult} from `@tanstack/query-core`, with `mutate` narrowed to the
149
+ * fire-and-forget {@link CreateMutateFunction} signature, plus the added `mutateAsync`.
150
+ *
151
+ * @template TData - The type your mutation function resolves to.
152
+ * @template TError - The type of errors your mutation function may throw.
153
+ * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`.
154
+ * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
155
+ * their `onMutateResult` parameter — useful for optimistic-update rollback data.
156
+ */
27
157
  export type CreateBaseMutationResult<TData = unknown, TError = DefaultError, TVariables = unknown, TOnMutateResult = unknown> = Override<MutationObserverResult<TData, TError, TVariables, TOnMutateResult>, {
28
158
  mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult>;
29
159
  }> & {
160
+ /**
161
+ * Similar to `mutate`, but returns a promise which can be awaited.
162
+ */
30
163
  mutateAsync: CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult>;
31
164
  };
32
165
  type CreateStatusBasedMutationResult<TStatus extends CreateBaseMutationResult['status'], TData = unknown, TError = DefaultError, TVariables = unknown, TOnMutateResult = unknown> = Extract<CreateBaseMutationResult<TData, TError, TVariables, TOnMutateResult>, {
33
166
  status: TStatus;
34
167
  }>;
35
168
  type SignalFunction<T extends () => any> = T & Signal<ReturnType<T>>;
169
+ /**
170
+ * The `isSuccess`/`isError`/`isPending`/`isIdle` methods on a mutation result. Each is both a `Signal`
171
+ * (its current boolean value is read reactively without calling it) and a type-guard function you can
172
+ * call — `if (mutation.isSuccess())` — so that `mutation.data` narrows away `undefined` inside the branch.
173
+ *
174
+ * @template TData - The type your mutation function resolves to.
175
+ * @template TError - The type of errors your mutation function may throw.
176
+ * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`.
177
+ * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
178
+ * their `onMutateResult` parameter — useful for optimistic-update rollback data.
179
+ */
36
180
  export interface BaseMutationNarrowing<TData = unknown, TError = DefaultError, TVariables = unknown, TOnMutateResult = unknown> {
37
181
  isSuccess: SignalFunction<(this: CreateMutationResult<TData, TError, TVariables, TOnMutateResult>) => this is CreateMutationResult<TData, TError, TVariables, TOnMutateResult, CreateStatusBasedMutationResult<'success', TData, TError, TVariables, TOnMutateResult>>>;
38
182
  isError: SignalFunction<(this: CreateMutationResult<TData, TError, TVariables, TOnMutateResult>) => this is CreateMutationResult<TData, TError, TVariables, TOnMutateResult, CreateStatusBasedMutationResult<'error', TData, TError, TVariables, TOnMutateResult>>>;
39
183
  isPending: SignalFunction<(this: CreateMutationResult<TData, TError, TVariables, TOnMutateResult>) => this is CreateMutationResult<TData, TError, TVariables, TOnMutateResult, CreateStatusBasedMutationResult<'pending', TData, TError, TVariables, TOnMutateResult>>>;
40
184
  isIdle: SignalFunction<(this: CreateMutationResult<TData, TError, TVariables, TOnMutateResult>) => this is CreateMutationResult<TData, TError, TVariables, TOnMutateResult, CreateStatusBasedMutationResult<'idle', TData, TError, TVariables, TOnMutateResult>>>;
41
185
  }
186
+ /**
187
+ * The result of `injectMutation`. Based on {@link CreateBaseMutationResult}, but value fields are exposed as
188
+ * a `Signal` — read them with `mutation.data()`, not `mutation.data` — while function fields (`mutate`,
189
+ * `mutateAsync`, `reset`) are called directly, unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are
190
+ * {@link BaseMutationNarrowing} type-guard methods rather than plain booleans.
191
+ *
192
+ * @template TData - The type your mutation function resolves to.
193
+ * @template TError - The type of errors your mutation function may throw.
194
+ * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`.
195
+ * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
196
+ * their `onMutateResult` parameter — useful for optimistic-update rollback data.
197
+ */
42
198
  export type CreateMutationResult<TData = unknown, TError = DefaultError, TVariables = unknown, TOnMutateResult = unknown, TState = CreateStatusBasedMutationResult<CreateBaseMutationResult['status'], TData, TError, TVariables, TOnMutateResult>> = BaseMutationNarrowing<TData, TError, TVariables, TOnMutateResult> & MapToSignals<OmitKeyof<TState, keyof BaseMutationNarrowing, 'safely'>>;
43
199
  export {};