| author | |
| committer | |
| log | 2486cbb9d095be3d97251f02f076d0e2a1cb0033 |
| tree | 07dc76904411d15ae8b97c3c862fb3b074afcd24 |
| parent | c6028dcd497631ff2d5a5a6c24b74b41f3ad21f4 |
| signature |
5 files changed, 22 insertions(+), 13 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-beta.3", | 3 | "version": "1.0.0-beta.4", |
| 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.md+3-3| ... | @@ -14,7 +14,7 @@ The primary gains React Mutation provides are | ... | @@ -14,7 +14,7 @@ The primary gains React Mutation provides are |
| 14 | `isError`, unhandled errors will be propagated to a global handler, which can | 14 | `isError`, unhandled errors will be propagated to a global handler, which can |
| 15 | display a UI toast. Otherwise, the component can display the error locally. | 15 | display a UI toast. Otherwise, the component can display the error locally. |
| 16 | - Optimistic helpers allow defining rollbacks and refetching logic independant | 16 | - Optimistic helpers allow defining rollbacks and refetching logic independant |
| 17 | of the actual mutation. The [built in helpers for React Query](#React-Query-Optimistic-Helpers) show this power in more detail. | 17 | of the actual mutation. The [built in helpers for React Query](#react-query-optimistic-helpers) show this power in more detail. |
| 18 | - Debounced Mutations are just so awesome to use. | 18 | - Debounced Mutations are just so awesome to use. |
| 19 | 19 | ||
| 20 | ## Usage | 20 | ## Usage |
| ... | @@ -22,11 +22,11 @@ The primary gains React Mutation provides are | ... | @@ -22,11 +22,11 @@ The primary gains React Mutation provides are |
| 22 | This library declares two kinds of mutations. Each kind has different behavior | 22 | This library declares two kinds of mutations. Each kind has different behavior |
| 23 | around concurrent operations. | 23 | around concurrent operations. |
| 24 | 24 | ||
| 25 | - [**Blocking Mutations**](#Blocking-Mutations): A mutation blocks the UI until it | 25 | - [**Blocking Mutations**](#blocking-mutations): A mutation blocks the UI until it |
| 26 | is complete. You press a button, a pending state appears, then it completes. | 26 | is complete. You press a button, a pending state appears, then it completes. |
| 27 | This works great for forms, creations and deletions, and is similar to React | 27 | This works great for forms, creations and deletions, and is similar to React |
| 28 | Query's mutation system. | 28 | Query's mutation system. |
| 29 | - [**Debounced Mutations**](#Debounced-Mutations): Each call to the mutation applies | 29 | - [**Debounced Mutations**](#debounced-mutations): Each call to the mutation applies |
| 30 | new optimistic state, and after a debounce (or throttle) the new optimistic | 30 | new optimistic state, and after a debounce (or throttle) the new optimistic |
| 31 | state is committed to the API. UI never shows a pending state for these. | 31 | state is committed to the API. UI never shows a pending state for these. |
| 32 | This works great for auto-saving input fields, follow buttons, and is | 32 | This works great for auto-saving input fields, follow buttons, and is |
src/blocking.ts+3-2| ... | @@ -34,7 +34,7 @@ export interface BlockingMutationOptions< | ... | @@ -34,7 +34,7 @@ export interface BlockingMutationOptions< |
| 34 | * Used in success messages. | 34 | * Used in success messages. |
| 35 | * Phrase it as a complete success message, e.g., "Deleted item successfully" | 35 | * Phrase it as a complete success message, e.g., "Deleted item successfully" |
| 36 | */ | 36 | */ |
| 37 | describeResult: string | ((context: Config["context"] & { args: Args; result: Result }) => string); | 37 | describeResult: string | ((context: Config["context"] & { args: Args; result: Result }) => string) | null; |
| 38 | /** | 38 | /** |
| 39 | * Specifying the optimistic strategy is required. To disable, pass an empty | 39 | * Specifying the optimistic strategy is required. To disable, pass an empty |
| 40 | * function with a comment to document why it isn't needed. | 40 | * function with a comment to document why it isn't needed. |
| ... | @@ -169,8 +169,9 @@ export class BlockingMutation< | ... | @@ -169,8 +169,9 @@ export class BlockingMutation< |
| 169 | : describe; | 169 | : describe; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | describeResult(args: Args, result: Result): string { | 172 | describeResult(args: Args, result: Result): string | undefined { |
| 173 | const { describeResult } = this.#options; | 173 | const { describeResult } = this.#options; |
| 174 | if (describeResult === null) return undefined; | ||
| 174 | return typeof describeResult === "function" | 175 | return typeof describeResult === "function" |
| 175 | ? describeResult({ ...this.#client.context, args, result }) | 176 | ? describeResult({ ...this.#client.context, args, result }) |
| 176 | : describeResult; | 177 | : describeResult; |
src/debounced.ts+14-6| ... | @@ -14,7 +14,10 @@ export interface DebouncedMutationOptions< | ... | @@ -14,7 +14,10 @@ export interface DebouncedMutationOptions< |
| 14 | * A rest params type is used to allow type inference. Place this function first to | 14 | * A rest params type is used to allow type inference. Place this function first to |
| 15 | * ensure TypeScript correctly infers the argument type for the rest of the functions. | 15 | * ensure TypeScript correctly infers the argument type for the rest of the functions. |
| 16 | */ | 16 | */ |
| 17 | optimistic: (context: DebouncedOptimisticContext<Config>, ...args: Args) => void; | 17 | optimistic: ( |
| 18 | context: DebouncedOptimisticContext<Config>, | ||
| 19 | ...args: Args | ||
| 20 | ) => void; | ||
| 18 | /** | 21 | /** |
| 19 | * Retrieve the current/optimistic value of the mutation. When this returns | 22 | * Retrieve the current/optimistic value of the mutation. When this returns |
| 20 | * the same thing as when the mutation started, it means that `mutate` does | 23 | * the same thing as when the mutation started, it means that `mutate` does |
| ... | @@ -56,7 +59,7 @@ export interface DebouncedMutationOptions< | ... | @@ -56,7 +59,7 @@ export interface DebouncedMutationOptions< |
| 56 | ) => string); | 59 | ) => string); |
| 57 | /** | 60 | /** |
| 58 | * Used in success messages. | 61 | * Used in success messages. |
| 59 | * Phrase it as a complete success message, e.g., "Renamed item successfully" | 62 | * Phrase it as a complete success message: "Renamed item successfully" |
| 60 | */ | 63 | */ |
| 61 | describeResult: | 64 | describeResult: |
| 62 | | string | 65 | | string |
| ... | @@ -64,7 +67,8 @@ export interface DebouncedMutationOptions< | ... | @@ -64,7 +67,8 @@ export interface DebouncedMutationOptions< |
| 64 | context: DebouncedCommitContext<NoInfer<Args>, Optimistic, Config> & { | 67 | context: DebouncedCommitContext<NoInfer<Args>, Optimistic, Config> & { |
| 65 | result: Result; | 68 | result: Result; |
| 66 | }, | 69 | }, |
| 67 | ) => string); | 70 | ) => string) |
| 71 | | null; | ||
| 68 | /** | 72 | /** |
| 69 | * Refetch all of the data this mutation could have affected. | 73 | * Refetch all of the data this mutation could have affected. |
| 70 | */ | 74 | */ |
| ... | @@ -251,15 +255,16 @@ export class DebouncedMutation< | ... | @@ -251,15 +255,16 @@ export class DebouncedMutation< |
| 251 | } | 255 | } |
| 252 | 256 | ||
| 253 | // Not available for debounced mutations - success reporting happens during commit | 257 | // Not available for debounced mutations - success reporting happens during commit |
| 254 | describeResult: undefined = undefined; | 258 | describeResult: null = null; |
| 255 | 259 | ||
| 256 | #describeResult( | 260 | #describeResult( |
| 257 | args: Args, | 261 | args: Args, |
| 258 | initial: Optimistic, | 262 | initial: Optimistic, |
| 259 | current: Optimistic, | 263 | current: Optimistic, |
| 260 | result: Result, | 264 | result: Result, |
| 261 | ): string { | 265 | ): string | undefined { |
| 262 | const { describeResult } = this.#options; | 266 | const { describeResult } = this.#options; |
| 267 | if (describeResult === null) return undefined; | ||
| 263 | return typeof describeResult === "function" | 268 | return typeof describeResult === "function" |
| 264 | ? describeResult({ | 269 | ? describeResult({ |
| 265 | ...this.#client.context, | 270 | ...this.#client.context, |
| ... | @@ -302,7 +307,10 @@ export class DebouncedMutation< | ... | @@ -302,7 +307,10 @@ export class DebouncedMutation< |
| 302 | 307 | ||
| 303 | // If this is the first call in the debounced run, take a snapshot and create shared helpers | 308 | // If this is the first call in the debounced run, take a snapshot and create shared helpers |
| 304 | if (channel.initial === null) { | 309 | if (channel.initial === null) { |
| 305 | channel.initial = this.#options.getValue({ ...this.#client.context, args }); | 310 | channel.initial = this.#options.getValue({ |
| 311 | ...this.#client.context, | ||
| 312 | args, | ||
| 313 | }); | ||
| 306 | channel.firstArgs = args; | 314 | channel.firstArgs = args; |
| 307 | 315 | ||
| 308 | // Create shared onRefetch handler for the debounced run | 316 | // Create shared onRefetch handler for the debounced run |
src/types.ts+1-1| ... | @@ -14,7 +14,7 @@ export interface Mutation<Args extends unknown[], Result> { | ... | @@ -14,7 +14,7 @@ export interface Mutation<Args extends unknown[], Result> { |
| 14 | cb: (update: MutationEvent<Result>) => void, | 14 | cb: (update: MutationEvent<Result>) => void, |
| 15 | ): () => void; | 15 | ): () => void; |
| 16 | describe(...args: Args): string; | 16 | describe(...args: Args): string; |
| 17 | describeResult?: (args: Args, result: Result) => string | undefined; | 17 | describeResult: ((args: Args, result: Result) => string | undefined) | null; |
| 18 | client: MutationClient<object, object>; | 18 | client: MutationClient<object, object>; |
| 19 | } | 19 | } |
| 20 | 20 |