authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-01-29 16:56:46-08:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-01-29 16:57:23-08:00
logd5c11b294ef2257d31778609caddf9980e24e6f6
tree19754a39aaf32be7470df76e19359f05f95a5093
parentb51077c59854543b2c70ea2be825d68cfb567d8c
signaturelock-open Commit is signed but in an unrecognized format.

feat: arrayFilter and useMutate args


3 files changed, 36 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-beta.7",3 "version": "1.0.0-beta.8",
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",
src/react.ts+13
...@@ -45,6 +45,7 @@ export interface UseMutateResultBase<Args extends unknown[], Result> {...@@ -45,6 +45,7 @@ export interface UseMutateResultBase<Args extends unknown[], Result> {
45 ..._: [...args: Args, options: RunOptions<Result>]45 ..._: [...args: Args, options: RunOptions<Result>]
46 ) => Promise<Result>;46 ) => Promise<Result>;
47 clear: () => void;47 clear: () => void;
48 args: Args | undefined;
48}49}
4950
50export interface UseMutateSuccess<Result> {51export interface UseMutateSuccess<Result> {
...@@ -175,7 +176,11 @@ class Observer<Args extends unknown[], Result> {...@@ -175,7 +176,11 @@ class Observer<Args extends unknown[], Result> {
175 run(...args: Args) {176 run(...args: Args) {
176 const mutation = this.mutation;177 const mutation = this.mutation;
177 if (!mutation) return;178 if (!mutation) return;
179 const argsChanged = this.currentArgs !== args;
178 this.currentArgs = args;180 this.currentArgs = args;
181 if (argsChanged && this.watched.has("args")) {
182 this.setRerender(Math.random());
183 }
179 const key = mutation.key(args);184 const key = mutation.key(args);
180 if (key !== this.currentKey) {185 if (key !== this.currentKey) {
181 this.currentKey = key;186 this.currentKey = key;
...@@ -249,7 +254,11 @@ class Observer<Args extends unknown[], Result> {...@@ -249,7 +254,11 @@ class Observer<Args extends unknown[], Result> {
249 const args = array.slice() as Args;254 const args = array.slice() as Args;
250 const options = args.pop() as RunOptions<Result>;255 const options = args.pop() as RunOptions<Result>;
251256
257 const argsChanged = this.currentArgs !== args;
252 this.currentArgs = args;258 this.currentArgs = args;
259 if (argsChanged && this.watched.has("args")) {
260 this.setRerender(Math.random());
261 }
253 const key = mutation.key(args);262 const key = mutation.key(args);
254263
255 // Set up subscription if key changed264 // Set up subscription if key changed
...@@ -347,6 +356,10 @@ class Observer<Args extends unknown[], Result> {...@@ -347,6 +356,10 @@ class Observer<Args extends unknown[], Result> {
347 self.watched.add("isOptimisticData");356 self.watched.add("isOptimisticData");
348 return self.state.isOptimisticData;357 return self.state.isOptimisticData;
349 },358 },
359 get args() {
360 self.watched.add("args");
361 return self.currentArgs ?? undefined;
362 },
350 } as UseMutateResult<Args, Result>))(this);363 } as UseMutateResult<Args, Result>))(this);
351}364}
352365
src/tanstack-query.ts+22
...@@ -509,6 +509,28 @@ class TanstackQueryOptimisticHelpers {...@@ -509,6 +509,28 @@ class TanstackQueryOptimisticHelpers {
509 });509 });
510 }510 }
511511
512 /**
513 * Filter items to just include items that match `filter`. This is the inverse of `arrayRemove`
514 * If the query or path doesn't exist, the updater is skipped.
515 */
516 arrayFilter<Data>(
517 queryKey: QueryKeyAndFn<Data[] | null>,
518 filter: (
519 item: Data,
520 index: number,
521 ) => boolean,
522 ) {
523 const prev = this.#get(queryKey);
524 if (!prev || !Array.isArray(prev)) return;
525
526 const newArray = prev.filter(filter);
527 this.#set(queryKey, newArray);
528 this.#onRestore(() => {
529 // TODO: splice items back in case original changed
530 this.#set(queryKey, prev);
531 });
532 }
533
512 /**534 /**
513 * Update items in an array that match a `filter`.535 * Update items in an array that match a `filter`.
514 * If the query or path doesn't exist, the updater is skipped.536 * If the query or path doesn't exist, the updater is skipped.