@tanstack/angular-query-experimental 5.60.0 → 5.60.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 (51) hide show
  1. package/build/{rollup.d.ts → index.d.ts} +280 -361
  2. package/build/index.js +572 -0
  3. package/build/index.js.map +1 -0
  4. package/package.json +12 -15
  5. package/src/create-base-query.ts +117 -0
  6. package/src/index.ts +28 -0
  7. package/src/infinite-query-options.ts +125 -0
  8. package/src/inject-infinite-query.ts +119 -0
  9. package/src/inject-is-fetching.ts +49 -0
  10. package/src/inject-is-mutating.ts +48 -0
  11. package/src/inject-mutation-state.ts +102 -0
  12. package/src/inject-mutation.ts +121 -0
  13. package/src/inject-queries.ts +246 -0
  14. package/src/inject-query-client.ts +22 -0
  15. package/src/inject-query.ts +207 -0
  16. package/src/providers.ts +351 -0
  17. package/src/query-options.ts +125 -0
  18. package/src/signal-proxy.ts +46 -0
  19. package/src/test-setup.ts +12 -0
  20. package/src/types.ts +328 -0
  21. package/src/util/assert-injector/assert-injector.test.ts +74 -0
  22. package/src/util/assert-injector/assert-injector.ts +81 -0
  23. package/src/util/index.ts +13 -0
  24. package/src/util/is-dev-mode/is-dev-mode.ts +3 -0
  25. package/src/util/lazy-init/lazy-init.ts +34 -0
  26. package/src/util/lazy-signal-initializer/lazy-signal-initializer.ts +23 -0
  27. package/build/README.md +0 -133
  28. package/build/esm2022/create-base-query.mjs +0 -62
  29. package/build/esm2022/index.mjs +0 -16
  30. package/build/esm2022/infinite-query-options.mjs +0 -12
  31. package/build/esm2022/inject-infinite-query.mjs +0 -15
  32. package/build/esm2022/inject-is-fetching.mjs +0 -38
  33. package/build/esm2022/inject-is-mutating.mjs +0 -37
  34. package/build/esm2022/inject-mutation-state.mjs +0 -47
  35. package/build/esm2022/inject-mutation.mjs +0 -51
  36. package/build/esm2022/inject-queries.mjs +0 -33
  37. package/build/esm2022/inject-query-client.mjs +0 -23
  38. package/build/esm2022/inject-query.mjs +0 -44
  39. package/build/esm2022/providers.mjs +0 -206
  40. package/build/esm2022/query-options.mjs +0 -26
  41. package/build/esm2022/signal-proxy.mjs +0 -38
  42. package/build/esm2022/tanstack-angular-query-experimental.mjs +0 -5
  43. package/build/esm2022/types.mjs +0 -3
  44. package/build/esm2022/util/assert-injector/assert-injector.mjs +0 -21
  45. package/build/esm2022/util/create-injection-token/create-injection-token.mjs +0 -61
  46. package/build/esm2022/util/index.mjs +0 -9
  47. package/build/esm2022/util/is-dev-mode/is-dev-mode.mjs +0 -3
  48. package/build/esm2022/util/lazy-init/lazy-init.mjs +0 -31
  49. package/build/esm2022/util/lazy-signal-initializer/lazy-signal-initializer.mjs +0 -14
  50. package/build/fesm2022/tanstack-angular-query-experimental.mjs +0 -738
  51. package/build/fesm2022/tanstack-angular-query-experimental.mjs.map +0 -1
