@tanstack/angular-query-experimental 5.74.0 → 5.74.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.d.ts +8 -11
- package/build/index.mjs +211 -186
- package/build/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/inject-infinite-query.ts +9 -7
- package/src/inject-is-fetching.ts +34 -28
- package/src/inject-is-mutating.ts +34 -28
- package/src/inject-is-restoring.ts +3 -3
- package/src/inject-mutation-state.ts +61 -55
- package/src/inject-mutation.ts +108 -114
- package/src/inject-queries.ts +6 -3
- package/src/inject-query.ts +8 -3
- package/src/util/assert-injector/assert-injector.test.ts +0 -78
- package/src/util/assert-injector/assert-injector.ts +0 -83
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from '@angular/core'
|
|
8
8
|
import type { Provider, Signal } from '@angular/core'
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const IS_RESTORING = new InjectionToken<Signal<boolean>>('')
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* The `Injector` in which to create the isRestoring signal.
|
|
@@ -30,7 +30,7 @@ export function injectIsRestoring(
|
|
|
30
30
|
!options?.injector && assertInInjectionContext(injectIsRestoring)
|
|
31
31
|
const injector = options?.injector ?? inject(Injector)
|
|
32
32
|
return injector.get(
|
|
33
|
-
|
|
33
|
+
IS_RESTORING,
|
|
34
34
|
computed(() => false),
|
|
35
35
|
{ optional: true },
|
|
36
36
|
)
|
|
@@ -44,7 +44,7 @@ export function injectIsRestoring(
|
|
|
44
44
|
*/
|
|
45
45
|
export function provideIsRestoring(isRestoring: Signal<boolean>): Provider {
|
|
46
46
|
return {
|
|
47
|
-
provide:
|
|
47
|
+
provide: IS_RESTORING,
|
|
48
48
|
useValue: isRestoring,
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
DestroyRef,
|
|
3
|
+
Injector,
|
|
4
|
+
NgZone,
|
|
5
|
+
assertInInjectionContext,
|
|
6
|
+
computed,
|
|
7
|
+
inject,
|
|
8
|
+
signal,
|
|
9
|
+
} from '@angular/core'
|
|
2
10
|
import {
|
|
3
11
|
QueryClient,
|
|
4
12
|
notifyManager,
|
|
5
13
|
replaceEqualDeep,
|
|
6
14
|
} from '@tanstack/query-core'
|
|
7
|
-
import {
|
|
8
|
-
import type { Injector, Signal } from '@angular/core'
|
|
15
|
+
import type { Signal } from '@angular/core'
|
|
9
16
|
import type {
|
|
10
17
|
Mutation,
|
|
11
18
|
MutationCache,
|
|
@@ -58,62 +65,61 @@ export function injectMutationState<TResult = MutationState>(
|
|
|
58
65
|
injectMutationStateFn: () => MutationStateOptions<TResult> = () => ({}),
|
|
59
66
|
options?: InjectMutationStateOptions,
|
|
60
67
|
): Signal<Array<TResult>> {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
!options?.injector && assertInInjectionContext(injectMutationState)
|
|
69
|
+
const injector = options?.injector ?? inject(Injector)
|
|
70
|
+
const destroyRef = injector.get(DestroyRef)
|
|
71
|
+
const ngZone = injector.get(NgZone)
|
|
72
|
+
const queryClient = injector.get(QueryClient)
|
|
73
|
+
const mutationCache = queryClient.getMutationCache()
|
|
67
74
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Computed signal that gets result from mutation cache based on passed options
|
|
77
|
+
* First element is the result, second element is the time when the result was set
|
|
78
|
+
*/
|
|
79
|
+
const resultFromOptionsSignal = computed(() => {
|
|
80
|
+
return [
|
|
81
|
+
getResult(mutationCache, injectMutationStateFn()),
|
|
82
|
+
performance.now(),
|
|
83
|
+
] as const
|
|
84
|
+
})
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Signal that contains result set by subscriber
|
|
88
|
+
* First element is the result, second element is the time when the result was set
|
|
89
|
+
*/
|
|
90
|
+
const resultFromSubscriberSignal = signal<[Array<TResult>, number] | null>(
|
|
91
|
+
null,
|
|
92
|
+
)
|
|
86
93
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Returns the last result by either subscriber or options
|
|
96
|
+
*/
|
|
97
|
+
const effectiveResultSignal = computed(() => {
|
|
98
|
+
const optionsResult = resultFromOptionsSignal()
|
|
99
|
+
const subscriberResult = resultFromSubscriberSignal()
|
|
100
|
+
return subscriberResult && subscriberResult[1] > optionsResult[1]
|
|
101
|
+
? subscriberResult[0]
|
|
102
|
+
: optionsResult[0]
|
|
103
|
+
})
|
|
97
104
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
const unsubscribe = ngZone.runOutsideAngular(() =>
|
|
106
|
+
mutationCache.subscribe(
|
|
107
|
+
notifyManager.batchCalls(() => {
|
|
108
|
+
const [lastResult] = effectiveResultSignal()
|
|
109
|
+
const nextResult = replaceEqualDeep(
|
|
110
|
+
lastResult,
|
|
111
|
+
getResult(mutationCache, injectMutationStateFn()),
|
|
112
|
+
)
|
|
113
|
+
if (lastResult !== nextResult) {
|
|
114
|
+
ngZone.run(() => {
|
|
115
|
+
resultFromSubscriberSignal.set([nextResult, performance.now()])
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
}),
|
|
119
|
+
),
|
|
120
|
+
)
|
|
114
121
|
|
|
115
|
-
|
|
122
|
+
destroyRef.onDestroy(unsubscribe)
|
|
116
123
|
|
|
117
|
-
|
|
118
|
-
})
|
|
124
|
+
return effectiveResultSignal
|
|
119
125
|
}
|
package/src/inject-mutation.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DestroyRef,
|
|
3
|
+
Injector,
|
|
3
4
|
NgZone,
|
|
5
|
+
assertInInjectionContext,
|
|
4
6
|
computed,
|
|
5
7
|
effect,
|
|
6
8
|
inject,
|
|
@@ -12,10 +14,8 @@ import {
|
|
|
12
14
|
QueryClient,
|
|
13
15
|
notifyManager,
|
|
14
16
|
} from '@tanstack/query-core'
|
|
15
|
-
import { assertInjector } from './util/assert-injector/assert-injector'
|
|
16
17
|
import { signalProxy } from './signal-proxy'
|
|
17
18
|
import { noop, shouldThrowError } from './util'
|
|
18
|
-
import type { Injector } from '@angular/core'
|
|
19
19
|
import type { DefaultError, MutationObserverResult } from '@tanstack/query-core'
|
|
20
20
|
import type { CreateMutateFunction, CreateMutationResult } from './types'
|
|
21
21
|
import type { CreateMutationOptions } from './mutation-options'
|
|
@@ -52,123 +52,117 @@ export function injectMutation<
|
|
|
52
52
|
>,
|
|
53
53
|
options?: InjectMutationOptions,
|
|
54
54
|
): CreateMutationResult<TData, TError, TVariables, TContext> {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* computed() is used so signals can be inserted into the options
|
|
62
|
-
* making it reactive. Wrapping options in a function ensures embedded expressions
|
|
63
|
-
* are preserved and can keep being applied after signal changes
|
|
64
|
-
*/
|
|
65
|
-
const optionsSignal = computed(injectMutationFn)
|
|
66
|
-
|
|
67
|
-
const observerSignal = (() => {
|
|
68
|
-
let instance: MutationObserver<
|
|
69
|
-
TData,
|
|
70
|
-
TError,
|
|
71
|
-
TVariables,
|
|
72
|
-
TContext
|
|
73
|
-
> | null = null
|
|
74
|
-
|
|
75
|
-
return computed(() => {
|
|
76
|
-
return (instance ||= new MutationObserver(queryClient, optionsSignal()))
|
|
77
|
-
})
|
|
78
|
-
})()
|
|
55
|
+
!options?.injector && assertInInjectionContext(injectMutation)
|
|
56
|
+
const injector = options?.injector ?? inject(Injector)
|
|
57
|
+
const destroyRef = injector.get(DestroyRef)
|
|
58
|
+
const ngZone = injector.get(NgZone)
|
|
59
|
+
const queryClient = injector.get(QueryClient)
|
|
79
60
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
61
|
+
/**
|
|
62
|
+
* computed() is used so signals can be inserted into the options
|
|
63
|
+
* making it reactive. Wrapping options in a function ensures embedded expressions
|
|
64
|
+
* are preserved and can keep being applied after signal changes
|
|
65
|
+
*/
|
|
66
|
+
const optionsSignal = computed(injectMutationFn)
|
|
67
|
+
|
|
68
|
+
const observerSignal = (() => {
|
|
69
|
+
let instance: MutationObserver<TData, TError, TVariables, TContext> | null =
|
|
70
|
+
null
|
|
71
|
+
|
|
72
|
+
return computed(() => {
|
|
73
|
+
return (instance ||= new MutationObserver(queryClient, optionsSignal()))
|
|
87
74
|
})
|
|
75
|
+
})()
|
|
76
|
+
|
|
77
|
+
const mutateFnSignal = computed<
|
|
78
|
+
CreateMutateFunction<TData, TError, TVariables, TContext>
|
|
79
|
+
>(() => {
|
|
80
|
+
const observer = observerSignal()
|
|
81
|
+
return (variables, mutateOptions) => {
|
|
82
|
+
observer.mutate(variables, mutateOptions).catch(noop)
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Computed signal that gets result from mutation cache based on passed options
|
|
88
|
+
*/
|
|
89
|
+
const resultFromInitialOptionsSignal = computed(() => {
|
|
90
|
+
const observer = observerSignal()
|
|
91
|
+
return observer.getCurrentResult()
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Signal that contains result set by subscriber
|
|
96
|
+
*/
|
|
97
|
+
const resultFromSubscriberSignal = signal<MutationObserverResult<
|
|
98
|
+
TData,
|
|
99
|
+
TError,
|
|
100
|
+
TVariables,
|
|
101
|
+
TContext
|
|
102
|
+
> | null>(null)
|
|
88
103
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
*/
|
|
92
|
-
const resultFromInitialOptionsSignal = computed(() => {
|
|
104
|
+
effect(
|
|
105
|
+
() => {
|
|
93
106
|
const observer = observerSignal()
|
|
94
|
-
|
|
95
|
-
})
|
|
107
|
+
const observerOptions = optionsSignal()
|
|
96
108
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const observerOptions = optionsSignal()
|
|
111
|
-
|
|
112
|
-
untracked(() => {
|
|
113
|
-
observer.setOptions(observerOptions)
|
|
114
|
-
})
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
injector: options?.injector,
|
|
118
|
-
},
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
effect(
|
|
122
|
-
() => {
|
|
123
|
-
// observer.trackResult is not used as this optimization is not needed for Angular
|
|
124
|
-
const observer = observerSignal()
|
|
125
|
-
|
|
126
|
-
untracked(() => {
|
|
127
|
-
const unsubscribe = ngZone.runOutsideAngular(() =>
|
|
128
|
-
observer.subscribe(
|
|
129
|
-
notifyManager.batchCalls((state) => {
|
|
130
|
-
ngZone.run(() => {
|
|
131
|
-
if (
|
|
132
|
-
state.isError &&
|
|
133
|
-
shouldThrowError(observer.options.throwOnError, [
|
|
134
|
-
state.error,
|
|
135
|
-
])
|
|
136
|
-
) {
|
|
137
|
-
ngZone.onError.emit(state.error)
|
|
138
|
-
throw state.error
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
resultFromSubscriberSignal.set(state)
|
|
142
|
-
})
|
|
143
|
-
}),
|
|
144
|
-
),
|
|
145
|
-
)
|
|
146
|
-
destroyRef.onDestroy(unsubscribe)
|
|
147
|
-
})
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
injector: options?.injector,
|
|
151
|
-
},
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
const resultSignal = computed(() => {
|
|
155
|
-
const resultFromSubscriber = resultFromSubscriberSignal()
|
|
156
|
-
const resultFromInitialOptions = resultFromInitialOptionsSignal()
|
|
157
|
-
|
|
158
|
-
const result = resultFromSubscriber ?? resultFromInitialOptions
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
...result,
|
|
162
|
-
mutate: mutateFnSignal(),
|
|
163
|
-
mutateAsync: result.mutate,
|
|
164
|
-
}
|
|
165
|
-
})
|
|
109
|
+
untracked(() => {
|
|
110
|
+
observer.setOptions(observerOptions)
|
|
111
|
+
})
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
injector,
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
effect(
|
|
119
|
+
() => {
|
|
120
|
+
// observer.trackResult is not used as this optimization is not needed for Angular
|
|
121
|
+
const observer = observerSignal()
|
|
166
122
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
123
|
+
untracked(() => {
|
|
124
|
+
const unsubscribe = ngZone.runOutsideAngular(() =>
|
|
125
|
+
observer.subscribe(
|
|
126
|
+
notifyManager.batchCalls((state) => {
|
|
127
|
+
ngZone.run(() => {
|
|
128
|
+
if (
|
|
129
|
+
state.isError &&
|
|
130
|
+
shouldThrowError(observer.options.throwOnError, [state.error])
|
|
131
|
+
) {
|
|
132
|
+
ngZone.onError.emit(state.error)
|
|
133
|
+
throw state.error
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
resultFromSubscriberSignal.set(state)
|
|
137
|
+
})
|
|
138
|
+
}),
|
|
139
|
+
),
|
|
140
|
+
)
|
|
141
|
+
destroyRef.onDestroy(unsubscribe)
|
|
142
|
+
})
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
injector,
|
|
146
|
+
},
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
const resultSignal = computed(() => {
|
|
150
|
+
const resultFromSubscriber = resultFromSubscriberSignal()
|
|
151
|
+
const resultFromInitialOptions = resultFromInitialOptionsSignal()
|
|
152
|
+
|
|
153
|
+
const result = resultFromSubscriber ?? resultFromInitialOptions
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
...result,
|
|
157
|
+
mutate: mutateFnSignal(),
|
|
158
|
+
mutateAsync: result.mutate,
|
|
159
|
+
}
|
|
173
160
|
})
|
|
161
|
+
|
|
162
|
+
return signalProxy(resultSignal) as CreateMutationResult<
|
|
163
|
+
TData,
|
|
164
|
+
TError,
|
|
165
|
+
TVariables,
|
|
166
|
+
TContext
|
|
167
|
+
>
|
|
174
168
|
}
|
package/src/inject-queries.ts
CHANGED
|
@@ -5,15 +5,17 @@ import {
|
|
|
5
5
|
} from '@tanstack/query-core'
|
|
6
6
|
import {
|
|
7
7
|
DestroyRef,
|
|
8
|
+
Injector,
|
|
8
9
|
NgZone,
|
|
10
|
+
assertInInjectionContext,
|
|
9
11
|
computed,
|
|
10
12
|
effect,
|
|
11
13
|
inject,
|
|
14
|
+
runInInjectionContext,
|
|
12
15
|
signal,
|
|
13
16
|
} from '@angular/core'
|
|
14
|
-
import { assertInjector } from './util/assert-injector/assert-injector'
|
|
15
17
|
import { injectIsRestoring } from './inject-is-restoring'
|
|
16
|
-
import type {
|
|
18
|
+
import type { Signal } from '@angular/core'
|
|
17
19
|
import type {
|
|
18
20
|
DefaultError,
|
|
19
21
|
OmitKeyof,
|
|
@@ -214,7 +216,8 @@ export function injectQueries<
|
|
|
214
216
|
},
|
|
215
217
|
injector?: Injector,
|
|
216
218
|
): Signal<TCombinedResult> {
|
|
217
|
-
|
|
219
|
+
!injector && assertInInjectionContext(injectQueries)
|
|
220
|
+
return runInInjectionContext(injector ?? inject(Injector), () => {
|
|
218
221
|
const destroyRef = inject(DestroyRef)
|
|
219
222
|
const ngZone = inject(NgZone)
|
|
220
223
|
const queryClient = inject(QueryClient)
|
package/src/inject-query.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { QueryObserver } from '@tanstack/query-core'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Injector,
|
|
4
|
+
assertInInjectionContext,
|
|
5
|
+
inject,
|
|
6
|
+
runInInjectionContext,
|
|
7
|
+
} from '@angular/core'
|
|
3
8
|
import { createBaseQuery } from './create-base-query'
|
|
4
|
-
import type { Injector } from '@angular/core'
|
|
5
9
|
import type { DefaultError, QueryKey } from '@tanstack/query-core'
|
|
6
10
|
import type {
|
|
7
11
|
CreateQueryOptions,
|
|
@@ -219,7 +223,8 @@ export function injectQuery(
|
|
|
219
223
|
injectQueryFn: () => CreateQueryOptions,
|
|
220
224
|
options?: InjectQueryOptions,
|
|
221
225
|
) {
|
|
222
|
-
|
|
226
|
+
!options?.injector && assertInInjectionContext(injectQuery)
|
|
227
|
+
return runInInjectionContext(options?.injector ?? inject(Injector), () =>
|
|
223
228
|
createBaseQuery(injectQueryFn, QueryObserver),
|
|
224
229
|
) as unknown as CreateQueryResult
|
|
225
230
|
}
|
|
@@ -1,78 +0,0 @@
|
|
|
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
|
-
provideExperimentalZonelessChangeDetection,
|
|
19
|
-
runInInjectionContext,
|
|
20
|
-
} from '@angular/core'
|
|
21
|
-
import { TestBed } from '@angular/core/testing'
|
|
22
|
-
import { assertInjector } from './assert-injector'
|
|
23
|
-
|
|
24
|
-
describe('assertInjector', () => {
|
|
25
|
-
const token = new InjectionToken('token', {
|
|
26
|
-
factory: () => 1,
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
function injectDummy(injector?: Injector) {
|
|
30
|
-
injector = assertInjector(injectDummy, injector)
|
|
31
|
-
return runInInjectionContext(injector, () => inject(token))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function injectDummyTwo(injector?: Injector) {
|
|
35
|
-
return assertInjector(injectDummyTwo, injector, () => inject(token) + 1)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
it('given no custom injector, when run in injection context, then return value', () => {
|
|
39
|
-
TestBed.configureTestingModule({
|
|
40
|
-
providers: [provideExperimentalZonelessChangeDetection()],
|
|
41
|
-
})
|
|
42
|
-
TestBed.runInInjectionContext(() => {
|
|
43
|
-
const value = injectDummy()
|
|
44
|
-
const valueTwo = injectDummyTwo()
|
|
45
|
-
expect(value).toEqual(1)
|
|
46
|
-
expect(valueTwo).toEqual(2)
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('given no custom injector, when run outside injection context, then throw', () => {
|
|
51
|
-
expect(() => injectDummy()).toThrowError(
|
|
52
|
-
/injectDummy\(\) can only be used within an injection context/i,
|
|
53
|
-
)
|
|
54
|
-
expect(() => injectDummyTwo()).toThrowError(
|
|
55
|
-
/injectDummyTwo\(\) can only be used within an injection context/i,
|
|
56
|
-
)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it('given a custom injector, when run in that injector context without providing number, then throw', () => {
|
|
60
|
-
expect(() => injectDummy(Injector.create({ providers: [] }))).toThrowError(
|
|
61
|
-
/No provider for InjectionToken/i,
|
|
62
|
-
)
|
|
63
|
-
expect(() =>
|
|
64
|
-
injectDummyTwo(Injector.create({ providers: [] })),
|
|
65
|
-
).toThrowError(/No provider for InjectionToken/i)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('given a custom injector, when run in that injector context and providing number, then return value', () => {
|
|
69
|
-
const value = injectDummy(
|
|
70
|
-
Injector.create({ providers: [{ provide: token, useValue: 2 }] }),
|
|
71
|
-
)
|
|
72
|
-
const valueTwo = injectDummyTwo(
|
|
73
|
-
Injector.create({ providers: [{ provide: token, useValue: 2 }] }),
|
|
74
|
-
)
|
|
75
|
-
expect(value).toEqual(2)
|
|
76
|
-
expect(valueTwo).toEqual(3)
|
|
77
|
-
})
|
|
78
|
-
})
|
|
@@ -1,83 +0,0 @@
|
|
|
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
|
-
* @template {() => any} Runner - Runner is a function that can return anything
|
|
27
|
-
* @param fn - the Function to pass in `assertInInjectionContext`
|
|
28
|
-
* @param injector - the optional "custom" Injector
|
|
29
|
-
* @param runner - the runner fn
|
|
30
|
-
* @returns result - returns the result of the Runner
|
|
31
|
-
* @example
|
|
32
|
-
* ```ts
|
|
33
|
-
* function injectValue(injector?: Injector) {
|
|
34
|
-
* return assertInjector(injectValue, injector, () => 'value');
|
|
35
|
-
* }
|
|
36
|
-
*
|
|
37
|
-
* injectValue(); // string
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export function assertInjector<TRunner extends () => any>(
|
|
41
|
-
fn: Function,
|
|
42
|
-
injector: Injector | undefined | null,
|
|
43
|
-
runner: TRunner,
|
|
44
|
-
): ReturnType<TRunner>
|
|
45
|
-
/**
|
|
46
|
-
* `assertInjector` extends `assertInInjectionContext` with an optional `Injector`
|
|
47
|
-
* After assertion, `assertInjector` returns a guaranteed `Injector` whether it is the default `Injector`
|
|
48
|
-
* within the current **Injection Context** or the custom `Injector` that was passed in.
|
|
49
|
-
* @param fn - the Function to pass in `assertInInjectionContext`
|
|
50
|
-
* @param injector - the optional "custom" Injector
|
|
51
|
-
* @returns Injector
|
|
52
|
-
* @example
|
|
53
|
-
* ```ts
|
|
54
|
-
* function injectDestroy(injector?: Injector) {
|
|
55
|
-
* injector = assertInjector(injectDestroy, injector);
|
|
56
|
-
*
|
|
57
|
-
* return runInInjectionContext(injector, () => {
|
|
58
|
-
* // code
|
|
59
|
-
* })
|
|
60
|
-
* }
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
export function assertInjector(
|
|
64
|
-
fn: Function,
|
|
65
|
-
injector: Injector | undefined | null,
|
|
66
|
-
): Injector
|
|
67
|
-
/**
|
|
68
|
-
* @param fn - the Function to pass in `assertInInjectionContext`
|
|
69
|
-
* @param injector - the optional "custom" Injector
|
|
70
|
-
* @param runner - the runner fn
|
|
71
|
-
* @returns any
|
|
72
|
-
*/
|
|
73
|
-
export function assertInjector(
|
|
74
|
-
fn: Function,
|
|
75
|
-
injector: Injector | undefined | null,
|
|
76
|
-
runner?: () => any,
|
|
77
|
-
) {
|
|
78
|
-
!injector && assertInInjectionContext(fn)
|
|
79
|
-
const assertedInjector = injector ?? inject(Injector)
|
|
80
|
-
|
|
81
|
-
if (!runner) return assertedInjector
|
|
82
|
-
return runInInjectionContext(assertedInjector, runner)
|
|
83
|
-
}
|