| author | |
| committer | |
| log | 9fe44b404d1cfae5e4751ac3ef020ef8da521b1a |
| tree | 8b51c37b5ffc230b053e5a5a9256b9ffab28c7b6 |
| parent | 30b230b64fca127fd768443d19b768ab5a7f88a2 |
| signature |
4 files changed, 56 insertions(+), 1 deletions(-)
jsr.json+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | { | 1 | { |
| 2 | "name": "@clo/react-mutation", | 2 | "name": "@clo/react-mutation", |
| 3 | "version": "1.0.0", | 3 | "version": "1.1.0", |
| 4 | "exports": { | 4 | "exports": { |
| 5 | ".": "./src/mod.ts", | 5 | ".": "./src/mod.ts", |
| 6 | "./tanstack-query.ts": "./src/tanstack-query.ts", | 6 | "./tanstack-query.ts": "./src/tanstack-query.ts", |
readme.changes.md created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | # notable changes in React Mutation | ||
| 2 | |||
| 3 | ## v1.1 | ||
| 4 | |||
| 5 | - Add `runAsHeadlessPromise`. The function name is intentionally long to avoid using it, please use `runWithOptions` instead. | ||
src/mutation.ts+40| ... | @@ -256,6 +256,46 @@ export class BlockingMutation< | ... | @@ -256,6 +256,46 @@ export class BlockingMutation< |
| 256 | this.runWithOptions(...args, {}); | 256 | this.runWithOptions(...args, {}); |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | /** | ||
| 260 | * Using this in any situation is likely incorrect. Use {@linkcode runWithOptions} | ||
| 261 | * to handle success and error. | ||
| 262 | * | ||
| 263 | * By using this, you must handle the success and error conditions of the | ||
| 264 | * promise, or else the user will never see the result on screen. If the | ||
| 265 | * mutation has snapshots, be aware that cancelled mutations are implemented | ||
| 266 | * with promises that never resolve. | ||
| 267 | */ | ||
| 268 | runAsHeadlessPromise(...array: [...Args, RunOptions<Result>]): Promise<Result> { | ||
| 269 | if (!this.#client.enabled) { | ||
| 270 | throw new Error( | ||
| 271 | "MutationClient was passed enabled: false. Are you trying to perform a mutation from SSR?", | ||
| 272 | ); | ||
| 273 | } | ||
| 274 | |||
| 275 | const args = array.slice() as Args; | ||
| 276 | const { onSuccess, onSuccessDataOnly, onError, onSettled, onRestore } = args | ||
| 277 | .pop() as RunOptions<Result>; | ||
| 278 | const promise = this.#runWithOptions(args, onRestore, true); | ||
| 279 | return promise.then((result) => { | ||
| 280 | // Call user handlers | ||
| 281 | onSuccess?.(result); | ||
| 282 | onSuccessDataOnly?.(result); | ||
| 283 | onSettled?.({ status: "success", result }); | ||
| 284 | return result; | ||
| 285 | }).catch((caught: unknown) => { | ||
| 286 | // Extract error and description if this is a wrapped mutation error | ||
| 287 | const isMutationError = (caught as MutationError)?.__mutationError === true; | ||
| 288 | const error = isMutationError ? (caught as MutationError).error : caught; | ||
| 289 | const description = isMutationError ? (caught as MutationError).description : this.describe(...args); | ||
| 290 | |||
| 291 | // Call user handlers with the unwrapped error | ||
| 292 | onError?.(error); | ||
| 293 | onSettled?.({ status: "error", error }); | ||
| 294 | |||
| 295 | throw caught; | ||
| 296 | }); | ||
| 297 | } | ||
| 298 | |||
| 259 | /** Calls the mutation with custom handlers that can suppress global handlers. */ | 299 | /** Calls the mutation with custom handlers that can suppress global handlers. */ |
| 260 | runWithOptions(...array: [...Args, RunOptions<Result>]): void { | 300 | runWithOptions(...array: [...Args, RunOptions<Result>]): void { |
| 261 | if (!this.#client.enabled) { | 301 | if (!this.#client.enabled) { |
src/types.ts+10| ... | @@ -5,6 +5,16 @@ export interface Mutation<Args extends unknown[], Result> { | ... | @@ -5,6 +5,16 @@ export interface Mutation<Args extends unknown[], Result> { |
| 5 | run(...args: Args): void; | 5 | run(...args: Args): void; |
| 6 | /** Calls the mutation with custom handlers that can suppress global handlers. */ | 6 | /** Calls the mutation with custom handlers that can suppress global handlers. */ |
| 7 | runWithOptions(...args: [...args: Args, options: RunOptions<Result>]): void; | 7 | runWithOptions(...args: [...args: Args, options: RunOptions<Result>]): void; |
| 8 | /** | ||
| 9 | * Using this in any situation is likely incorrect, even internally. | ||
| 10 | * Use {@linkcode runWithOptions} to handle success and error. | ||
| 11 | * | ||
| 12 | * By using this, you must handle the success and error conditions of the | ||
| 13 | * promise, or else the user will never see the result on screen. If the | ||
| 14 | * mutation has snapshots, be aware that cancelled mutations are implemented | ||
| 15 | * with promises that never resolve. | ||
| 16 | */ | ||
| 17 | runAsHeadlessPromise(...array: [...Args, RunOptions<Result>]): Promise<Result>; | ||
| 8 | 18 | ||
| 9 | /** Returns the concurrency key used for a given set of arguments */ | 19 | /** Returns the concurrency key used for a given set of arguments */ |
| 10 | key(args: Args): string; | 20 | key(args: Args): string; |