@@ -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
+ }
@@ -0,0 +1,12 @@
1
+ import '@analogjs/vite-plugin-angular/setup-vitest'
2
+
3
+ import {
4
+ BrowserDynamicTestingModule,
5
+ platformBrowserDynamicTesting,
6
+ } from '@angular/platform-browser-dynamic/testing'
7
+ import { getTestBed } from '@angular/core/testing'
8
+
9
+ getTestBed().initTestEnvironment(
10
+ BrowserDynamicTestingModule,
11
+ platformBrowserDynamicTesting(),
12
+ )
package/src/types.ts ADDED
@@ -0,0 +1,328 @@
1
+ /* istanbul ignore file */
2
+
3
+ import type {
4
+ DefaultError,
5
+ DefinedInfiniteQueryObserverResult,
6
+ DefinedQueryObserverResult,
7
+ InfiniteQueryObserverOptions,
8
+ InfiniteQueryObserverResult,
9
+ MutateFunction,
10
+ MutationObserverOptions,
11
+ MutationObserverResult,
12
+ OmitKeyof,
13
+ Override,
14
+ QueryKey,
15
+ QueryObserverOptions,
16
+ QueryObserverResult,
17
+ } from '@tanstack/query-core'
18
+ import type { Signal } from '@angular/core'
19
+ import type { MapToSignals } from './signal-proxy'
20
+
21
+ /**
22
+ * @public
23
+ */
24
+ export interface CreateBaseQueryOptions<
25
+ TQueryFnData = unknown,
26
+ TError = DefaultError,
27
+ TData = TQueryFnData,
28
+ TQueryData = TQueryFnData,
29
+ TQueryKey extends QueryKey = QueryKey,
30
+ > extends QueryObserverOptions<
31
+ TQueryFnData,
32
+ TError,
33
+ TData,
34
+ TQueryData,
35
+ TQueryKey
36
+ > {}
37
+
38
+ /**
39
+ * @public
40
+ */
41
+ export interface CreateQueryOptions<
42
+ TQueryFnData = unknown,
43
+ TError = DefaultError,
44
+ TData = TQueryFnData,
45
+ TQueryKey extends QueryKey = QueryKey,
46
+ > extends OmitKeyof<
47
+ CreateBaseQueryOptions<
48
+ TQueryFnData,
49
+ TError,
50
+ TData,
51
+ TQueryFnData,
52
+ TQueryKey
53
+ >,
54
+ 'suspense'
55
+ > {}
56
+
57
+ /**
58
+ * @public
59
+ */
60
+ type CreateStatusBasedQueryResult<
61
+ TStatus extends QueryObserverResult['status'],
62
+ TData = unknown,
63
+ TError = DefaultError,
64
+ > = Extract<QueryObserverResult<TData, TError>, { status: TStatus }>
65
+
66
+ /**
67
+ * @public
68
+ */
69
+ export interface BaseQueryNarrowing<TData = unknown, TError = DefaultError> {
70
+ isSuccess: (
71
+ this: CreateBaseQueryResult<TData, TError>,
72
+ ) => this is CreateBaseQueryResult<
73
+ TData,
74
+ TError,
75
+ CreateStatusBasedQueryResult<'success', TData, TError>
76
+ >
77
+ isError: (
78
+ this: CreateBaseQueryResult<TData, TError>,
79
+ ) => this is CreateBaseQueryResult<
80
+ TData,
81
+ TError,
82
+ CreateStatusBasedQueryResult<'error', TData, TError>
83
+ >
84
+ isPending: (
85
+ this: CreateBaseQueryResult<TData, TError>,
86
+ ) => this is CreateBaseQueryResult<
87
+ TData,
88
+ TError,
89
+ CreateStatusBasedQueryResult<'pending', TData, TError>
90
+ >
91
+ }
92
+
93
+ /**
94
+ * @public
95
+ */
96
+ export interface CreateInfiniteQueryOptions<
97
+ TQueryFnData = unknown,
98
+ TError = DefaultError,
99
+ TData = TQueryFnData,
100
+ TQueryData = TQueryFnData,
101
+ TQueryKey extends QueryKey = QueryKey,
102
+ TPageParam = unknown,
103
+ > extends OmitKeyof<
104
+ InfiniteQueryObserverOptions<
105
+ TQueryFnData,
106
+ TError,
107
+ TData,
108
+ TQueryData,
109
+ TQueryKey,
110
+ TPageParam
111
+ >,
112
+ 'suspense'
113
+ > {}
114
+
115
+ /**
116
+ * @public
117
+ */
118
+ export type CreateBaseQueryResult<
119
+ TData = unknown,
120
+ TError = DefaultError,
121
+ TState = QueryObserverResult<TData, TError>,
122
+ > = BaseQueryNarrowing<TData, TError> &
123
+ MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>
124
+
125
+ /**
126
+ * @public
127
+ */
128
+ export type CreateQueryResult<
129
+ TData = unknown,
130
+ TError = DefaultError,
131
+ > = CreateBaseQueryResult<TData, TError>
132
+
133
+ /**
134
+ * @public
135
+ */
136
+ export type DefinedCreateQueryResult<
137
+ TData = unknown,
138
+ TError = DefaultError,
139
+ TDefinedQueryObserver = DefinedQueryObserverResult<TData, TError>,
140
+ > = MapToSignals<TDefinedQueryObserver>
141
+
142
+ /**
143
+ * @public
144
+ */
145
+ export type CreateInfiniteQueryResult<
146
+ TData = unknown,
147
+ TError = DefaultError,
148
+ > = MapToSignals<InfiniteQueryObserverResult<TData, TError>>
149
+
150
+ /**
151
+ * @public
152
+ */
153
+ export type DefinedCreateInfiniteQueryResult<
154
+ TData = unknown,
155
+ TError = DefaultError,
156
+ TDefinedInfiniteQueryObserver = DefinedInfiniteQueryObserverResult<
157
+ TData,
158
+ TError
159
+ >,
160
+ > = MapToSignals<TDefinedInfiniteQueryObserver>
161
+
162
+ /**
163
+ * @public
164
+ */
165
+ export interface CreateMutationOptions<
166
+ TData = unknown,
167
+ TError = DefaultError,
168
+ TVariables = void,
169
+ TContext = unknown,
170
+ > extends OmitKeyof<
171
+ MutationObserverOptions<TData, TError, TVariables, TContext>,
172
+ '_defaulted'
173
+ > {}
174
+
175
+ /**
176
+ * @public
177
+ */
178
+ export type CreateMutateFunction<
179
+ TData = unknown,
180
+ TError = DefaultError,
181
+ TVariables = void,
182
+ TContext = unknown,
183
+ > = (
184
+ ...args: Parameters<MutateFunction<TData, TError, TVariables, TContext>>
185
+ ) => void
186
+
187
+ /**
188
+ * @public
189
+ */
190
+ export type CreateMutateAsyncFunction<
191
+ TData = unknown,
192
+ TError = DefaultError,
193
+ TVariables = void,
194
+ TContext = unknown,
195
+ > = MutateFunction<TData, TError, TVariables, TContext>
196
+
197
+ /**
198
+ * @public
199
+ */
200
+ export type CreateBaseMutationResult<
201
+ TData = unknown,
202
+ TError = DefaultError,
203
+ TVariables = unknown,
204
+ TContext = unknown,
205
+ > = Override<
206
+ MutationObserverResult<TData, TError, TVariables, TContext>,
207
+ { mutate: CreateMutateFunction<TData, TError, TVariables, TContext> }
208
+ > & {
209
+ mutateAsync: CreateMutateAsyncFunction<TData, TError, TVariables, TContext>
210
+ }
211
+
212
+ /**
213
+ * @public
214
+ */
215
+ type CreateStatusBasedMutationResult<
216
+ TStatus extends CreateBaseMutationResult['status'],
217
+ TData = unknown,
218
+ TError = DefaultError,
219
+ TVariables = unknown,
220
+ TContext = unknown,
221
+ > = Extract<
222
+ CreateBaseMutationResult<TData, TError, TVariables, TContext>,
223
+ { status: TStatus }
224
+ >
225
+
226
+ type SignalFunction<T extends () => any> = T & Signal<ReturnType<T>>
227
+
228
+ /**
229
+ * @public
230
+ */
231
+ export interface BaseMutationNarrowing<
232
+ TData = unknown,
233
+ TError = DefaultError,
234
+ TVariables = unknown,
235
+ TContext = unknown,
236
+ > {
237
+ isSuccess: SignalFunction<
238
+ (
239
+ this: CreateMutationResult<TData, TError, TVariables, TContext>,
240
+ ) => this is CreateMutationResult<
241
+ TData,
242
+ TError,
243
+ TVariables,
244
+ TContext,
245
+ CreateStatusBasedMutationResult<
246
+ 'success',
247
+ TData,
248
+ TError,
249
+ TVariables,
250
+ TContext
251
+ >
252
+ >
253
+ >
254
+ isError: SignalFunction<
255
+ (
256
+ this: CreateMutationResult<TData, TError, TVariables, TContext>,
257
+ ) => this is CreateMutationResult<
258
+ TData,
259
+ TError,
260
+ TVariables,
261
+ TContext,
262
+ CreateStatusBasedMutationResult<
263
+ 'error',
264
+ TData,
265
+ TError,
266
+ TVariables,
267
+ TContext
268
+ >
269
+ >
270
+ >
271
+ isPending: SignalFunction<
272
+ (
273
+ this: CreateMutationResult<TData, TError, TVariables, TContext>,
274
+ ) => this is CreateMutationResult<
275
+ TData,
276
+ TError,
277
+ TVariables,
278
+ TContext,
279
+ CreateStatusBasedMutationResult<
280
+ 'pending',
281
+ TData,
282
+ TError,
283
+ TVariables,
284
+ TContext
285
+ >
286
+ >
287
+ >
288
+ isIdle: SignalFunction<
289
+ (
290
+ this: CreateMutationResult<TData, TError, TVariables, TContext>,
291
+ ) => this is CreateMutationResult<
292
+ TData,
293
+ TError,
294
+ TVariables,
295
+ TContext,
296
+ CreateStatusBasedMutationResult<
297
+ 'idle',
298
+ TData,
299
+ TError,
300
+ TVariables,
301
+ TContext
302
+ >
303
+ >
304
+ >
305
+ }
306
+
307
+ /**
308
+ * @public
309
+ */
310
+ export type CreateMutationResult<
311
+ TData = unknown,
312
+ TError = DefaultError,
313
+ TVariables = unknown,
314
+ TContext = unknown,
315
+ TState = CreateStatusBasedMutationResult<
316
+ CreateBaseMutationResult['status'],
317
+ TData,
318
+ TError,
319
+ TVariables,
320
+ TContext
321
+ >,
322
+ > = BaseMutationNarrowing<TData, TError, TVariables, TContext> &
323
+ MapToSignals<OmitKeyof<TState, keyof BaseMutationNarrowing, 'safely'>>
324
+
325
+ /**
326
+ * @public
327
+ */
328
+ export type NonUndefinedGuard<T> = T extends undefined ? never : T
@@ -0,0 +1,74 @@
1
+ /* eslint-disable cspell/spellchecker */
2
+ /**
3
+ * The code in this file is adapted from NG Extension Platform at https://ngxtension.netlify.app.
4
+ *
5
+ * Original Author: Chau Tran
6
+ *
7
+ * NG Extension Platform is an open-source project licensed under the MIT license.
8
+ *
9
+ * For more information about the original code, see
10
+ * https://github.com/nartc/ngxtension-platform
11
+ */
12
+ /* eslint-enable */
13
+
14
+ import {
15
+ InjectionToken,
16
+ Injector,
17
+ inject,
18
+ runInInjectionContext,
19
+ } from '@angular/core'
20
+ import { TestBed } from '@angular/core/testing'
21
+ import { assertInjector } from './assert-injector'
22
+
23
+ describe('assertInjector', () => {
24
+ const token = new InjectionToken('token', {
25
+ factory: () => 1,
26
+ })
27
+
28
+ function injectDummy(injector?: Injector) {
29
+ injector = assertInjector(injectDummy, injector)
30
+ return runInInjectionContext(injector, () => inject(token))
31
+ }
32
+
33
+ function injectDummyTwo(injector?: Injector) {
34
+ return assertInjector(injectDummyTwo, injector, () => inject(token) + 1)
35
+ }
36
+
37
+ it('given no custom injector, when run in injection context, then return value', () => {
38
+ TestBed.runInInjectionContext(() => {
39
+ const value = injectDummy()
40
+ const valueTwo = injectDummyTwo()
41
+ expect(value).toEqual(1)
42
+ expect(valueTwo).toEqual(2)
43
+ })
44
+ })
45
+
46
+ it('given no custom injector, when run outside injection context, then throw', () => {
47
+ expect(() => injectDummy()).toThrowError(
48
+ /injectDummy\(\) can only be used within an injection context/i,
49
+ )
50
+ expect(() => injectDummyTwo()).toThrowError(
51
+ /injectDummyTwo\(\) can only be used within an injection context/i,
52
+ )
53
+ })
54
+
55
+ it('given a custom injector, when run in that injector context without providing number, then throw', () => {
56
+ expect(() => injectDummy(Injector.create({ providers: [] }))).toThrowError(
57
+ /No provider for InjectionToken/i,
58
+ )
59
+ expect(() =>
60
+ injectDummyTwo(Injector.create({ providers: [] })),
61
+ ).toThrowError(/No provider for InjectionToken/i)
62
+ })
63
+
64
+ it('given a custom injector, when run in that injector context and providing number, then return value', () => {
65
+ const value = injectDummy(
66
+ Injector.create({ providers: [{ provide: token, useValue: 2 }] }),
67
+ )
68
+ const valueTwo = injectDummyTwo(
69
+ Injector.create({ providers: [{ provide: token, useValue: 2 }] }),
70
+ )
71
+ expect(value).toEqual(2)
72
+ expect(valueTwo).toEqual(3)
73
+ })
74
+ })
@@ -0,0 +1,81 @@
1
+ /* eslint-disable cspell/spellchecker */
2
+ /**
3
+ * The code in this file is adapted from NG Extension Platform at https://ngxtension.netlify.app.
4
+ *
5
+ * Original Author: Chau Tran
6
+ *
7
+ * NG Extension Platform is an open-source project licensed under the MIT license.
8
+ *
9
+ * For more information about the original code, see
10
+ * https://github.com/nartc/ngxtension-platform
11
+ */
12
+ /* eslint-enable */
13
+
14
+ import {
15
+ Injector,
16
+ assertInInjectionContext,
17
+ inject,
18
+ runInInjectionContext,
19
+ } from '@angular/core'
20
+
21
+ /**
22
+ * `assertInjector` extends `assertInInjectionContext` with an optional `Injector`
23
+ * After assertion, `assertInjector` runs the `runner` function with the guaranteed `Injector`
24
+ * whether it is the default `Injector` within the current **Injection Context**
25
+ * or the custom `Injector` that was passed in.
26
+ *
27
+ * @template {() => any} Runner - Runner is a function that can return anything
28
+ * @param {Function} fn - the Function to pass in `assertInInjectionContext`
29
+ * @param {Injector | undefined | null} injector - the optional "custom" Injector
30
+ * @param {Runner} runner - the runner fn
31
+ * @returns {ReturnType<Runner>} result - returns the result of the Runner
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * function injectValue(injector?: Injector) {
36
+ * return assertInjector(injectValue, injector, () => 'value');
37
+ * }
38
+ *
39
+ * injectValue(); // string
40
+ * ```
41
+ */
42
+ export function assertInjector<TRunner extends () => any>(
43
+ fn: Function,
44
+ injector: Injector | undefined | null,
45
+ runner: TRunner,
46
+ ): ReturnType<TRunner>
47
+ /**
48
+ * `assertInjector` extends `assertInInjectionContext` with an optional `Injector`
49
+ * After assertion, `assertInjector` returns a guaranteed `Injector` whether it is the default `Injector`
50
+ * within the current **Injection Context** or the custom `Injector` that was passed in.
51
+ *
52
+ * @param {Function} fn - the Function to pass in `assertInInjectionContext`
53
+ * @param {Injector | undefined | null} injector - the optional "custom" Injector
54
+ * @returns Injector
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * function injectDestroy(injector?: Injector) {
59
+ * injector = assertInjector(injectDestroy, injector);
60
+ *
61
+ * return runInInjectionContext(injector, () => {
62
+ * // code
63
+ * })
64
+ * }
65
+ * ```
66
+ */
67
+ export function assertInjector(
68
+ fn: Function,
69
+ injector: Injector | undefined | null,
70
+ ): Injector
71
+ export function assertInjector(
72
+ fn: Function,
73
+ injector: Injector | undefined | null,
74
+ runner?: () => any,
75
+ ) {
76
+ !injector && assertInInjectionContext(fn)
77
+ const assertedInjector = injector ?? inject(Injector)
78
+
79
+ if (!runner) return assertedInjector
80
+ return runInInjectionContext(assertedInjector, runner)
81
+ }
@@ -0,0 +1,13 @@
1
+ export function shouldThrowError<T extends (...args: Array<any>) => boolean>(
2
+ throwError: boolean | T | undefined,
3
+ params: Parameters<T>,
4
+ ): boolean {
5
+ // Allow throwError function to override throwing behavior on a per-error basis
6
+ if (typeof throwError === 'function') {
7
+ return throwError(...params)
8
+ }
9
+
10
+ return !!throwError
11
+ }
12
+
13
+ export function noop() {}
@@ -0,0 +1,3 @@
1
+ // Re-export for mocking in tests
2
+
3
+ export { isDevMode } from '@angular/core'
@@ -0,0 +1,34 @@
1
+ import { untracked } from '@angular/core'
2
+
3
+ export function lazyInit<T extends object>(initializer: () => T): T {
4
+ let object: T | null = null
5
+
6
+ const initializeObject = () => {
7
+ if (!object) {
8
+ object = untracked(() => initializer())
9
+ }
10
+ }
11
+
12
+ queueMicrotask(() => initializeObject())
13
+
14
+ return new Proxy<T>({} as T, {
15
+ get(_, prop, receiver) {
16
+ initializeObject()
17
+ return Reflect.get(object as T, prop, receiver)
18
+ },
19
+ has(_, prop) {
20
+ initializeObject()
21
+ return Reflect.has(object as T, prop)
22
+ },
23
+ ownKeys() {
24
+ initializeObject()
25
+ return Reflect.ownKeys(object as T)
26
+ },
27
+ getOwnPropertyDescriptor() {
28
+ return {
29
+ enumerable: true,
30
+ configurable: true,
31
+ }
32
+ },
33
+ })
34
+ }
@@ -0,0 +1,23 @@
1
+ import { Injector, computed, inject, untracked } from '@angular/core'
2
+ import type { Signal } from '@angular/core'
3
+
4
+ type SignalInitializerFn<T> = (injector: Injector) => Signal<T>
5
+
6
+ export function lazySignalInitializer<T>(
7
+ initializerFn: SignalInitializerFn<T>,
8
+ ) {
9
+ const injector = inject(Injector)
10
+
11
+ let source: Signal<T> | null = null
12
+
13
+ const unwrapSignal = () => {
14
+ if (!source) {
15
+ source = untracked(() => initializerFn(injector))
16
+ }
17
+ return source()
18
+ }
19
+
20
+ queueMicrotask(() => unwrapSignal())
21
+
22
+ return computed(unwrapSignal)
23
+ }