@tanstack/angular-query-experimental 5.103.1 → 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.
Files changed (219) hide show
  1. package/dist/create-base-query.d.mts +169 -0
  2. package/dist/create-base-query.d.mts.map +1 -0
  3. package/dist/create-base-query.mjs +91 -0
  4. package/dist/create-base-query.mjs.map +1 -0
  5. package/dist/devtools/index.d.mts +3 -0
  6. package/dist/devtools/index.mjs +2 -0
  7. package/dist/devtools/production/index.d.mts +4 -0
  8. package/dist/devtools/production/index.mjs +2 -0
  9. package/dist/devtools/stub.d.mts +6 -0
  10. package/dist/devtools/stub.d.mts.map +1 -0
  11. package/dist/devtools/stub.mjs +9 -0
  12. package/dist/devtools/stub.mjs.map +1 -0
  13. package/dist/devtools/types.d.mts +107 -0
  14. package/dist/devtools/types.d.mts.map +1 -0
  15. package/dist/devtools/types.mjs +1 -0
  16. package/{devtools/with-devtools.d.ts → dist/devtools/with-devtools.d.mts} +6 -2
  17. package/dist/devtools/with-devtools.d.mts.map +1 -0
  18. package/dist/devtools/with-devtools.mjs +110 -0
  19. package/dist/devtools/with-devtools.mjs.map +1 -0
  20. package/dist/devtools-panel/index.d.mts +3 -0
  21. package/dist/devtools-panel/index.mjs +2 -0
  22. package/{devtools-panel/inject-devtools-panel.d.ts → dist/devtools-panel/inject-devtools-panel.d.mts} +6 -2
  23. package/dist/devtools-panel/inject-devtools-panel.d.mts.map +1 -0
  24. package/dist/devtools-panel/inject-devtools-panel.mjs +67 -0
  25. package/dist/devtools-panel/inject-devtools-panel.mjs.map +1 -0
  26. package/dist/devtools-panel/production/index.d.mts +4 -0
  27. package/dist/devtools-panel/production/index.mjs +2 -0
  28. package/dist/devtools-panel/stub.d.mts +6 -0
  29. package/dist/devtools-panel/stub.d.mts.map +1 -0
  30. package/dist/devtools-panel/stub.mjs +7 -0
  31. package/dist/devtools-panel/stub.mjs.map +1 -0
  32. package/dist/devtools-panel/types.d.mts +52 -0
  33. package/dist/devtools-panel/types.d.mts.map +1 -0
  34. package/dist/devtools-panel/types.mjs +1 -0
  35. package/dist/index.d.mts +16 -0
  36. package/{index.mjs → dist/index.mjs} +8 -21
  37. package/dist/index.mjs.map +1 -0
  38. package/{infinite-query-options.d.ts → dist/infinite-query-options.d.mts} +35 -31
  39. package/dist/infinite-query-options.d.mts.map +1 -0
  40. package/dist/infinite-query-options.mjs +8 -0
  41. package/dist/infinite-query-options.mjs.map +1 -0
  42. package/{inject-infinite-query.d.ts → dist/inject-infinite-query.d.mts} +18 -14
  43. package/dist/inject-infinite-query.d.mts.map +1 -0
  44. package/dist/inject-infinite-query.mjs +13 -0
  45. package/dist/inject-infinite-query.mjs.map +1 -0
  46. package/{inject-is-fetching.d.ts → dist/inject-is-fetching.d.mts} +14 -10
  47. package/dist/inject-is-fetching.d.mts.map +1 -0
  48. package/dist/inject-is-fetching.mjs +69 -0
  49. package/dist/inject-is-fetching.mjs.map +1 -0
  50. package/{inject-is-mutating.d.ts → dist/inject-is-mutating.d.mts} +14 -10
  51. package/dist/inject-is-mutating.d.mts.map +1 -0
  52. package/dist/inject-is-mutating.mjs +52 -0
  53. package/dist/inject-is-mutating.mjs.map +1 -0
  54. package/{inject-is-restoring.d.ts → dist/inject-is-restoring.d.mts} +13 -10
  55. package/dist/inject-is-restoring.d.mts.map +1 -0
  56. package/dist/inject-is-restoring.mjs +35 -0
  57. package/dist/inject-is-restoring.mjs.map +1 -0
  58. package/{inject-mutation-state.d.ts → dist/inject-mutation-state.d.mts} +16 -13
  59. package/dist/inject-mutation-state.d.mts.map +1 -0
  60. package/dist/inject-mutation-state.mjs +103 -0
  61. package/dist/inject-mutation-state.mjs.map +1 -0
  62. package/{inject-mutation.d.ts → dist/inject-mutation.d.mts} +15 -11
  63. package/dist/inject-mutation.d.mts.map +1 -0
  64. package/dist/inject-mutation.mjs +226 -0
  65. package/dist/inject-mutation.mjs.map +1 -0
  66. package/dist/inject-queries-experimental/index.d.mts +2 -0
  67. package/dist/inject-queries-experimental/index.mjs +2 -0
  68. package/{inject-queries.d.ts → dist/inject-queries.d.mts} +36 -55
  69. package/dist/inject-queries.d.mts.map +1 -0
  70. package/dist/inject-queries.mjs +203 -0
  71. package/dist/inject-queries.mjs.map +1 -0
  72. package/{inject-query-client.d.ts → dist/inject-query-client.d.mts} +8 -4
  73. package/dist/inject-query-client.d.mts.map +1 -0
  74. package/dist/inject-query-client.mjs +23 -0
  75. package/dist/inject-query-client.mjs.map +1 -0
  76. package/{inject-query.d.ts → dist/inject-query.d.mts} +18 -14
  77. package/dist/inject-query.d.mts.map +1 -0
  78. package/dist/inject-query.mjs +12 -0
  79. package/dist/inject-query.mjs.map +1 -0
  80. package/{mutation-options.d.ts → dist/mutation-options.d.mts} +8 -4
  81. package/dist/mutation-options.d.mts.map +1 -0
  82. package/dist/mutation-options.mjs +8 -0
  83. package/dist/mutation-options.mjs.map +1 -0
  84. package/dist/pending-tasks-compat.d.mts +10 -0
  85. package/dist/pending-tasks-compat.d.mts.map +1 -0
  86. package/dist/pending-tasks-compat.mjs +13 -0
  87. package/dist/pending-tasks-compat.mjs.map +1 -0
  88. package/{providers.d.ts → dist/providers.d.mts} +16 -13
  89. package/dist/providers.d.mts.map +1 -0
  90. package/dist/providers.mjs +124 -0
  91. package/dist/providers.mjs.map +1 -0
  92. package/{query-options.d.ts → dist/query-options.d.mts} +41 -37
  93. package/dist/query-options.d.mts.map +1 -0
  94. package/dist/query-options.mjs +8 -0
  95. package/dist/query-options.mjs.map +1 -0
  96. package/dist/signal-proxy.d.mts +13 -0
  97. package/dist/signal-proxy.d.mts.map +1 -0
  98. package/dist/signal-proxy.mjs +35 -0
  99. package/dist/signal-proxy.mjs.map +1 -0
  100. package/{types.d.ts → dist/types.d.mts} +36 -37
  101. package/dist/types.d.mts.map +1 -0
  102. package/dist/types.mjs +6 -0
  103. package/dist/types.mjs.map +1 -0
  104. package/package.json +48 -20
  105. package/src/__tests__/infinite-query-options.test-d.ts +314 -0
  106. package/src/__tests__/infinite-query-options.test.ts +19 -0
  107. package/src/__tests__/inject-devtools-panel.test.ts +196 -0
  108. package/src/__tests__/inject-infinite-query.test-d.ts +66 -0
  109. package/src/__tests__/inject-infinite-query.test.ts +227 -0
  110. package/src/__tests__/inject-is-fetching.test.ts +108 -0
  111. package/src/__tests__/inject-is-mutating.test.ts +113 -0
  112. package/src/__tests__/inject-is-restoring.test.ts +93 -0
  113. package/src/__tests__/inject-mutation-state.test-d.ts +22 -0
  114. package/src/__tests__/inject-mutation-state.test.ts +198 -0
  115. package/src/__tests__/inject-mutation.test-d.ts +158 -0
  116. package/src/__tests__/inject-mutation.test.ts +1161 -0
  117. package/src/__tests__/inject-queries.test-d.ts +196 -0
  118. package/src/__tests__/inject-queries.test.ts +240 -0
  119. package/src/__tests__/inject-query.test-d.ts +357 -0
  120. package/src/__tests__/inject-query.test.ts +700 -0
  121. package/src/__tests__/mutation-options.test-d.ts +234 -0
  122. package/src/__tests__/mutation-options.test.ts +344 -0
  123. package/src/__tests__/pending-tasks.test.ts +644 -0
  124. package/src/__tests__/provide-query-client.test.ts +38 -0
  125. package/src/__tests__/provide-tanstack-query.test.ts +38 -0
  126. package/src/__tests__/query-options.test-d.ts +262 -0
  127. package/src/__tests__/query-options.test.ts +14 -0
  128. package/src/__tests__/signal-proxy.test.ts +27 -0
  129. package/src/__tests__/test-utils.ts +77 -0
  130. package/src/__tests__/with-devtools.test.ts +674 -0
  131. package/src/create-base-query.ts +175 -0
  132. package/src/devtools/index.ts +8 -0
  133. package/src/devtools/production/index.ts +1 -0
  134. package/src/devtools/stub.ts +7 -0
  135. package/src/devtools/types.ts +116 -0
  136. package/src/devtools/with-devtools.ts +182 -0
  137. package/src/devtools-panel/index.ts +8 -0
  138. package/src/devtools-panel/inject-devtools-panel.ts +110 -0
  139. package/src/devtools-panel/production/index.ts +1 -0
  140. package/src/devtools-panel/stub.ts +7 -0
  141. package/src/devtools-panel/types.ts +57 -0
  142. package/src/index.ts +60 -0
  143. package/src/infinite-query-options.ts +354 -0
  144. package/src/inject-infinite-query.ts +296 -0
  145. package/src/inject-is-fetching.ts +97 -0
  146. package/src/inject-is-mutating.ts +80 -0
  147. package/src/inject-is-restoring.ts +53 -0
  148. package/src/inject-mutation-state.ts +167 -0
  149. package/src/inject-mutation.ts +328 -0
  150. package/src/inject-queries-experimental/index.ts +1 -0
  151. package/src/inject-queries.ts +479 -0
  152. package/src/inject-query-client.ts +22 -0
  153. package/src/inject-query.ts +208 -0
  154. package/src/mutation-options.ts +121 -0
  155. package/src/pending-tasks-compat.ts +27 -0
  156. package/src/providers.ts +170 -0
  157. package/src/query-options.ts +292 -0
  158. package/src/signal-proxy.ts +46 -0
  159. package/src/types.ts +429 -0
  160. package/create-base-query.d.ts +0 -164
  161. package/create-base-query.mjs +0 -99
  162. package/create-base-query.mjs.map +0 -1
  163. package/devtools/index.d.ts +0 -2
  164. package/devtools/index.mjs +0 -5
  165. package/devtools/index.mjs.map +0 -1
  166. package/devtools/production/index.d.ts +0 -1
  167. package/devtools/stub.d.ts +0 -2
  168. package/devtools/stub.mjs +0 -8
  169. package/devtools/stub.mjs.map +0 -1
  170. package/devtools/types.d.ts +0 -100
  171. package/devtools/with-devtools.mjs +0 -106
  172. package/devtools/with-devtools.mjs.map +0 -1
  173. package/devtools-panel/index.d.ts +0 -2
  174. package/devtools-panel/index.mjs +0 -5
  175. package/devtools-panel/index.mjs.map +0 -1
  176. package/devtools-panel/inject-devtools-panel.mjs +0 -72
  177. package/devtools-panel/inject-devtools-panel.mjs.map +0 -1
  178. package/devtools-panel/production/index.d.ts +0 -1
  179. package/devtools-panel/stub.d.ts +0 -2
  180. package/devtools-panel/stub.mjs +0 -8
  181. package/devtools-panel/stub.mjs.map +0 -1
  182. package/devtools-panel/types.d.ts +0 -48
  183. package/index.d.ts +0 -25
  184. package/index.mjs.map +0 -1
  185. package/infinite-query-options.mjs +0 -7
  186. package/infinite-query-options.mjs.map +0 -1
  187. package/inject-infinite-query.mjs +0 -18
  188. package/inject-infinite-query.mjs.map +0 -1
  189. package/inject-is-fetching.mjs +0 -31
  190. package/inject-is-fetching.mjs.map +0 -1
  191. package/inject-is-mutating.mjs +0 -31
  192. package/inject-is-mutating.mjs.map +0 -1
  193. package/inject-is-restoring.mjs +0 -21
  194. package/inject-is-restoring.mjs.map +0 -1
  195. package/inject-mutation-state.mjs +0 -51
  196. package/inject-mutation-state.mjs.map +0 -1
  197. package/inject-mutation.mjs +0 -94
  198. package/inject-mutation.mjs.map +0 -1
  199. package/inject-queries-experimental/index.d.ts +0 -1
  200. package/inject-queries-experimental/index.mjs +0 -5
  201. package/inject-queries-experimental/index.mjs.map +0 -1
  202. package/inject-queries.mjs +0 -82
  203. package/inject-queries.mjs.map +0 -1
  204. package/inject-query-client.mjs +0 -9
  205. package/inject-query-client.mjs.map +0 -1
  206. package/inject-query.mjs +0 -14
  207. package/inject-query.mjs.map +0 -1
  208. package/mutation-options.mjs +0 -7
  209. package/mutation-options.mjs.map +0 -1
  210. package/pending-tasks-compat.d.ts +0 -7
  211. package/pending-tasks-compat.mjs +0 -19
  212. package/pending-tasks-compat.mjs.map +0 -1
  213. package/providers.mjs +0 -32
  214. package/providers.mjs.map +0 -1
  215. package/query-options.mjs +0 -7
  216. package/query-options.mjs.map +0 -1
  217. package/signal-proxy.d.ts +0 -11
  218. package/signal-proxy.mjs +0 -29
  219. package/signal-proxy.mjs.map +0 -1
