@tanstack/angular-query-experimental 5.103.2 → 5.104.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.
- package/dist/create-base-query.d.mts +168 -0
- package/dist/create-base-query.d.mts.map +1 -0
- package/dist/create-base-query.mjs +91 -0
- package/dist/create-base-query.mjs.map +1 -0
- package/dist/devtools/index.d.mts +3 -0
- package/dist/devtools/index.mjs +2 -0
- package/dist/devtools/production/index.d.mts +4 -0
- package/dist/devtools/production/index.mjs +2 -0
- package/dist/devtools/stub.d.mts +5 -0
- package/dist/devtools/stub.d.mts.map +1 -0
- package/dist/devtools/stub.mjs +9 -0
- package/dist/devtools/stub.mjs.map +1 -0
- package/dist/devtools/types.d.mts +106 -0
- package/dist/devtools/types.d.mts.map +1 -0
- package/dist/devtools/types.mjs +1 -0
- package/{devtools/with-devtools.d.ts → dist/devtools/with-devtools.d.mts} +4 -1
- package/dist/devtools/with-devtools.d.mts.map +1 -0
- package/dist/devtools/with-devtools.mjs +110 -0
- package/dist/devtools/with-devtools.mjs.map +1 -0
- package/dist/devtools-panel/index.d.mts +3 -0
- package/dist/devtools-panel/index.mjs +2 -0
- package/{devtools-panel/inject-devtools-panel.d.ts → dist/devtools-panel/inject-devtools-panel.d.mts} +4 -1
- package/dist/devtools-panel/inject-devtools-panel.d.mts.map +1 -0
- package/dist/devtools-panel/inject-devtools-panel.mjs +67 -0
- package/dist/devtools-panel/inject-devtools-panel.mjs.map +1 -0
- package/dist/devtools-panel/production/index.d.mts +4 -0
- package/dist/devtools-panel/production/index.mjs +2 -0
- package/dist/devtools-panel/stub.d.mts +5 -0
- package/dist/devtools-panel/stub.d.mts.map +1 -0
- package/dist/devtools-panel/stub.mjs +7 -0
- package/dist/devtools-panel/stub.mjs.map +1 -0
- package/dist/devtools-panel/types.d.mts +51 -0
- package/dist/devtools-panel/types.d.mts.map +1 -0
- package/dist/devtools-panel/types.mjs +1 -0
- package/dist/index.d.mts +16 -0
- package/{index.mjs → dist/index.mjs} +8 -21
- package/dist/index.mjs.map +1 -0
- package/{infinite-query-options.d.ts → dist/infinite-query-options.d.mts} +28 -25
- package/dist/infinite-query-options.d.mts.map +1 -0
- package/dist/infinite-query-options.mjs +8 -0
- package/dist/infinite-query-options.mjs.map +1 -0
- package/{inject-infinite-query.d.ts → dist/inject-infinite-query.d.mts} +13 -10
- package/dist/inject-infinite-query.d.mts.map +1 -0
- package/dist/inject-infinite-query.mjs +13 -0
- package/dist/inject-infinite-query.mjs.map +1 -0
- package/{inject-is-fetching.d.ts → dist/inject-is-fetching.d.mts} +11 -8
- package/dist/inject-is-fetching.d.mts.map +1 -0
- package/dist/inject-is-fetching.mjs +69 -0
- package/dist/inject-is-fetching.mjs.map +1 -0
- package/{inject-is-mutating.d.ts → dist/inject-is-mutating.d.mts} +11 -8
- package/dist/inject-is-mutating.d.mts.map +1 -0
- package/dist/inject-is-mutating.mjs +52 -0
- package/dist/inject-is-mutating.mjs.map +1 -0
- package/{inject-is-restoring.d.ts → dist/inject-is-restoring.d.mts} +10 -8
- package/dist/inject-is-restoring.d.mts.map +1 -0
- package/dist/inject-is-restoring.mjs +35 -0
- package/dist/inject-is-restoring.mjs.map +1 -0
- package/{inject-mutation-state.d.ts → dist/inject-mutation-state.d.mts} +13 -11
- package/dist/inject-mutation-state.d.mts.map +1 -0
- package/dist/inject-mutation-state.mjs +103 -0
- package/dist/inject-mutation-state.mjs.map +1 -0
- package/{inject-mutation.d.ts → dist/inject-mutation.d.mts} +12 -9
- package/dist/inject-mutation.d.mts.map +1 -0
- package/dist/inject-mutation.mjs +226 -0
- package/dist/inject-mutation.mjs.map +1 -0
- package/dist/inject-queries-experimental/index.d.mts +2 -0
- package/dist/inject-queries-experimental/index.mjs +2 -0
- package/{inject-queries.d.ts → dist/inject-queries.d.mts} +33 -53
- package/dist/inject-queries.d.mts.map +1 -0
- package/dist/inject-queries.mjs +203 -0
- package/dist/inject-queries.mjs.map +1 -0
- package/{inject-query-client.d.ts → dist/inject-query-client.d.mts} +6 -3
- package/dist/inject-query-client.d.mts.map +1 -0
- package/dist/inject-query-client.mjs +23 -0
- package/dist/inject-query-client.mjs.map +1 -0
- package/{inject-query.d.ts → dist/inject-query.d.mts} +13 -10
- package/dist/inject-query.d.mts.map +1 -0
- package/dist/inject-query.mjs +12 -0
- package/dist/inject-query.mjs.map +1 -0
- package/{mutation-options.d.ts → dist/mutation-options.d.mts} +5 -2
- package/dist/mutation-options.d.mts.map +1 -0
- package/dist/mutation-options.mjs +8 -0
- package/dist/mutation-options.mjs.map +1 -0
- package/dist/pending-tasks-compat.d.mts +9 -0
- package/dist/pending-tasks-compat.d.mts.map +1 -0
- package/dist/pending-tasks-compat.mjs +13 -0
- package/dist/pending-tasks-compat.mjs.map +1 -0
- package/{providers.d.ts → dist/providers.d.mts} +7 -5
- package/dist/providers.d.mts.map +1 -0
- package/dist/providers.mjs +124 -0
- package/dist/providers.mjs.map +1 -0
- package/{query-options.d.ts → dist/query-options.d.mts} +34 -31
- package/dist/query-options.d.mts.map +1 -0
- package/dist/query-options.mjs +8 -0
- package/dist/query-options.mjs.map +1 -0
- package/{signal-proxy.d.ts → dist/signal-proxy.d.mts} +5 -4
- package/dist/signal-proxy.d.mts.map +1 -0
- package/dist/signal-proxy.mjs +35 -0
- package/dist/signal-proxy.mjs.map +1 -0
- package/{types.d.ts → dist/types.d.mts} +24 -26
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +6 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +50 -20
- package/src/__tests__/infinite-query-options.test-d.ts +314 -0
- package/src/__tests__/infinite-query-options.test.ts +19 -0
- package/src/__tests__/inject-devtools-panel.test.ts +196 -0
- package/src/__tests__/inject-infinite-query.test-d.ts +66 -0
- package/src/__tests__/inject-infinite-query.test.ts +227 -0
- package/src/__tests__/inject-is-fetching.test.ts +108 -0
- package/src/__tests__/inject-is-mutating.test.ts +113 -0
- package/src/__tests__/inject-is-restoring.test.ts +93 -0
- package/src/__tests__/inject-mutation-state.test-d.ts +22 -0
- package/src/__tests__/inject-mutation-state.test.ts +198 -0
- package/src/__tests__/inject-mutation.test-d.ts +158 -0
- package/src/__tests__/inject-mutation.test.ts +1161 -0
- package/src/__tests__/inject-queries.test-d.ts +196 -0
- package/src/__tests__/inject-queries.test.ts +240 -0
- package/src/__tests__/inject-query.test-d.ts +357 -0
- package/src/__tests__/inject-query.test.ts +700 -0
- package/src/__tests__/mutation-options.test-d.ts +234 -0
- package/src/__tests__/mutation-options.test.ts +344 -0
- package/src/__tests__/pending-tasks.test.ts +644 -0
- package/src/__tests__/provide-query-client.test.ts +38 -0
- package/src/__tests__/provide-tanstack-query.test.ts +38 -0
- package/src/__tests__/query-options.test-d.ts +262 -0
- package/src/__tests__/query-options.test.ts +14 -0
- package/src/__tests__/signal-proxy.test.ts +27 -0
- package/src/__tests__/test-utils.ts +77 -0
- package/src/__tests__/with-devtools.test.ts +674 -0
- package/src/create-base-query.ts +176 -0
- package/src/devtools/index.ts +8 -0
- package/src/devtools/production/index.ts +1 -0
- package/src/devtools/stub.ts +7 -0
- package/src/devtools/types.ts +116 -0
- package/src/devtools/with-devtools.ts +182 -0
- package/src/devtools-panel/index.ts +8 -0
- package/src/devtools-panel/inject-devtools-panel.ts +110 -0
- package/src/devtools-panel/production/index.ts +1 -0
- package/src/devtools-panel/stub.ts +7 -0
- package/src/devtools-panel/types.ts +57 -0
- package/src/index.ts +60 -0
- package/src/infinite-query-options.ts +354 -0
- package/src/inject-infinite-query.ts +296 -0
- package/src/inject-is-fetching.ts +97 -0
- package/src/inject-is-mutating.ts +80 -0
- package/src/inject-is-restoring.ts +53 -0
- package/src/inject-mutation-state.ts +167 -0
- package/src/inject-mutation.ts +328 -0
- package/src/inject-queries-experimental/index.ts +1 -0
- package/src/inject-queries.ts +480 -0
- package/src/inject-query-client.ts +22 -0
- package/src/inject-query.ts +208 -0
- package/src/mutation-options.ts +121 -0
- package/src/pending-tasks-compat.ts +27 -0
- package/src/providers.ts +170 -0
- package/src/query-options.ts +292 -0
- package/src/signal-proxy.ts +46 -0
- package/src/types.ts +429 -0
- package/create-base-query.d.ts +0 -164
- package/create-base-query.mjs +0 -99
- package/create-base-query.mjs.map +0 -1
- package/devtools/index.d.ts +0 -2
- package/devtools/index.mjs +0 -5
- package/devtools/index.mjs.map +0 -1
- package/devtools/production/index.d.ts +0 -1
- package/devtools/stub.d.ts +0 -2
- package/devtools/stub.mjs +0 -8
- package/devtools/stub.mjs.map +0 -1
- package/devtools/types.d.ts +0 -103
- package/devtools/with-devtools.mjs +0 -106
- package/devtools/with-devtools.mjs.map +0 -1
- package/devtools-panel/index.d.ts +0 -2
- package/devtools-panel/index.mjs +0 -5
- package/devtools-panel/index.mjs.map +0 -1
- package/devtools-panel/inject-devtools-panel.mjs +0 -72
- package/devtools-panel/inject-devtools-panel.mjs.map +0 -1
- package/devtools-panel/production/index.d.ts +0 -1
- package/devtools-panel/stub.d.ts +0 -2
- package/devtools-panel/stub.mjs +0 -8
- package/devtools-panel/stub.mjs.map +0 -1
- package/devtools-panel/types.d.ts +0 -48
- package/index.d.ts +0 -25
- package/index.mjs.map +0 -1
- package/infinite-query-options.mjs +0 -7
- package/infinite-query-options.mjs.map +0 -1
- package/inject-infinite-query.mjs +0 -18
- package/inject-infinite-query.mjs.map +0 -1
- package/inject-is-fetching.mjs +0 -31
- package/inject-is-fetching.mjs.map +0 -1
- package/inject-is-mutating.mjs +0 -31
- package/inject-is-mutating.mjs.map +0 -1
- package/inject-is-restoring.mjs +0 -21
- package/inject-is-restoring.mjs.map +0 -1
- package/inject-mutation-state.mjs +0 -51
- package/inject-mutation-state.mjs.map +0 -1
- package/inject-mutation.mjs +0 -94
- package/inject-mutation.mjs.map +0 -1
- package/inject-queries-experimental/index.d.ts +0 -1
- package/inject-queries-experimental/index.mjs +0 -5
- package/inject-queries-experimental/index.mjs.map +0 -1
- package/inject-queries.mjs +0 -82
- package/inject-queries.mjs.map +0 -1
- package/inject-query-client.mjs +0 -9
- package/inject-query-client.mjs.map +0 -1
- package/inject-query.mjs +0 -14
- package/inject-query.mjs.map +0 -1
- package/mutation-options.mjs +0 -7
- package/mutation-options.mjs.map +0 -1
- package/pending-tasks-compat.d.ts +0 -7
- package/pending-tasks-compat.mjs +0 -19
- package/pending-tasks-compat.mjs.map +0 -1
- package/providers.mjs +0 -32
- package/providers.mjs.map +0 -1
- package/query-options.mjs +0 -7
- package/query-options.mjs.map +0 -1
- package/signal-proxy.mjs +0 -29
- package/signal-proxy.mjs.map +0 -1
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Injector,
|
|
3
|
+
NgZone,
|
|
4
|
+
assertInInjectionContext,
|
|
5
|
+
computed,
|
|
6
|
+
effect,
|
|
7
|
+
inject,
|
|
8
|
+
signal,
|
|
9
|
+
untracked,
|
|
10
|
+
} from '@angular/core'
|
|
11
|
+
import {
|
|
12
|
+
MutationObserver,
|
|
13
|
+
QueryClient,
|
|
14
|
+
noop,
|
|
15
|
+
notifyManager,
|
|
16
|
+
shouldThrowError,
|
|
17
|
+
} from '@tanstack/query-core'
|
|
18
|
+
import { signalProxy } from './signal-proxy'
|
|
19
|
+
import { PENDING_TASKS } from './pending-tasks-compat'
|
|
20
|
+
import type { PendingTaskRef } from './pending-tasks-compat'
|
|
21
|
+
import type { DefaultError, MutationObserverResult } from '@tanstack/query-core'
|
|
22
|
+
import type {
|
|
23
|
+
CreateMutateFunction,
|
|
24
|
+
CreateMutationOptions,
|
|
25
|
+
CreateMutationResult,
|
|
26
|
+
} from './types'
|
|
27
|
+
|
|
28
|
+
export interface InjectMutationOptions {
|
|
29
|
+
/**
|
|
30
|
+
* The `Injector` in which to create the mutation.
|
|
31
|
+
*
|
|
32
|
+
* If this is not provided, the current injection context will be used instead (via `inject`).
|
|
33
|
+
*/
|
|
34
|
+
injector?: Injector
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects.
|
|
39
|
+
* `injectMutation` is the function for that. Unlike queries, mutations are not run automatically.
|
|
40
|
+
*
|
|
41
|
+
* @remarks `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a
|
|
42
|
+
* second argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to
|
|
43
|
+
* the shared mutation definition. Callbacks defined in `injectMutationFn` fire for every mutation; per-call
|
|
44
|
+
* callbacks fire only for the latest call you've made — `mutateAsync` gives you a promise per call instead,
|
|
45
|
+
* so you can await `Promise.all`/`Promise.allSettled` over several calls and see each one's outcome.
|
|
46
|
+
* @see {@link mutationOptions} to share these options across multiple `injectMutation` call sites, or to look
|
|
47
|
+
* the mutation up elsewhere via its `mutationKey` (e.g. with `injectMutationState`).
|
|
48
|
+
* @param injectMutationFn - A function that returns mutation options. Similar to `computed` from Angular,
|
|
49
|
+
* this function runs in the reactive context, so signals read inside it drive the mutation's options.
|
|
50
|
+
* @param options - Additional configuration
|
|
51
|
+
* @returns The mutation result. Value fields are exposed as a `Signal` — read `data`/`error` by calling them
|
|
52
|
+
* (e.g. `mutation.data()`) — while function fields (`mutate`, `mutateAsync`, `reset`) are called directly,
|
|
53
|
+
* unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are type-guard methods you can call to narrow whether
|
|
54
|
+
* `data` is defined.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```angular-ts
|
|
58
|
+
* @Component({
|
|
59
|
+
* selector: 'todos',
|
|
60
|
+
* template: `
|
|
61
|
+
* @if (addMutation.isPending()) {
|
|
62
|
+
* <span>Adding todo...</span>
|
|
63
|
+
* } @else if (addMutation.isError()) {
|
|
64
|
+
* <div>An error occurred: {{ addMutation.error()?.message }}</div>
|
|
65
|
+
* }
|
|
66
|
+
* <button (click)="addMutation.mutate('Item')">Add</button>
|
|
67
|
+
* `,
|
|
68
|
+
* })
|
|
69
|
+
* export class Todos {
|
|
70
|
+
* readonly #queryClient = inject(QueryClient)
|
|
71
|
+
*
|
|
72
|
+
* readonly addMutation = injectMutation(() => ({
|
|
73
|
+
* mutationFn: addTodo,
|
|
74
|
+
* onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
75
|
+
* }))
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* Optimistic update via `onMutate`, rolling back on `onError`:
|
|
81
|
+
* ```angular-ts
|
|
82
|
+
* @Component({
|
|
83
|
+
* selector: 'todos',
|
|
84
|
+
* template: `<button (click)="addMutation.mutate('Item')">Add</button>`,
|
|
85
|
+
* })
|
|
86
|
+
* export class Todos {
|
|
87
|
+
* readonly #queryClient = inject(QueryClient)
|
|
88
|
+
*
|
|
89
|
+
* readonly addMutation = injectMutation(() => ({
|
|
90
|
+
* mutationFn: addTodo,
|
|
91
|
+
* onMutate: async (newTodo) => {
|
|
92
|
+
* await this.#queryClient.cancelQueries({ queryKey: ['todos'] })
|
|
93
|
+
* const previousTodos = this.#queryClient.getQueryData<Array<string>>(['todos'])
|
|
94
|
+
*
|
|
95
|
+
* this.#queryClient.setQueryData<Array<string>>(['todos'], (old) => [
|
|
96
|
+
* ...(old ?? []),
|
|
97
|
+
* newTodo,
|
|
98
|
+
* ])
|
|
99
|
+
*
|
|
100
|
+
* // Passed to `onError` as `onMutateResult` if the mutation fails.
|
|
101
|
+
* return { previousTodos }
|
|
102
|
+
* },
|
|
103
|
+
* onError: (_err, _newTodo, onMutateResult) => {
|
|
104
|
+
* this.#queryClient.setQueryData(['todos'], onMutateResult?.previousTodos)
|
|
105
|
+
* },
|
|
106
|
+
* onSettled: () => {
|
|
107
|
+
* this.#queryClient.invalidateQueries({ queryKey: ['todos'] })
|
|
108
|
+
* },
|
|
109
|
+
* }))
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a promise per
|
|
115
|
+
* call instead, so you can wait for all of them when they succeed:
|
|
116
|
+
* ```angular-ts
|
|
117
|
+
* @Component({
|
|
118
|
+
* selector: 'todos',
|
|
119
|
+
* template: `
|
|
120
|
+
* <button (click)="handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])">Add all</button>
|
|
121
|
+
* `,
|
|
122
|
+
* })
|
|
123
|
+
* export class Todos {
|
|
124
|
+
* readonly #queryClient = inject(QueryClient)
|
|
125
|
+
*
|
|
126
|
+
* readonly addMutation = injectMutation(() => ({
|
|
127
|
+
* mutationFn: addTodo,
|
|
128
|
+
* onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
129
|
+
* }))
|
|
130
|
+
*
|
|
131
|
+
* async handleAddAll(todos: Array<string>) {
|
|
132
|
+
* try {
|
|
133
|
+
* await Promise.all(todos.map((todo) => this.addMutation.mutateAsync(todo)))
|
|
134
|
+
* } catch (error) {
|
|
135
|
+
* console.error('Failed to add todos:', error)
|
|
136
|
+
* }
|
|
137
|
+
* }
|
|
138
|
+
* }
|
|
139
|
+
* ```
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* If some of the mutations above can fail independently of the others, and you want to know which ones did —
|
|
143
|
+
* rather than losing that information the moment the first one rejects — swap `Promise.all` for
|
|
144
|
+
* `Promise.allSettled`:
|
|
145
|
+
* ```angular-ts
|
|
146
|
+
* @Component({
|
|
147
|
+
* selector: 'todos',
|
|
148
|
+
* template: `
|
|
149
|
+
* <button (click)="handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])">Add all</button>
|
|
150
|
+
* `,
|
|
151
|
+
* })
|
|
152
|
+
* export class Todos {
|
|
153
|
+
* readonly #queryClient = inject(QueryClient)
|
|
154
|
+
*
|
|
155
|
+
* readonly addMutation = injectMutation(() => ({
|
|
156
|
+
* mutationFn: addTodo,
|
|
157
|
+
* onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
158
|
+
* }))
|
|
159
|
+
*
|
|
160
|
+
* async handleAddAll(todos: Array<string>) {
|
|
161
|
+
* const addResults = await Promise.allSettled(
|
|
162
|
+
* todos.map((todo) => this.addMutation.mutateAsync(todo)),
|
|
163
|
+
* )
|
|
164
|
+
*
|
|
165
|
+
* addResults.forEach((addResult, index) => {
|
|
166
|
+
* if (addResult.status === 'rejected') {
|
|
167
|
+
* console.error(`Failed to add "${todos[index]}":`, addResult.reason)
|
|
168
|
+
* }
|
|
169
|
+
* })
|
|
170
|
+
* }
|
|
171
|
+
* }
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
export function injectMutation<
|
|
175
|
+
TData = unknown,
|
|
176
|
+
TError = DefaultError,
|
|
177
|
+
TVariables = void,
|
|
178
|
+
TOnMutateResult = unknown,
|
|
179
|
+
>(
|
|
180
|
+
injectMutationFn: () => CreateMutationOptions<
|
|
181
|
+
TData,
|
|
182
|
+
TError,
|
|
183
|
+
TVariables,
|
|
184
|
+
TOnMutateResult
|
|
185
|
+
>,
|
|
186
|
+
options?: InjectMutationOptions,
|
|
187
|
+
): CreateMutationResult<TData, TError, TVariables, TOnMutateResult> {
|
|
188
|
+
!options?.injector && assertInInjectionContext(injectMutation)
|
|
189
|
+
const injector = options?.injector ?? inject(Injector)
|
|
190
|
+
const ngZone = injector.get(NgZone)
|
|
191
|
+
const pendingTasks = injector.get(PENDING_TASKS)
|
|
192
|
+
const queryClient = injector.get(QueryClient)
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* computed() is used so signals can be inserted into the options
|
|
196
|
+
* making it reactive. Wrapping options in a function ensures embedded expressions
|
|
197
|
+
* are preserved and can keep being applied after signal changes
|
|
198
|
+
*/
|
|
199
|
+
const optionsSignal = computed(injectMutationFn)
|
|
200
|
+
|
|
201
|
+
const observerSignal = (() => {
|
|
202
|
+
let instance: MutationObserver<
|
|
203
|
+
TData,
|
|
204
|
+
TError,
|
|
205
|
+
TVariables,
|
|
206
|
+
TOnMutateResult
|
|
207
|
+
> | null = null
|
|
208
|
+
|
|
209
|
+
return computed(() => {
|
|
210
|
+
return (instance ||= new MutationObserver(queryClient, optionsSignal()))
|
|
211
|
+
})
|
|
212
|
+
})()
|
|
213
|
+
|
|
214
|
+
const mutateFnSignal = computed<
|
|
215
|
+
CreateMutateFunction<TData, TError, TVariables, TOnMutateResult>
|
|
216
|
+
>(() => {
|
|
217
|
+
const observer = observerSignal()
|
|
218
|
+
return (
|
|
219
|
+
...args: Parameters<
|
|
220
|
+
CreateMutateFunction<TData, TError, TVariables, TOnMutateResult>
|
|
221
|
+
>
|
|
222
|
+
) => {
|
|
223
|
+
observer.mutate(args[0] as TVariables, args[1]).catch(noop)
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Computed signal that gets result from mutation cache based on passed options
|
|
229
|
+
*/
|
|
230
|
+
const resultFromInitialOptionsSignal = computed(() => {
|
|
231
|
+
const observer = observerSignal()
|
|
232
|
+
return observer.getCurrentResult()
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Signal that contains result set by subscriber
|
|
237
|
+
*/
|
|
238
|
+
const resultFromSubscriberSignal = signal<MutationObserverResult<
|
|
239
|
+
TData,
|
|
240
|
+
TError,
|
|
241
|
+
TVariables,
|
|
242
|
+
TOnMutateResult
|
|
243
|
+
> | null>(null)
|
|
244
|
+
|
|
245
|
+
effect(
|
|
246
|
+
() => {
|
|
247
|
+
const observer = observerSignal()
|
|
248
|
+
const observerOptions = optionsSignal()
|
|
249
|
+
|
|
250
|
+
untracked(() => {
|
|
251
|
+
observer.setOptions(observerOptions)
|
|
252
|
+
})
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
injector,
|
|
256
|
+
},
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
effect(
|
|
260
|
+
(onCleanup) => {
|
|
261
|
+
// observer.trackResult is not used as this optimization is not needed for Angular
|
|
262
|
+
const observer = observerSignal()
|
|
263
|
+
let pendingTaskRef: PendingTaskRef | null = null
|
|
264
|
+
|
|
265
|
+
untracked(() => {
|
|
266
|
+
const unsubscribe = ngZone.runOutsideAngular(() =>
|
|
267
|
+
observer.subscribe(
|
|
268
|
+
notifyManager.batchCalls((state) => {
|
|
269
|
+
ngZone.run(() => {
|
|
270
|
+
// Track pending task when mutation is pending
|
|
271
|
+
if (state.isPending && !pendingTaskRef) {
|
|
272
|
+
pendingTaskRef = pendingTasks.add()
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Clear pending task when mutation is no longer pending
|
|
276
|
+
if (!state.isPending && pendingTaskRef) {
|
|
277
|
+
pendingTaskRef()
|
|
278
|
+
pendingTaskRef = null
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (
|
|
282
|
+
state.isError &&
|
|
283
|
+
shouldThrowError(observer.options.throwOnError, [state.error])
|
|
284
|
+
) {
|
|
285
|
+
ngZone.onError.emit(state.error)
|
|
286
|
+
throw state.error
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
resultFromSubscriberSignal.set(state)
|
|
290
|
+
})
|
|
291
|
+
}),
|
|
292
|
+
),
|
|
293
|
+
)
|
|
294
|
+
onCleanup(() => {
|
|
295
|
+
// Clean up any pending task on destroy
|
|
296
|
+
if (pendingTaskRef) {
|
|
297
|
+
pendingTaskRef()
|
|
298
|
+
pendingTaskRef = null
|
|
299
|
+
}
|
|
300
|
+
unsubscribe()
|
|
301
|
+
})
|
|
302
|
+
})
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
injector,
|
|
306
|
+
},
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
const resultSignal = computed(() => {
|
|
310
|
+
const resultFromSubscriber = resultFromSubscriberSignal()
|
|
311
|
+
const resultFromInitialOptions = resultFromInitialOptionsSignal()
|
|
312
|
+
|
|
313
|
+
const result = resultFromSubscriber ?? resultFromInitialOptions
|
|
314
|
+
|
|
315
|
+
return {
|
|
316
|
+
...result,
|
|
317
|
+
mutate: mutateFnSignal(),
|
|
318
|
+
mutateAsync: result.mutate,
|
|
319
|
+
}
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
return signalProxy(resultSignal) as CreateMutationResult<
|
|
323
|
+
TData,
|
|
324
|
+
TError,
|
|
325
|
+
TVariables,
|
|
326
|
+
TOnMutateResult
|
|
327
|
+
>
|
|
328
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../inject-queries'
|