| 171 | } |
| 172 | |
| 173 | async execute(variables: TVariables): Promise<TData> { |
| 174 | const onContinue = () => { |
| 175 | this.#dispatch({ type: 'continue' }) |
| 176 | } |
| 177 | |
| 178 | const mutationFnContext = { |
| 179 | client: this.#client, |
| 180 | meta: this.options.meta, |
| 181 | mutationKey: this.options.mutationKey, |
| 182 | } satisfies MutationFunctionContext |
| 183 | |
| 184 | this.#retryer = createRetryer({ |
| 185 | fn: () => { |
| 186 | if (!this.options.mutationFn) { |
| 187 | return Promise.reject(new Error('No mutationFn found')) |
| 188 | } |
| 189 | |
| 190 | return this.options.mutationFn(variables, mutationFnContext) |
| 191 | }, |
| 192 | onFail: (failureCount, error) => { |
| 193 | this.#dispatch({ type: 'failed', failureCount, error }) |
| 194 | }, |
| 195 | onPause: () => { |
| 196 | this.#dispatch({ type: 'pause' }) |
| 197 | }, |
| 198 | onContinue, |
| 199 | retry: this.options.retry ?? 0, |
| 200 | retryDelay: this.options.retryDelay, |
| 201 | networkMode: this.options.networkMode, |
| 202 | canRun: () => this.#mutationCache.canRun(this), |
| 203 | }) |
| 204 | |
| 205 | const restored = this.state.status === 'pending' |
| 206 | const isPaused = !this.#retryer.canStart() |
| 207 | |
| 208 | try { |
| 209 | if (restored) { |
| 210 | // Dispatch continue action to unpause restored mutation |
| 211 | onContinue() |
| 212 | } else { |
| 213 | this.#dispatch({ type: 'pending', variables, isPaused }) |
| 214 | // Notify cache callback |
| 215 | await this.#mutationCache.config.onMutate?.( |
| 216 | variables, |
| 217 | this as Mutation<unknown, unknown, unknown, unknown>, |
| 218 | mutationFnContext, |
| 219 | ) |
| 220 | const context = await this.options.onMutate?.( |
| 221 | variables, |
| 222 | mutationFnContext, |
| 223 | ) |
| 224 | if (context !== this.state.context) { |
| 225 | this.#dispatch({ |
| 226 | type: 'pending', |
| 227 | context, |
| 228 | variables, |
| 229 | isPaused, |
| 230 | }) |