package/src/index.ts ADDED
@@ -0,0 +1,60 @@
1
+ /* istanbul ignore file */
2
+
3
+ // Re-export core
4
+ export * from '@tanstack/query-core'
5
+
6
+ export * from './types'
7
+
8
+ export type {
9
+ DefinedInitialDataOptions,
10
+ UndefinedInitialDataOptions,
11
+ UnusedSkipTokenOptions,
12
+ } from './query-options'
13
+ export { queryOptions } from './query-options'
14
+
15
+ export type { CreateMutationOptions } from './types'
16
+ export { mutationOptions } from './mutation-options'
17
+
18
+ export type {
19
+ DefinedInitialDataInfiniteOptions,
20
+ UndefinedInitialDataInfiniteOptions,
21
+ UnusedSkipTokenInfiniteOptions,
22
+ } from './infinite-query-options'
23
+ export { infiniteQueryOptions } from './infinite-query-options'
24
+
25
+ export type { InjectInfiniteQueryOptions } from './inject-infinite-query'
26
+ export { injectInfiniteQuery } from './inject-infinite-query'
27
+
28
+ export type { InjectIsFetchingOptions } from './inject-is-fetching'
29
+ export { injectIsFetching } from './inject-is-fetching'
30
+
31
+ export type { InjectIsMutatingOptions } from './inject-is-mutating'
32
+ export { injectIsMutating } from './inject-is-mutating'
33
+
34
+ export { injectIsRestoring, provideIsRestoring } from './inject-is-restoring'
35
+
36
+ export type { InjectMutationOptions } from './inject-mutation'
37
+ export { injectMutation } from './inject-mutation'
38
+
39
+ export type { InjectMutationStateOptions } from './inject-mutation-state'
40
+ export { injectMutationState } from './inject-mutation-state'
41
+
42
+ export type { QueriesOptions, QueriesResults } from './inject-queries'
43
+
44
+ export type { InjectQueryOptions } from './inject-query'
45
+ export { injectQuery } from './inject-query'
46
+
47
+ export { injectQueryClient } from './inject-query-client'
48
+
49
+ export type {
50
+ DevtoolsFeature,
51
+ PersistQueryClientFeature,
52
+ QueryFeature,
53
+ QueryFeatures,
54
+ } from './providers'
55
+ export {
56
+ provideAngularQuery,
57
+ provideQueryClient,
58
+ provideTanStackQuery,
59
+ queryFeature,
60
+ } from './providers'
@@ -0,0 +1,354 @@
1
+ import type {
2
+ DefaultError,
3
+ InfiniteData,
4
+ InitialDataFunction,
5
+ NonUndefinedGuard,
6
+ OmitKeyof,
7
+ QueryKey,
8
+ QueryKeyWithDataTag,
9
+ SkipToken,
10
+ } from '@tanstack/query-core'
11
+ import type { CreateInfiniteQueryOptions } from './types'
12
+
13
+ /**
14
+ * The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set — `data`
15
+ * may be `undefined` while the query is `pending`.
16
+ *
17
+ * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
18
+ * @template TError - The type of errors your `queryFn` may throw.
19
+ * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData<TQueryFnData>`,
20
+ * the shape of all fetched pages plus their page params.
21
+ * @template TQueryKey - The type of your `queryKey`.
22
+ * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
23
+ */
24
+ export type UndefinedInitialDataInfiniteOptions<
25
+ TQueryFnData,
26
+ TError = DefaultError,
27
+ TData = InfiniteData<TQueryFnData>,
28
+ TQueryKey extends QueryKey = QueryKey,
29
+ TPageParam = unknown,
30
+ > = CreateInfiniteQueryOptions<
31
+ TQueryFnData,
32
+ TError,
33
+ TData,
34
+ TQueryKey,
35
+ TPageParam
36
+ > & {
37
+ /**
38
+ * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been
39
+ * created or cached yet). If set to a function, the function will be called **once** during the shared/root
40
+ * query initialization, and be expected to synchronously return the initial data. Initial data is
41
+ * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the
42
+ * cache.
43
+ */
44
+ initialData?:
45
+ | undefined
46
+ | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>
47
+ | InitialDataFunction<
48
+ NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>
49
+ >
50
+ }
51
+
52
+ /**
53
+ * The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set and
54
+ * `queryFn` is not `skipToken` — same as {@link UndefinedInitialDataInfiniteOptions}, but `queryFn` may not be
55
+ * `skipToken`.
56
+ *
57
+ * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
58
+ * @template TError - The type of errors your `queryFn` may throw.
59
+ * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData<TQueryFnData>`,
60
+ * the shape of all fetched pages plus their page params.
61
+ * @template TQueryKey - The type of your `queryKey`.
62
+ * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
63
+ */
64
+ export type UnusedSkipTokenInfiniteOptions<
65
+ TQueryFnData,
66
+ TError = DefaultError,
67
+ TData = InfiniteData<TQueryFnData>,
68
+ TQueryKey extends QueryKey = QueryKey,
69
+ TPageParam = unknown,
70
+ > = OmitKeyof<
71
+ CreateInfiniteQueryOptions<
72
+ TQueryFnData,
73
+ TError,
74
+ TData,
75
+ TQueryKey,
76
+ TPageParam
77
+ >,
78
+ 'queryFn'
79
+ > & {
80
+ /**
81
+ * `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If
82
+ * you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a
83
+ * fetch that fails with "Missing queryFn" unless `enabled` is `false` or a default query function has been
84
+ * defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own.
85
+ */
86
+ queryFn?: Exclude<
87
+ CreateInfiniteQueryOptions<
88
+ TQueryFnData,
89
+ TError,
90
+ TData,
91
+ TQueryKey,
92
+ TPageParam
93
+ >['queryFn'],
94
+ SkipToken | undefined
95
+ >
96
+ }
97
+
98
+ /**
99
+ * The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is set — `data` is
100
+ * never `undefined` (unless a `select` changes `TData` to include `undefined`).
101
+ *
102
+ * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
103
+ * @template TError - The type of errors your `queryFn` may throw.
104
+ * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData<TQueryFnData>`,
105
+ * the shape of all fetched pages plus their page params.
106
+ * @template TQueryKey - The type of your `queryKey`.
107
+ * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
108
+ */
109
+ export type DefinedInitialDataInfiniteOptions<
110
+ TQueryFnData,
111
+ TError = DefaultError,
112
+ TData = InfiniteData<TQueryFnData>,
113
+ TQueryKey extends QueryKey = QueryKey,
114
+ TPageParam = unknown,
115
+ > = CreateInfiniteQueryOptions<
116
+ TQueryFnData,
117
+ TError,
118
+ TData,
119
+ TQueryKey,
120
+ TPageParam
121
+ > & {
122
+ /**
123
+ * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been
124
+ * created or cached yet). If set to a function, the function will be called **once** during the shared/root
125
+ * query initialization, and be expected to synchronously return the initial data. Initial data is
126
+ * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the
127
+ * cache.
128
+ */
129
+ initialData:
130
+ | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>
131
+ | (() => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>)
132
+ | undefined
133
+ }
134
+
135
+ /**
136
+ * You can generally pass everything to `infiniteQueryOptions` that you can also pass to
137
+ * `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as
138
+ * `queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options
139
+ * for.
140
+ *
141
+ * This overload is selected when `initialData` is set.
142
+ *
143
+ * @see {@link injectInfiniteQuery} to run an infinite query with these options.
144
+ * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to
145
+ * `injectInfiniteQuery`, with `initialData` set.
146
+ * @returns The same options object, typed so that `queryKey` carries the inferred data type.
147
+ * @remarks See {@link injectInfiniteQuery} for examples that fetch further pages, from a button click or
148
+ * automatically as the user scrolls.
149
+ *
150
+ * @example
151
+ * ```angular-ts
152
+ * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental'
153
+ *
154
+ * export const projectsOptions = infiniteQueryOptions({
155
+ * queryKey: ['projects'],
156
+ * queryFn: ({ pageParam }) => fetchProjects(pageParam),
157
+ * initialPageParam: 0,
158
+ * getNextPageParam: (lastPage) => lastPage.nextId,
159
+ * initialData: { pages: [], pageParams: [] },
160
+ * })
161
+ *
162
+ * @Component({
163
+ * selector: 'projects',
164
+ * template: `
165
+ * <!-- `projectsQuery.data()` is never `undefined`, thanks to `initialData` — even if a
166
+ * refetch fails, so the list stays visible alongside the error. -->
167
+ * <ul>
168
+ * @for (page of projectsQuery.data().pages; track $index) {
169
+ * @for (project of page.projects; track project.id) {
170
+ * <li>{{ project.name }}</li>
171
+ * }
172
+ * }
173
+ * </ul>
174
+ * `,
175
+ * })
176
+ * export class Projects {
177
+ * readonly projectsQuery = injectInfiniteQuery(() => projectsOptions)
178
+ * }
179
+ * ```
180
+ */
181
+ export function infiniteQueryOptions<
182
+ TQueryFnData,
183
+ TError = DefaultError,
184
+ TData = InfiniteData<TQueryFnData>,
185
+ TQueryKey extends QueryKey = QueryKey,
186
+ TPageParam = unknown,
187
+ >(
188
+ options: DefinedInitialDataInfiniteOptions<
189
+ TQueryFnData,
190
+ TError,
191
+ TData,
192
+ TQueryKey,
193
+ TPageParam
194
+ >,
195
+ ): DefinedInitialDataInfiniteOptions<
196
+ TQueryFnData,
197
+ TError,
198
+ TData,
199
+ TQueryKey,
200
+ TPageParam
201
+ > &
202
+ QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
203
+
204
+ /**
205
+ * You can generally pass everything to `infiniteQueryOptions` that you can also pass to
206
+ * `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as
207
+ * `queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options
208
+ * for.
209
+ *
210
+ * @returns The same options object, typed so that `queryKey` carries the inferred data type.
211
+ * @remarks See {@link injectInfiniteQuery} for examples that fetch further pages, from a button click or
212
+ * automatically as the user scrolls.
213
+ *
214
+ * @example
215
+ * A parameterized factory, so the same options object can be reused per `postId`:
216
+ * ```angular-ts
217
+ * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental'
218
+ *
219
+ * export const commentsOptions = (postId: string) =>
220
+ * infiniteQueryOptions({
221
+ * queryKey: ['post', postId, 'comments'],
222
+ * queryFn: ({ pageParam }) => fetchComments(postId, pageParam),
223
+ * initialPageParam: 0,
224
+ * getNextPageParam: (lastPage) => lastPage.nextId,
225
+ * })
226
+ *
227
+ * @Component({
228
+ * selector: 'comments',
229
+ * template: `
230
+ * @if (commentsQuery.isPending()) {
231
+ * Loading...
232
+ * } @else if (commentsQuery.isError()) {
233
+ * <span>Error: {{ commentsQuery.error()?.message }}</span>
234
+ * } @else {
235
+ * <ul>
236
+ * @for (page of commentsQuery.data().pages; track $index) {
237
+ * @for (comment of page.comments; track comment.id) {
238
+ * <li>{{ comment.text }}</li>
239
+ * }
240
+ * }
241
+ * </ul>
242
+ * }
243
+ * `,
244
+ * })
245
+ * export class Comments {
246
+ * readonly postId = signal('1')
247
+ * readonly commentsQuery = injectInfiniteQuery(() => commentsOptions(this.postId()))
248
+ * }
249
+ * ```
250
+ *
251
+ * @see {@link injectInfiniteQuery} to run an infinite query with these options.
252
+ * @param options - The {@link UnusedSkipTokenInfiniteOptions} to use — everything you can pass to
253
+ * `injectInfiniteQuery`.
254
+ */
255
+ export function infiniteQueryOptions<
256
+ TQueryFnData,
257
+ TError = DefaultError,
258
+ TData = InfiniteData<TQueryFnData>,
259
+ TQueryKey extends QueryKey = QueryKey,
260
+ TPageParam = unknown,
261
+ >(
262
+ options: UnusedSkipTokenInfiniteOptions<
263
+ TQueryFnData,
264
+ TError,
265
+ TData,
266
+ TQueryKey,
267
+ TPageParam
268
+ >,
269
+ ): UnusedSkipTokenInfiniteOptions<
270
+ TQueryFnData,
271
+ TError,
272
+ TData,
273
+ TQueryKey,
274
+ TPageParam
275
+ > &
276
+ QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
277
+
278
+ /**
279
+ * You can generally pass everything to `infiniteQueryOptions` that you can also pass to
280
+ * `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as
281
+ * `queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options
282
+ * for.
283
+ *
284
+ * @returns The same options object, typed so that `queryKey` carries the inferred data type.
285
+ * @remarks See {@link injectInfiniteQuery} for examples that fetch further pages (from a button click or
286
+ * automatically as the user scrolls) and that use `skipToken` to disable the query until `postId` is set.
287
+ *
288
+ * @example
289
+ * A parameterized factory, so the same options object can be reused per `postId`:
290
+ * ```angular-ts
291
+ * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental'
292
+ *
293
+ * export const commentsOptions = (postId: string) =>
294
+ * infiniteQueryOptions({
295
+ * queryKey: ['post', postId, 'comments'],
296
+ * queryFn: ({ pageParam }) => fetchComments(postId, pageParam),
297
+ * initialPageParam: 0,
298
+ * getNextPageParam: (lastPage) => lastPage.nextId,
299
+ * })
300
+ *
301
+ * @Component({
302
+ * selector: 'comments',
303
+ * template: `
304
+ * @if (commentsQuery.isPending()) {
305
+ * Loading...
306
+ * } @else if (commentsQuery.isError()) {
307
+ * <span>Error: {{ commentsQuery.error()?.message }}</span>
308
+ * } @else {
309
+ * <ul>
310
+ * @for (page of commentsQuery.data().pages; track $index) {
311
+ * @for (comment of page.comments; track comment.id) {
312
+ * <li>{{ comment.text }}</li>
313
+ * }
314
+ * }
315
+ * </ul>
316
+ * }
317
+ * `,
318
+ * })
319
+ * export class Comments {
320
+ * readonly postId = signal('1')
321
+ * readonly commentsQuery = injectInfiniteQuery(() => commentsOptions(this.postId()))
322
+ * }
323
+ * ```
324
+ *
325
+ * @see {@link injectInfiniteQuery} to run an infinite query with these options.
326
+ * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to
327
+ * `injectInfiniteQuery`.
328
+ */
329
+ export function infiniteQueryOptions<
330
+ TQueryFnData,
331
+ TError = DefaultError,
332
+ TData = InfiniteData<TQueryFnData>,
333
+ TQueryKey extends QueryKey = QueryKey,
334
+ TPageParam = unknown,
335
+ >(
336
+ options: UndefinedInitialDataInfiniteOptions<
337
+ TQueryFnData,
338
+ TError,
339
+ TData,
340
+ TQueryKey,
341
+ TPageParam
342
+ >,
343
+ ): UndefinedInitialDataInfiniteOptions<
344
+ TQueryFnData,
345
+ TError,
346
+ TData,
347
+ TQueryKey,
348
+ TPageParam
349
+ > &
350
+ QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
351
+
352
+ export function infiniteQueryOptions(options: unknown) {
353
+ return options
354
+ }
@@ -0,0 +1,296 @@
1
+ import { InfiniteQueryObserver } from '@tanstack/query-core'
2
+ import {
3
+ Injector,
4
+ assertInInjectionContext,
5
+ inject,
6
+ runInInjectionContext,
7
+ } from '@angular/core'
8
+ import { createBaseQuery } from './create-base-query'
9
+ import type {
10
+ DefaultError,
11
+ InfiniteData,
12
+ QueryKey,
13
+ QueryObserver,
14
+ } from '@tanstack/query-core'
15
+ import type {
16
+ CreateInfiniteQueryOptions,
17
+ CreateInfiniteQueryResult,
18
+ DefinedCreateInfiniteQueryResult,
19
+ } from './types'
20
+ import type {
21
+ DefinedInitialDataInfiniteOptions,
22
+ UndefinedInitialDataInfiniteOptions,
23
+ } from './infinite-query-options'
24
+
25
+ export interface InjectInfiniteQueryOptions {
26
+ /**
27
+ * The `Injector` in which to create the infinite query.
28
+ *
29
+ * If this is not provided, the current injection context will be used instead (via `inject`).
30
+ */
31
+ injector?: Injector
32
+ }
33
+
34
+ /**
35
+ * The options for `injectInfiniteQuery` are identical to `injectQuery`, with the addition of
36
+ * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. Infinite queries can
37
+ * additively "load more" data onto an existing set of data, or "infinite scroll".
38
+ *
39
+ * This overload is selected when `initialData` is set on the options returned by `injectInfiniteQueryFn`,
40
+ * so the resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`).
41
+ *
42
+ * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default
43
+ * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user
44
+ * actions, or add conditions like `hasNextPage() && !isFetching()`.
45
+ * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and imperative APIs
46
+ * like `queryClient.fetchInfiniteQuery`.
47
+ * @param injectInfiniteQueryFn - A function returning the {@link DefinedInitialDataInfiniteOptions} to use —
48
+ * everything you can pass to `injectInfiniteQuery`, with `initialData` set. Similar to `computed` from
49
+ * Angular, this function runs in the reactive context, so signals read inside it drive the query.
50
+ * @param options - Additional configuration.
51
+ * @returns The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
52
+ * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and
53
+ * `data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
54
+ * `InfiniteData<TQueryFnData>` shape.
55
+ *
56
+ * @example
57
+ * ```angular-ts
58
+ * @Component({
59
+ * selector: 'projects',
60
+ * template: `
61
+ * <!-- `projectsQuery.data()` is never `undefined`, thanks to `initialData` — even if a
62
+ * refetch fails, so the list stays visible alongside the error. -->
63
+ * <ul>
64
+ * @for (page of projectsQuery.data().pages; track $index) {
65
+ * @for (project of page.projects; track project.id) {
66
+ * <li>{{ project.name }}</li>
67
+ * }
68
+ * }
69
+ * </ul>
70
+ * `,
71
+ * })
72
+ * export class Projects {
73
+ * readonly projectsQuery = injectInfiniteQuery(() => ({
74
+ * queryKey: ['projects'],
75
+ * queryFn: ({ pageParam }) => fetchProjects(pageParam),
76
+ * initialPageParam: 0,
77
+ * getNextPageParam: (lastPage) => lastPage.nextId,
78
+ * initialData: { pages: [], pageParams: [] },
79
+ * }))
80
+ * }
81
+ * ```
82
+ */
83
+ export function injectInfiniteQuery<
84
+ TQueryFnData,
85
+ TError = DefaultError,
86
+ TData = InfiniteData<TQueryFnData>,
87
+ TQueryKey extends QueryKey = QueryKey,
88
+ TPageParam = unknown,
89
+ >(
90
+ injectInfiniteQueryFn: () => DefinedInitialDataInfiniteOptions<
91
+ TQueryFnData,
92
+ TError,
93
+ TData,
94
+ TQueryKey,
95
+ TPageParam
96
+ >,
97
+ options?: InjectInfiniteQueryOptions,
98
+ ): DefinedCreateInfiniteQueryResult<TData, TError>
99
+
100
+ /**
101
+ * Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a
102
+ * unique key. Infinite queries can additively "load more" data onto an existing set of data, or
103
+ * "infinite scroll".
104
+ *
105
+ * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default
106
+ * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user
107
+ * actions, or add conditions like `hasNextPage() && !isFetching()`. This is the only overload that accepts
108
+ * `queryFn: skipToken`, shown below.
109
+ * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and imperative APIs
110
+ * like `queryClient.fetchInfiniteQuery`.
111
+ * @param injectInfiniteQueryFn - A function returning the {@link UndefinedInitialDataInfiniteOptions} to use
112
+ * — everything you can pass to `injectInfiniteQuery`. Similar to `computed` from Angular, this function runs
113
+ * in the reactive context, so signals read inside it drive the query.
114
+ * @param options - Additional configuration.
115
+ * @returns The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
116
+ * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and
117
+ * `data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
118
+ * `InfiniteData<TQueryFnData>` shape.
119
+ *
120
+ * @example
121
+ * Fetching the next page from a button click:
122
+ * ```angular-ts
123
+ * @Component({
124
+ * selector: 'projects-list',
125
+ * template: `
126
+ * <ul>
127
+ * @for (page of projectsQuery.data()?.pages; track $index) {
128
+ * @for (project of page.projects; track project.id) {
129
+ * <li>{{ project.name }}</li>
130
+ * }
131
+ * }
132
+ * </ul>
133
+ * <button
134
+ * [disabled]="!projectsQuery.hasNextPage() || projectsQuery.isFetching()"
135
+ * (click)="projectsQuery.fetchNextPage()"
136
+ * >
137
+ * Load More
138
+ * </button>
139
+ * `,
140
+ * })
141
+ * export class ProjectsList {
142
+ * readonly projectsQuery = injectInfiniteQuery(() => ({
143
+ * queryKey: ['projects'],
144
+ * queryFn: ({ pageParam }) => fetchProjects(pageParam),
145
+ * initialPageParam: 0,
146
+ * getNextPageParam: (lastPage) => lastPage.nextId,
147
+ * }))
148
+ * }
149
+ * ```
150
+ *
151
+ * @example
152
+ * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a sentinel
153
+ * element after the list:
154
+ * ```angular-ts
155
+ * @Component({
156
+ * selector: 'projects-list',
157
+ * template: `
158
+ * <ul>
159
+ * @for (page of projectsQuery.data()?.pages; track $index) {
160
+ * @for (project of page.projects; track project.id) {
161
+ * <li>{{ project.name }}</li>
162
+ * }
163
+ * }
164
+ * </ul>
165
+ * <div #sentinel>{{ projectsQuery.isFetchingNextPage() ? 'Loading more...' : '' }}</div>
166
+ * `,
167
+ * })
168
+ * export class ProjectsList {
169
+ * readonly sentinel = viewChild<ElementRef<HTMLElement>>('sentinel')
170
+ *
171
+ * readonly projectsQuery = injectInfiniteQuery(() => ({
172
+ * queryKey: ['projects'],
173
+ * queryFn: ({ pageParam }) => fetchProjects(pageParam),
174
+ * initialPageParam: 0,
175
+ * getNextPageParam: (lastPage) => lastPage.nextId,
176
+ * }))
177
+ *
178
+ * constructor() {
179
+ * effect((onCleanup) => {
180
+ * const sentinel = this.sentinel()?.nativeElement
181
+ * if (
182
+ * sentinel == null ||
183
+ * !this.projectsQuery.hasNextPage() ||
184
+ * this.projectsQuery.isFetching()
185
+ * ) {
186
+ * return
187
+ * }
188
+ *
189
+ * const observer = new IntersectionObserver(([entry]) => {
190
+ * if (entry?.isIntersecting) this.projectsQuery.fetchNextPage()
191
+ * })
192
+ * observer.observe(sentinel)
193
+ *
194
+ * onCleanup(() => observer.disconnect())
195
+ * })
196
+ * }
197
+ * }
198
+ * ```
199
+ *
200
+ * @example
201
+ * A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn` instead of
202
+ * setting `enabled: false`:
203
+ * ```angular-ts
204
+ * @Component({
205
+ * selector: 'comments',
206
+ * template: `
207
+ * @if (postId() == null) {
208
+ * Select a post
209
+ * } @else if (commentsQuery.isPending()) {
210
+ * Loading...
211
+ * } @else if (commentsQuery.isError()) {
212
+ * <span>Error: {{ commentsQuery.error()?.message }}</span>
213
+ * } @else {
214
+ * <ul>
215
+ * @for (page of commentsQuery.data().pages; track $index) {
216
+ * @for (comment of page.comments; track comment.id) {
217
+ * <li>{{ comment.text }}</li>
218
+ * }
219
+ * }
220
+ * </ul>
221
+ * }
222
+ * `,
223
+ * })
224
+ * export class Comments {
225
+ * readonly postId = signal<string | undefined>(undefined)
226
+ *
227
+ * readonly commentsQuery = injectInfiniteQuery(() => ({
228
+ * queryKey: ['post', this.postId(), 'comments'],
229
+ * queryFn:
230
+ * this.postId() != null
231
+ * ? ({ pageParam }) => fetchComments(this.postId()!, pageParam)
232
+ * : skipToken,
233
+ * initialPageParam: 0,
234
+ * getNextPageParam: (lastPage) => lastPage.nextId,
235
+ * }))
236
+ * }
237
+ * ```
238
+ */
239
+ export function injectInfiniteQuery<
240
+ TQueryFnData,
241
+ TError = DefaultError,
242
+ TData = InfiniteData<TQueryFnData>,
243
+ TQueryKey extends QueryKey = QueryKey,
244
+ TPageParam = unknown,
245
+ >(
246
+ injectInfiniteQueryFn: () => UndefinedInitialDataInfiniteOptions<
247
+ TQueryFnData,
248
+ TError,
249
+ TData,
250
+ TQueryKey,
251
+ TPageParam
252
+ >,
253
+ options?: InjectInfiniteQueryOptions,
254
+ ): CreateInfiniteQueryResult<TData, TError>
255
+
256
+ /**
257
+ * This overload accepts the general {@link CreateInfiniteQueryOptions} shape rather than the
258
+ * `initialData`-aware overloads above, so whether `data` is defined can't be inferred from the call site —
259
+ * useful when wrapping `injectInfiniteQuery` in your own helper function that forwards caller-provided
260
+ * options.
261
+ *
262
+ * @param injectInfiniteQueryFn - A function that returns infinite query options. Similar to `computed` from
263
+ * Angular, this function runs in the reactive context, so signals read inside it drive the query.
264
+ * @param options - Additional configuration.
265
+ * @returns The infinite query result.
266
+ */
267
+ export function injectInfiniteQuery<
268
+ TQueryFnData,
269
+ TError = DefaultError,
270
+ TData = InfiniteData<TQueryFnData>,
271
+ TQueryKey extends QueryKey = QueryKey,
272
+ TPageParam = unknown,
273
+ >(
274
+ injectInfiniteQueryFn: () => CreateInfiniteQueryOptions<
275
+ TQueryFnData,
276
+ TError,
277
+ TData,
278
+ TQueryKey,
279
+ TPageParam
280
+ >,
281
+ options?: InjectInfiniteQueryOptions,
282
+ ): CreateInfiniteQueryResult<TData, TError>
283
+
284
+ export function injectInfiniteQuery(
285
+ injectInfiniteQueryFn: () => CreateInfiniteQueryOptions,
286
+ options?: InjectInfiniteQueryOptions,
287
+ ) {
288
+ !options?.injector && assertInInjectionContext(injectInfiniteQuery)
289
+ const injector = options?.injector ?? inject(Injector)
290
+ return runInInjectionContext(injector, () =>
291
+ createBaseQuery(
292
+ injectInfiniteQueryFn,
293
+ InfiniteQueryObserver as typeof QueryObserver,
294
+ ),
295
+ )
296
+ }