@veams/status-quo-query 0.5.0 → 0.7.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/README.md +98 -40
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/mutation.d.ts +8 -8
- package/dist/mutation.js +3 -3
- package/dist/mutation.js.map +1 -1
- package/dist/provider.d.ts +9 -9
- package/dist/provider.js +16 -14
- package/dist/provider.js.map +1 -1
- package/dist/query.d.ts +9 -8
- package/dist/query.js +3 -3
- package/dist/query.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/tracked.spec.ts +29 -29
- package/src/index.ts +3 -3
- package/src/mutation.ts +9 -9
- package/src/provider.ts +28 -26
- package/src/query.ts +10 -9
package/README.md
CHANGED
|
@@ -23,10 +23,10 @@ Root exports:
|
|
|
23
23
|
- `QueryManager`
|
|
24
24
|
- `CreateQuery`
|
|
25
25
|
- `CreateMutation`
|
|
26
|
-
- `
|
|
27
|
-
- `
|
|
28
|
-
- `
|
|
29
|
-
- `
|
|
26
|
+
- `CreateQueryAndMutation`
|
|
27
|
+
- `CreateMutationWithDefaults`
|
|
28
|
+
- `CreateUntrackedQuery`
|
|
29
|
+
- `CreateUntrackedMutation`
|
|
30
30
|
- `QueryService`
|
|
31
31
|
- `MutationService`
|
|
32
32
|
- `QueryServiceSnapshot`
|
|
@@ -75,12 +75,14 @@ const saveProduct = async (variables: {
|
|
|
75
75
|
saved: true as const,
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
const
|
|
78
|
+
const fetchUser = async (userId: number) => ({ id: userId, name: 'Ada' });
|
|
79
|
+
|
|
80
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
79
81
|
'applicationId',
|
|
80
82
|
'productId',
|
|
81
83
|
] as const);
|
|
82
84
|
|
|
83
|
-
const productQuery =
|
|
85
|
+
const productQuery = createQuery(
|
|
84
86
|
['product', { deps: { applicationId: 'app-1', productId: 'product-1' }, view: { page: 1 } }],
|
|
85
87
|
() => fetchProduct('app-1', 'product-1'),
|
|
86
88
|
{
|
|
@@ -88,7 +90,7 @@ const productQuery = createTrackedQuery(
|
|
|
88
90
|
}
|
|
89
91
|
);
|
|
90
92
|
|
|
91
|
-
const updateProduct =
|
|
93
|
+
const updateProduct = createMutation(saveProduct, {
|
|
92
94
|
invalidateOn: 'success',
|
|
93
95
|
});
|
|
94
96
|
|
|
@@ -99,7 +101,7 @@ await updateProduct.mutate({
|
|
|
99
101
|
productName: 'Ada',
|
|
100
102
|
});
|
|
101
103
|
|
|
102
|
-
const userQuery = manager.
|
|
104
|
+
const userQuery = manager.createUntrackedQuery(['user', 42], () => fetchUser(42), {
|
|
103
105
|
enabled: false,
|
|
104
106
|
});
|
|
105
107
|
await userQuery.refetch();
|
|
@@ -163,18 +165,18 @@ const saveProduct = async (variables: {
|
|
|
163
165
|
productName: string;
|
|
164
166
|
}) => variables;
|
|
165
167
|
|
|
166
|
-
const [
|
|
168
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
167
169
|
'applicationId',
|
|
168
170
|
'productId',
|
|
169
171
|
] as const);
|
|
170
172
|
|
|
171
|
-
const productQuery =
|
|
173
|
+
const productQuery = createQuery(
|
|
172
174
|
['product', { deps: { applicationId, productId }, view: { page: 1 } }],
|
|
173
175
|
() => fetchProduct(applicationId, productId),
|
|
174
176
|
{ enabled: false }
|
|
175
177
|
);
|
|
176
178
|
|
|
177
|
-
const saveProductMutation =
|
|
179
|
+
const saveProductMutation = createMutation(saveProduct);
|
|
178
180
|
|
|
179
181
|
await saveProductMutation.mutate({
|
|
180
182
|
applicationId,
|
|
@@ -208,22 +210,22 @@ const saveProduct = async (variables: {
|
|
|
208
210
|
productName: string;
|
|
209
211
|
}) => variables;
|
|
210
212
|
|
|
211
|
-
const [
|
|
213
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
212
214
|
'applicationId',
|
|
213
215
|
'productId',
|
|
214
216
|
] as const);
|
|
215
217
|
|
|
216
|
-
|
|
218
|
+
createQuery(
|
|
217
219
|
['product', { deps: { applicationId: 'app-1', productId: 'product-1' }, view: { page: 1 } }],
|
|
218
220
|
() => fetchProduct('app-1', 'product-1')
|
|
219
221
|
);
|
|
220
222
|
|
|
221
|
-
|
|
223
|
+
createQuery(
|
|
222
224
|
['product', { deps: { applicationId: 'app-1', productId: 'product-2' }, view: { page: 1 } }],
|
|
223
225
|
() => fetchProduct('app-1', 'product-2')
|
|
224
226
|
);
|
|
225
227
|
|
|
226
|
-
const renameProduct =
|
|
228
|
+
const renameProduct = createMutation(saveProduct);
|
|
227
229
|
|
|
228
230
|
await renameProduct.mutate({
|
|
229
231
|
applicationId: 'app-1',
|
|
@@ -256,22 +258,22 @@ const syncProductData = async (variables: {
|
|
|
256
258
|
productId: string;
|
|
257
259
|
}) => variables;
|
|
258
260
|
|
|
259
|
-
const [
|
|
261
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
260
262
|
'applicationId',
|
|
261
263
|
'productId',
|
|
262
264
|
] as const);
|
|
263
265
|
|
|
264
|
-
|
|
266
|
+
createQuery(
|
|
265
267
|
['product', { deps: { applicationId: 'app-1', productId: 'product-1' }, view: { page: 1 } }],
|
|
266
268
|
() => fetchProduct('app-1', 'product-1')
|
|
267
269
|
);
|
|
268
270
|
|
|
269
|
-
|
|
271
|
+
createQuery(
|
|
270
272
|
['product', { deps: { applicationId: 'app-2', productId: 'product-1' }, view: { page: 1 } }],
|
|
271
273
|
() => fetchProduct('app-2', 'product-1')
|
|
272
274
|
);
|
|
273
275
|
|
|
274
|
-
const syncProduct =
|
|
276
|
+
const syncProduct = createMutation(syncProductData, {
|
|
275
277
|
matchMode: 'union',
|
|
276
278
|
});
|
|
277
279
|
|
|
@@ -301,12 +303,17 @@ const manager = setupQueryManager(queryClient);
|
|
|
301
303
|
|
|
302
304
|
const syncApplicationProducts = async (variables: { applicationId: string }) => variables;
|
|
303
305
|
|
|
304
|
-
const [
|
|
306
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
305
307
|
'applicationId',
|
|
306
308
|
'productId',
|
|
307
309
|
] as const);
|
|
308
310
|
|
|
309
|
-
|
|
311
|
+
createQuery(
|
|
312
|
+
['product', { deps: { applicationId: 'app-1', productId: 'product-1' }, view: { page: 1 } }],
|
|
313
|
+
async () => ({ applicationId: 'app-1', productId: 'product-1' })
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
const refreshApplicationProducts = createMutation(syncApplicationProducts);
|
|
310
317
|
|
|
311
318
|
await refreshApplicationProducts.mutate({
|
|
312
319
|
applicationId: 'app-1',
|
|
@@ -328,11 +335,16 @@ const manager = setupQueryManager(queryClient);
|
|
|
328
335
|
|
|
329
336
|
const removeProduct = async (variables: { applicationId: string }) => variables;
|
|
330
337
|
|
|
331
|
-
const [
|
|
338
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
332
339
|
'applicationId',
|
|
333
340
|
] as const);
|
|
334
341
|
|
|
335
|
-
|
|
342
|
+
createQuery(
|
|
343
|
+
['product-list', { deps: { applicationId: 'app-1' }, view: { page: 1 } }],
|
|
344
|
+
async () => [{ applicationId: 'app-1', productId: 'product-1' }]
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
const cleanupMutation = createMutation(removeProduct, {
|
|
336
348
|
invalidateOn: 'settled',
|
|
337
349
|
});
|
|
338
350
|
```
|
|
@@ -360,7 +372,7 @@ const saveProduct = async (variables: {
|
|
|
360
372
|
productName: string;
|
|
361
373
|
}) => variables;
|
|
362
374
|
|
|
363
|
-
const nestedMutation = manager.
|
|
375
|
+
const nestedMutation = manager.createMutation(saveProduct, {
|
|
364
376
|
resolveDependencies: (variables: {
|
|
365
377
|
payload: { applicationId: string };
|
|
366
378
|
product: { id: string };
|
|
@@ -381,6 +393,52 @@ Standalone tracked mutations need either:
|
|
|
381
393
|
- `dependencyKeys`
|
|
382
394
|
- or `resolveDependencies`
|
|
383
395
|
|
|
396
|
+
## FAQ
|
|
397
|
+
|
|
398
|
+
### Is `view` still part of the TanStack cache key?
|
|
399
|
+
|
|
400
|
+
Yes. TanStack uses the full query key for cache identity, so these are different cache entries:
|
|
401
|
+
|
|
402
|
+
```ts
|
|
403
|
+
['products', { deps: { applicationId: 'app-1' }, view: { page: 1 } }]
|
|
404
|
+
['products', { deps: { applicationId: 'app-1' }, view: { page: 2 } }]
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
That means `view` still matters for pagination, sorting, filtering, and any other cache variant you want TanStack to separate.
|
|
408
|
+
|
|
409
|
+
### Why does tracked invalidation ignore `view`?
|
|
410
|
+
|
|
411
|
+
Because `view` usually describes how the same domain data is presented, not what domain entity the query depends on.
|
|
412
|
+
|
|
413
|
+
If tracked invalidation matched on `view`, mutations would often miss related cache entries:
|
|
414
|
+
|
|
415
|
+
- renaming one product can change alphabetical sort order
|
|
416
|
+
- creating or deleting one product can shift pagination boundaries
|
|
417
|
+
- changing one record can affect multiple filtered views
|
|
418
|
+
|
|
419
|
+
Keeping `deps` for invalidation and `view` for cache partitioning makes that distinction explicit.
|
|
420
|
+
|
|
421
|
+
### What if I need to invalidate page 2 but not page 1?
|
|
422
|
+
|
|
423
|
+
That is a valid case, but it is intentionally not the default tracked behavior.
|
|
424
|
+
|
|
425
|
+
Use one of these options:
|
|
426
|
+
|
|
427
|
+
- call `query.invalidate()` on the exact query handle you want to refresh
|
|
428
|
+
- call `manager.invalidateQueries({ queryKey, exact: true })` with the specific key
|
|
429
|
+
- move `page` from `view` into `deps` only if page is truly part of the invalidation semantics in your domain
|
|
430
|
+
|
|
431
|
+
If page-specific invalidation is an exception, manual exact invalidation is usually the better choice.
|
|
432
|
+
|
|
433
|
+
### When is broad tracked invalidation the right tradeoff?
|
|
434
|
+
|
|
435
|
+
It is usually correct when one mutation can affect multiple views of the same domain slice:
|
|
436
|
+
|
|
437
|
+
- product creation can change counts and membership across multiple pages
|
|
438
|
+
- deletion can pull later items forward into earlier pages
|
|
439
|
+
- renaming can move items between sorted pages
|
|
440
|
+
- updates can move records in or out of filtered lists
|
|
441
|
+
|
|
384
442
|
## API
|
|
385
443
|
|
|
386
444
|
### `setupQueryManager(queryClient)`
|
|
@@ -391,9 +449,9 @@ Returns `QueryManager` with:
|
|
|
391
449
|
|
|
392
450
|
- `createQuery(queryKey, queryFn, options?)`
|
|
393
451
|
- `createMutation(mutationFn, options?)`
|
|
394
|
-
- `
|
|
395
|
-
- `
|
|
396
|
-
- `
|
|
452
|
+
- `createQueryAndMutation(dependencyKeys)`
|
|
453
|
+
- `createUntrackedQuery(queryKey, queryFn, options?)`
|
|
454
|
+
- `createUntrackedMutation(mutationFn, options?)`
|
|
397
455
|
- `cancelQueries(...)`
|
|
398
456
|
- `getQueryData(...)`
|
|
399
457
|
- `invalidateQueries(...)`
|
|
@@ -415,9 +473,9 @@ Tracked queries embed dependency metadata into the final query-key segment:
|
|
|
415
473
|
|
|
416
474
|
Only `deps` participates in automatic invalidation tracking. `view` is optional and is treated as normal query-key data.
|
|
417
475
|
|
|
418
|
-
`
|
|
476
|
+
`createQuery(queryKey, queryFn, options?)` returns the same `QueryService<TData, TError>` shape as `createUntrackedQuery(...)`, but it registers the query hash under every `deps` entry and re-registers on `refetch()` or the first `subscribe(...)` if TanStack has removed the cache entry in the meantime.
|
|
419
477
|
|
|
420
|
-
`
|
|
478
|
+
`createMutation(mutationFn, options?)` returns the same `MutationService<TData, TError, TVariables, TOnMutateResult>` shape as `createUntrackedMutation(...)`, but adds:
|
|
421
479
|
|
|
422
480
|
- `dependencyKeys?`
|
|
423
481
|
- `resolveDependencies?`
|
|
@@ -426,14 +484,14 @@ Only `deps` participates in automatic invalidation tracking. `view` is optional
|
|
|
426
484
|
|
|
427
485
|
Standalone tracked mutations need either `dependencyKeys` or `resolveDependencies`.
|
|
428
486
|
|
|
429
|
-
`
|
|
487
|
+
`createQueryAndMutation(dependencyKeys)` captures dependency keys once and returns:
|
|
430
488
|
|
|
431
|
-
- the tracked
|
|
432
|
-
- a tracked
|
|
489
|
+
- the tracked `createQuery` factory
|
|
490
|
+
- a tracked `createMutation` factory whose default resolver reads `variables[dependencyKey]`
|
|
433
491
|
|
|
434
492
|
Use `resolveDependencies` when the mutation variables do not expose the tracked dependency fields directly.
|
|
435
493
|
|
|
436
|
-
### `
|
|
494
|
+
### `createQueryAndMutation(dependencyKeys)`
|
|
437
495
|
|
|
438
496
|
Captures dependency names once and returns:
|
|
439
497
|
|
|
@@ -442,7 +500,7 @@ Captures dependency names once and returns:
|
|
|
442
500
|
|
|
443
501
|
The tracked query factory still expects a query key with a final `{ deps, view? }` segment. The tracked mutation factory keeps the same `MutationService` shape as `createMutation(...)`, but no longer needs `dependencyKeys` repeated in each call.
|
|
444
502
|
|
|
445
|
-
Reach for standalone `
|
|
503
|
+
Reach for standalone `createMutation(...)` when:
|
|
446
504
|
|
|
447
505
|
- query and mutation do not share one dependency-key list
|
|
448
506
|
- mutation variables need a custom `resolveDependencies(...)`
|
|
@@ -450,11 +508,11 @@ Reach for standalone `createTrackedMutation(...)` when:
|
|
|
450
508
|
|
|
451
509
|
### `setupQuery(queryClient)`
|
|
452
510
|
|
|
453
|
-
Creates a `
|
|
511
|
+
Creates a `createUntrackedQuery` factory bound to a `QueryClient`.
|
|
454
512
|
|
|
455
|
-
`
|
|
513
|
+
`createUntrackedQuery(queryKey, queryFn, options?)` returns `QueryService<TData, TError>`.
|
|
456
514
|
|
|
457
|
-
`QueryServiceOptions` is based on TanStack `QueryObserverOptions`, without `queryKey` and `queryFn` because those are provided directly to `
|
|
515
|
+
`QueryServiceOptions` is based on TanStack `QueryObserverOptions`, without `queryKey` and `queryFn` because those are provided directly to `createUntrackedQuery`.
|
|
458
516
|
|
|
459
517
|
`QueryService` methods:
|
|
460
518
|
|
|
@@ -485,11 +543,11 @@ Creates a `createQuery` factory bound to a `QueryClient`.
|
|
|
485
543
|
|
|
486
544
|
### `setupMutation(queryClient)`
|
|
487
545
|
|
|
488
|
-
Creates a `
|
|
546
|
+
Creates a `createUntrackedMutation` factory bound to a `QueryClient`.
|
|
489
547
|
|
|
490
|
-
`
|
|
548
|
+
`createUntrackedMutation(mutationFn, options?)` returns `MutationService<TData, TError, TVariables, TOnMutateResult>`.
|
|
491
549
|
|
|
492
|
-
`MutationServiceOptions` is based on TanStack `MutationObserverOptions`, without `mutationFn` because it is provided directly to `
|
|
550
|
+
`MutationServiceOptions` is based on TanStack `MutationObserverOptions`, without `mutationFn` because it is provided directly to `createUntrackedMutation`.
|
|
493
551
|
|
|
494
552
|
`MutationService` methods:
|
|
495
553
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from './mutation';
|
|
2
|
-
export * from './query';
|
|
3
|
-
export * from './provider';
|
|
1
|
+
export * from './mutation.js';
|
|
2
|
+
export * from './query.js';
|
|
3
|
+
export * from './provider.js';
|
|
4
4
|
export type { TrackedDependencyRecord, TrackedDependencyValue, TrackedInvalidateOn, TrackedMatchMode, TrackedQueryKey, TrackedQueryKeySegment, } from './tracking';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Re-export all mutation-related types and functions.
|
|
2
|
-
export * from './mutation';
|
|
2
|
+
export * from './mutation.js';
|
|
3
3
|
// Re-export all query-related types and functions.
|
|
4
|
-
export * from './query';
|
|
4
|
+
export * from './query.js';
|
|
5
5
|
// Re-export all provider-related types and functions for cache management.
|
|
6
|
-
export * from './provider';
|
|
6
|
+
export * from './provider.js';
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,cAAc,eAAe,CAAC;AAC9B,mDAAmD;AACnD,cAAc,YAAY,CAAC;AAC3B,2EAA2E;AAC3E,cAAc,eAAe,CAAC"}
|
package/dist/mutation.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type MutationFunction, type MutateOptions, type MutationObserverOptions, type MutationObserverResult, type MutationStatus as TanstackMutationStatus, type QueryClient } from '@tanstack/query-core';
|
|
2
|
-
import { type TrackedDependencyRecord, type TrackingRegistry, type TrackedInvalidateOn, type TrackedMatchMode } from './tracking';
|
|
2
|
+
import { type TrackedDependencyRecord, type TrackingRegistry, type TrackedInvalidateOn, type TrackedMatchMode } from './tracking.js';
|
|
3
3
|
export type MutationStatus = TanstackMutationStatus;
|
|
4
4
|
/**
|
|
5
5
|
* Represents a stable snapshot of the mutation service's state.
|
|
@@ -29,9 +29,9 @@ export interface MutationService<TData = unknown, TError = Error, TVariables = v
|
|
|
29
29
|
*/
|
|
30
30
|
export type MutationServiceOptions<TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown> = Omit<MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationFn'>;
|
|
31
31
|
/**
|
|
32
|
-
* Function signature for the mutation factory.
|
|
32
|
+
* Function signature for the untracked mutation factory.
|
|
33
33
|
*/
|
|
34
|
-
export interface
|
|
34
|
+
export interface CreateUntrackedMutation {
|
|
35
35
|
<TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown>(mutationFn: MutationFunction<TData, TVariables>, options?: MutationServiceOptions<TData, TError, TVariables, TOnMutateResult>): MutationService<TData, TError, TVariables, TOnMutateResult>;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
@@ -48,20 +48,20 @@ export interface TrackedMutationServiceOptions<TDeps extends TrackedDependencyRe
|
|
|
48
48
|
matchMode?: TrackedMatchMode;
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
* Function signature for
|
|
51
|
+
* Function signature for the default mutation factory with automatic invalidation.
|
|
52
52
|
*/
|
|
53
|
-
export interface
|
|
53
|
+
export interface CreateMutation {
|
|
54
54
|
<TDeps extends TrackedDependencyRecord = TrackedDependencyRecord, TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown>(mutationFn: MutationFunction<TData, TVariables>, options?: TrackedMutationServiceOptions<TDeps, TData, TError, TVariables, TOnMutateResult>): MutationService<TData, TError, TVariables, TOnMutateResult>;
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* Prepares the mutation factory by binding it to a specific QueryClient instance.
|
|
58
58
|
*/
|
|
59
|
-
export declare function setupMutation(queryClient: QueryClient):
|
|
59
|
+
export declare function setupMutation(queryClient: QueryClient): CreateUntrackedMutation;
|
|
60
60
|
/**
|
|
61
|
-
* Prepares
|
|
61
|
+
* Prepares the default mutation factory that coordinates invalidation through the shared registry.
|
|
62
62
|
*
|
|
63
63
|
* The implementation intentionally wraps the normal mutation service instead of re-implementing
|
|
64
64
|
* TanStack lifecycle behavior. TanStack still owns retries, callbacks, and state transitions;
|
|
65
65
|
* the facade only adds dependency resolution plus the follow-up invalidation pass.
|
|
66
66
|
*/
|
|
67
|
-
export declare function setupTrackedMutation(queryClient: QueryClient, trackingRegistry: TrackingRegistry, defaultDependencyKeys?: readonly string[]):
|
|
67
|
+
export declare function setupTrackedMutation(queryClient: QueryClient, trackingRegistry: TrackingRegistry, defaultDependencyKeys?: readonly string[]): CreateMutation;
|
package/dist/mutation.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
// Import MutationObserver to observe and manage mutations.
|
|
3
3
|
MutationObserver, } from '@tanstack/query-core';
|
|
4
|
-
import { pickTrackedDependencies, resolveTrackedQueries, toTrackedDependencyEntries, } from './tracking';
|
|
4
|
+
import { pickTrackedDependencies, resolveTrackedQueries, toTrackedDependencyEntries, } from './tracking.js';
|
|
5
5
|
/**
|
|
6
6
|
* Prepares the mutation factory by binding it to a specific QueryClient instance.
|
|
7
7
|
*/
|
|
@@ -12,14 +12,14 @@ export function setupMutation(queryClient) {
|
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Prepares
|
|
15
|
+
* Prepares the default mutation factory that coordinates invalidation through the shared registry.
|
|
16
16
|
*
|
|
17
17
|
* The implementation intentionally wraps the normal mutation service instead of re-implementing
|
|
18
18
|
* TanStack lifecycle behavior. TanStack still owns retries, callbacks, and state transitions;
|
|
19
19
|
* the facade only adds dependency resolution plus the follow-up invalidation pass.
|
|
20
20
|
*/
|
|
21
21
|
export function setupTrackedMutation(queryClient, trackingRegistry, defaultDependencyKeys) {
|
|
22
|
-
return function
|
|
22
|
+
return function createMutation(mutationFn, options) {
|
|
23
23
|
// Split tracked-only options from the underlying TanStack mutation observer options.
|
|
24
24
|
const { dependencyKeys, invalidateOn = 'success', matchMode = 'intersection', resolveDependencies, ...mutationOptions } = options ?? {};
|
|
25
25
|
// Reuse the normal mutation service so snapshots and subscription behavior stay identical.
|
package/dist/mutation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutation.js","sourceRoot":"","sources":["../src/mutation.ts"],"names":[],"mappings":"AAAA,OAAO;AACL,2DAA2D;AAC3D,gBAAgB,GAajB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAML,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,
|
|
1
|
+
{"version":3,"file":"mutation.js","sourceRoot":"","sources":["../src/mutation.ts"],"names":[],"mappings":"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"}
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { type QueryClient, type MutationFunction } from '@tanstack/query-core';
|
|
2
|
-
import { type CreateMutation, type
|
|
3
|
-
import { type CreateQuery, type
|
|
4
|
-
import { type TrackedDependencyValue } from './tracking';
|
|
2
|
+
import { type CreateMutation, type CreateUntrackedMutation, type MutationService, type TrackedMutationServiceOptions } from './mutation.js';
|
|
3
|
+
import { type CreateQuery, type CreateUntrackedQuery } from './query';
|
|
4
|
+
import { type TrackedDependencyValue } from './tracking.js';
|
|
5
5
|
/**
|
|
6
6
|
* Mutation factory returned by the paired tracked helper.
|
|
7
7
|
*
|
|
8
8
|
* This omits `dependencyKeys` on purpose because the paired helper already captured those keys
|
|
9
9
|
* once at setup time and injects them automatically for each tracked mutation it creates.
|
|
10
10
|
*/
|
|
11
|
-
export interface
|
|
11
|
+
export interface CreateMutationWithDefaults<TDependencyKey extends string> {
|
|
12
12
|
<TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown>(mutationFn: MutationFunction<TData, TVariables>, options?: Omit<TrackedMutationServiceOptions<Record<TDependencyKey, TrackedDependencyValue>, TData, TError, TVariables, TOnMutateResult>, 'dependencyKeys'>): MutationService<TData, TError, TVariables, TOnMutateResult>;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Paired tracked helper that captures dependency keys once for default mutation resolution.
|
|
16
16
|
*/
|
|
17
|
-
export interface
|
|
18
|
-
<const TDependencyKeys extends readonly string[]>(dependencyKeys: TDependencyKeys): readonly [
|
|
17
|
+
export interface CreateQueryAndMutation {
|
|
18
|
+
<const TDependencyKeys extends readonly string[]>(dependencyKeys: TDependencyKeys): readonly [CreateQuery, CreateMutationWithDefaults<TDependencyKeys[number]>];
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Defines the public API for the query manager facade.
|
|
@@ -23,9 +23,9 @@ export interface CreateTrackedQueryAndMutation {
|
|
|
23
23
|
export interface QueryManager {
|
|
24
24
|
createMutation: CreateMutation;
|
|
25
25
|
createQuery: CreateQuery;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
createUntrackedQuery: CreateUntrackedQuery;
|
|
27
|
+
createUntrackedMutation: CreateUntrackedMutation;
|
|
28
|
+
createQueryAndMutation: CreateQueryAndMutation;
|
|
29
29
|
cancelQueries: QueryClient['cancelQueries'];
|
|
30
30
|
getQueryData: QueryClient['getQueryData'];
|
|
31
31
|
invalidateQueries: QueryClient['invalidateQueries'];
|
package/dist/provider.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Import mutation and query setup functions and their factory types.
|
|
2
|
-
import { setupMutation, setupTrackedMutation, } from './mutation';
|
|
2
|
+
import { setupMutation, setupTrackedMutation, } from './mutation.js';
|
|
3
3
|
import { setupQuery, setupTrackedQuery } from './query';
|
|
4
|
-
import { createTrackingRegistry, } from './tracking';
|
|
4
|
+
import { createTrackingRegistry, } from './tracking.js';
|
|
5
5
|
/**
|
|
6
6
|
* Prepares the query manager facade by binding all actions to a specific QueryClient instance.
|
|
7
7
|
*/
|
|
@@ -9,8 +9,10 @@ export function setupQueryManager(queryClient) {
|
|
|
9
9
|
// One shared registry is the whole point of the manager-only tracked API. Queries and
|
|
10
10
|
// mutations created from the same manager can now coordinate invalidation through it.
|
|
11
11
|
const trackingRegistry = createTrackingRegistry();
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const queryFactory = setupTrackedQuery(queryClient, trackingRegistry);
|
|
13
|
+
const mutationFactory = setupTrackedMutation(queryClient, trackingRegistry);
|
|
14
|
+
const untrackedQueryFactory = setupQuery(queryClient);
|
|
15
|
+
const untrackedMutationFactory = setupMutation(queryClient);
|
|
14
16
|
queryClient.getQueryCache().subscribe((event) => {
|
|
15
17
|
if (event.type === 'removed') {
|
|
16
18
|
// When TanStack GC removes a query from the live cache, drop its hash from our registry too.
|
|
@@ -22,23 +24,23 @@ export function setupQueryManager(queryClient) {
|
|
|
22
24
|
// Return the implementation of the QueryManager interface.
|
|
23
25
|
return {
|
|
24
26
|
// Bind mutation factory to this QueryClient.
|
|
25
|
-
createMutation:
|
|
27
|
+
createMutation: mutationFactory,
|
|
26
28
|
// Bind query factory to this QueryClient.
|
|
27
|
-
createQuery:
|
|
28
|
-
// Bind
|
|
29
|
-
|
|
30
|
-
// Bind
|
|
31
|
-
|
|
29
|
+
createQuery: queryFactory,
|
|
30
|
+
// Bind untracked query factory to this QueryClient.
|
|
31
|
+
createUntrackedQuery: untrackedQueryFactory,
|
|
32
|
+
// Bind untracked mutation factory to this QueryClient.
|
|
33
|
+
createUntrackedMutation: untrackedMutationFactory,
|
|
32
34
|
// Provide a paired helper that captures dependency keys once.
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
+
createQueryAndMutation: (dependencyKeys) => {
|
|
36
|
+
const createMutationWithDefaults = (mutationFn, options) =>
|
|
35
37
|
// Inject the dependency keys once so the paired mutation factory can derive dependency
|
|
36
38
|
// values directly from mutation variables without repeating the mapping each time.
|
|
37
|
-
|
|
39
|
+
mutationFactory(mutationFn, {
|
|
38
40
|
...options,
|
|
39
41
|
dependencyKeys,
|
|
40
42
|
});
|
|
41
|
-
return [
|
|
43
|
+
return [queryFactory, createMutationWithDefaults];
|
|
42
44
|
},
|
|
43
45
|
// Proxy for canceling queries with this client context.
|
|
44
46
|
cancelQueries: queryClient.cancelQueries.bind(queryClient),
|
package/dist/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAMA,qEAAqE;AACrE,OAAO,EAKL,aAAa,EACb,oBAAoB,GACrB,MAAM,
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAMA,qEAAqE;AACrE,OAAO,EAKL,aAAa,EACb,oBAAoB,GACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAA+C,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACrG,OAAO,EACL,sBAAsB,GAEvB,MAAM,eAAe,CAAC;AAiEvB;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAwB;IACxD,sFAAsF;IACtF,sFAAsF;IACtF,MAAM,gBAAgB,GAAG,sBAAsB,EAAE,CAAC;IAClD,MAAM,YAAY,GAAG,iBAAiB,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IACtE,MAAM,eAAe,GAAG,oBAAoB,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAC5E,MAAM,qBAAqB,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,wBAAwB,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAE5D,WAAW,CAAC,aAAa,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,6FAA6F;YAC7F,4FAA4F;YAC5F,gFAAgF;YAChF,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,2DAA2D;IAC3D,OAAO;QACL,6CAA6C;QAC7C,cAAc,EAAE,eAAe;QAC/B,0CAA0C;QAC1C,WAAW,EAAE,YAAY;QACzB,oDAAoD;QACpD,oBAAoB,EAAE,qBAAqB;QAC3C,uDAAuD;QACvD,uBAAuB,EAAE,wBAAwB;QACjD,8DAA8D;QAC9D,sBAAsB,EAAE,CACtB,cAA+B,EAC/B,EAAE;YACF,MAAM,0BAA0B,GAE5B,CACF,UAA+C,EAC/C,OASC,EACD,EAAE;YACF,uFAAuF;YACvF,mFAAmF;YACnF,eAAe,CAMb,UAAU,EAAE;gBACZ,GAAG,OAAO;gBACV,cAAc;aACf,CAAC,CAAC;YAEL,OAAO,CAAC,YAAY,EAAE,0BAA0B,CAAU,CAAC;QAC7D,CAAC;QACD,wDAAwD;QACxD,aAAa,EAAE,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC;QAC1D,4DAA4D;QAC5D,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC;QACxD,2DAA2D;QAC3D,iBAAiB,EAAE,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC;QAClE,yDAAyD;QACzD,cAAc,EAAE,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC;QAC5D,uDAAuD;QACvD,aAAa,EAAE,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC;QAC1D,wDAAwD;QACxD,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC;QACxD,yDAAyD;QACzD,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC;QACxD,mDAAmD;QACnD,gBAAgB,EAAE,GAAG,EAAE,CAAC,WAAW;KACpC,CAAC;AACJ,CAAC"}
|
package/dist/query.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FetchStatus, type InvalidateOptions, type InvalidateQueryFilters, type QueryClient, type QueryFunction, type QueryKey, type QueryObserverOptions, type QueryObserverResult, type RefetchOptions, type QueryStatus as TanstackQueryStatus } from '@tanstack/query-core';
|
|
2
|
-
import { type TrackedDependencyRecord, type TrackingRegistry, type TrackedQueryKey } from './tracking';
|
|
2
|
+
import { type TrackedDependencyRecord, type TrackingRegistry, type TrackedQueryKey } from './tracking.js';
|
|
3
3
|
export type QueryFetchStatus = FetchStatus;
|
|
4
4
|
export type QueryStatus = TanstackQueryStatus;
|
|
5
5
|
/**
|
|
@@ -38,18 +38,19 @@ export interface QueryService<TData, TError> {
|
|
|
38
38
|
export interface QueryInvalidateOptions extends Pick<InvalidateOptions, 'cancelRefetch' | 'throwOnError'>, Pick<InvalidateQueryFilters, 'refetchType'> {
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* Function signature for the query factory.
|
|
41
|
+
* Function signature for the untracked query factory.
|
|
42
42
|
*/
|
|
43
|
-
export interface
|
|
43
|
+
export interface CreateUntrackedQuery {
|
|
44
44
|
<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options?: QueryServiceOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>): QueryService<TData, TError>;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* Function signature for
|
|
47
|
+
* Function signature for the default query factory that derives dependencies from the final
|
|
48
|
+
* query-key segment.
|
|
48
49
|
*
|
|
49
50
|
* The tracked query handle deliberately stays API-compatible with the normal query service.
|
|
50
51
|
* The only extra behavior is invisible: dependency registration and on-demand re-registration.
|
|
51
52
|
*/
|
|
52
|
-
export interface
|
|
53
|
+
export interface CreateQuery {
|
|
53
54
|
<TDeps extends TrackedDependencyRecord, TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends TrackedQueryKey<TDeps> = TrackedQueryKey<TDeps>>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options?: QueryServiceOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>): QueryService<TData, TError>;
|
|
54
55
|
}
|
|
55
56
|
/**
|
|
@@ -67,9 +68,9 @@ export declare function isQueryLoading(query: QueryMetaState): boolean;
|
|
|
67
68
|
/**
|
|
68
69
|
* Prepares the query factory by binding it to a specific QueryClient instance.
|
|
69
70
|
*/
|
|
70
|
-
export declare function setupQuery(queryClient: QueryClient):
|
|
71
|
+
export declare function setupQuery(queryClient: QueryClient): CreateUntrackedQuery;
|
|
71
72
|
/**
|
|
72
|
-
* Prepares
|
|
73
|
+
* Prepares the default query factory that registers and re-registers query dependencies on demand.
|
|
73
74
|
*
|
|
74
75
|
* Tracked queries register immediately on creation, but TanStack is still free to garbage-collect
|
|
75
76
|
* the underlying query when it becomes idle. When that happens, the provider-level cache
|
|
@@ -78,4 +79,4 @@ export declare function setupQuery(queryClient: QueryClient): CreateQuery;
|
|
|
78
79
|
* A later `refetch()` or first subscription can rebuild the TanStack query. That is why tracked
|
|
79
80
|
* query handles call `ensureRegistered()` before they become active again.
|
|
80
81
|
*/
|
|
81
|
-
export declare function setupTrackedQuery(queryClient: QueryClient, trackingRegistry: TrackingRegistry):
|
|
82
|
+
export declare function setupTrackedQuery(queryClient: QueryClient, trackingRegistry: TrackingRegistry): CreateQuery;
|
package/dist/query.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
// Import QueryObserver to monitor and manage individual queries.
|
|
3
3
|
QueryObserver, } from '@tanstack/query-core';
|
|
4
|
-
import { extractTrackedDependencies, } from './tracking';
|
|
4
|
+
import { extractTrackedDependencies, } from './tracking.js';
|
|
5
5
|
/**
|
|
6
6
|
* Extracts and maps status and fetchStatus to our QueryMetaState interface.
|
|
7
7
|
*/
|
|
@@ -29,7 +29,7 @@ export function setupQuery(queryClient) {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
|
-
* Prepares
|
|
32
|
+
* Prepares the default query factory that registers and re-registers query dependencies on demand.
|
|
33
33
|
*
|
|
34
34
|
* Tracked queries register immediately on creation, but TanStack is still free to garbage-collect
|
|
35
35
|
* the underlying query when it becomes idle. When that happens, the provider-level cache
|
|
@@ -39,7 +39,7 @@ export function setupQuery(queryClient) {
|
|
|
39
39
|
* query handles call `ensureRegistered()` before they become active again.
|
|
40
40
|
*/
|
|
41
41
|
export function setupTrackedQuery(queryClient, trackingRegistry) {
|
|
42
|
-
return function
|
|
42
|
+
return function createQuery(queryKey, queryFn, options) {
|
|
43
43
|
// Validate and normalize the dependency entries once when the handle is created.
|
|
44
44
|
const dependencies = extractTrackedDependencies(queryKey);
|
|
45
45
|
// Reuse the same core query service implementation as the untracked API.
|
package/dist/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO;AAaL,iEAAiE;AACjE,aAAa,GAUd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAIL,0BAA0B,GAC3B,MAAM,
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -9,12 +9,12 @@ describe('Tracked Query Invalidation', () => {
|
|
|
9
9
|
});
|
|
10
10
|
const manager = setupQueryManager(queryClient);
|
|
11
11
|
const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries');
|
|
12
|
-
const [
|
|
12
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
13
13
|
'applicationId',
|
|
14
14
|
'productId',
|
|
15
15
|
] as const);
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
createQuery(
|
|
18
18
|
[
|
|
19
19
|
'product',
|
|
20
20
|
{
|
|
@@ -26,7 +26,7 @@ describe('Tracked Query Invalidation', () => {
|
|
|
26
26
|
{ enabled: false }
|
|
27
27
|
);
|
|
28
28
|
|
|
29
|
-
const mutation =
|
|
29
|
+
const mutation = createMutation(jest.fn().mockResolvedValue({ ok: true as const }));
|
|
30
30
|
|
|
31
31
|
await mutation.mutate({
|
|
32
32
|
applicationId: 'app-1',
|
|
@@ -50,7 +50,7 @@ describe('Tracked Query Invalidation', () => {
|
|
|
50
50
|
const manager = setupQueryManager(new QueryClient());
|
|
51
51
|
|
|
52
52
|
expect(() =>
|
|
53
|
-
manager.
|
|
53
|
+
manager.createQuery(
|
|
54
54
|
['invalid', { view: { page: 1 } }] as never,
|
|
55
55
|
jest.fn().mockResolvedValue('nope')
|
|
56
56
|
)
|
|
@@ -63,23 +63,23 @@ describe('Tracked Query Invalidation', () => {
|
|
|
63
63
|
});
|
|
64
64
|
const manager = setupQueryManager(queryClient);
|
|
65
65
|
const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries');
|
|
66
|
-
const [
|
|
66
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
67
67
|
'applicationId',
|
|
68
68
|
'productId',
|
|
69
69
|
] as const);
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
createQuery(
|
|
72
72
|
['product', { deps: { applicationId: 'app-1', productId: 'product-1' }, view: { page: 1 } }],
|
|
73
73
|
jest.fn().mockResolvedValue('page-1'),
|
|
74
74
|
{ enabled: false }
|
|
75
75
|
);
|
|
76
|
-
|
|
76
|
+
createQuery(
|
|
77
77
|
['product', { deps: { applicationId: 'app-1', productId: 'product-2' }, view: { page: 2 } }],
|
|
78
78
|
jest.fn().mockResolvedValue('page-2'),
|
|
79
79
|
{ enabled: false }
|
|
80
80
|
);
|
|
81
81
|
|
|
82
|
-
const mutation =
|
|
82
|
+
const mutation = createMutation(jest.fn().mockResolvedValue({ ok: true as const }));
|
|
83
83
|
|
|
84
84
|
await mutation.mutate({ applicationId: 'app-1', productName: 'Shared update' });
|
|
85
85
|
|
|
@@ -92,28 +92,28 @@ describe('Tracked Query Invalidation', () => {
|
|
|
92
92
|
});
|
|
93
93
|
const manager = setupQueryManager(queryClient);
|
|
94
94
|
const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries');
|
|
95
|
-
const [
|
|
95
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
96
96
|
'applicationId',
|
|
97
97
|
'productId',
|
|
98
98
|
] as const);
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
createQuery(
|
|
101
101
|
['product', { deps: { applicationId: 'app-1', productId: 'product-1' }, view: { page: 1 } }],
|
|
102
102
|
jest.fn().mockResolvedValue('product-1'),
|
|
103
103
|
{ enabled: false }
|
|
104
104
|
);
|
|
105
|
-
|
|
105
|
+
createQuery(
|
|
106
106
|
['product', { deps: { applicationId: 'app-1', productId: 'product-2' }, view: { page: 2 } }],
|
|
107
107
|
jest.fn().mockResolvedValue('product-2'),
|
|
108
108
|
{ enabled: false }
|
|
109
109
|
);
|
|
110
|
-
|
|
110
|
+
createQuery(
|
|
111
111
|
['product', { deps: { applicationId: 'app-2', productId: 'product-1' }, view: { page: 3 } }],
|
|
112
112
|
jest.fn().mockResolvedValue('product-3'),
|
|
113
113
|
{ enabled: false }
|
|
114
114
|
);
|
|
115
115
|
|
|
116
|
-
const mutation =
|
|
116
|
+
const mutation = createMutation(jest.fn().mockResolvedValue({ ok: true as const }), {
|
|
117
117
|
matchMode: 'union',
|
|
118
118
|
});
|
|
119
119
|
|
|
@@ -129,13 +129,13 @@ describe('Tracked Query Invalidation', () => {
|
|
|
129
129
|
const manager = setupQueryManager(queryClient);
|
|
130
130
|
const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries');
|
|
131
131
|
|
|
132
|
-
manager.
|
|
132
|
+
manager.createQuery(
|
|
133
133
|
['product', { deps: { applicationId: 'app-1', productId: 'product-1' }, view: { page: 1 } }],
|
|
134
134
|
jest.fn().mockResolvedValue('product'),
|
|
135
135
|
{ enabled: false }
|
|
136
136
|
);
|
|
137
137
|
|
|
138
|
-
const mutation = manager.
|
|
138
|
+
const mutation = manager.createMutation(
|
|
139
139
|
jest.fn().mockResolvedValue({ ok: true as const }),
|
|
140
140
|
{
|
|
141
141
|
resolveDependencies: (variables: {
|
|
@@ -162,20 +162,20 @@ describe('Tracked Query Invalidation', () => {
|
|
|
162
162
|
});
|
|
163
163
|
const manager = setupQueryManager(queryClient);
|
|
164
164
|
const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries');
|
|
165
|
-
const [
|
|
165
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
166
166
|
'applicationId',
|
|
167
167
|
] as const);
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
createQuery(
|
|
170
170
|
['product', { deps: { applicationId: 'app-1' }, view: { page: 1 } }],
|
|
171
171
|
jest.fn().mockResolvedValue('product'),
|
|
172
172
|
{ enabled: false }
|
|
173
173
|
);
|
|
174
174
|
|
|
175
|
-
const invalidateOnError =
|
|
175
|
+
const invalidateOnError = createMutation(jest.fn().mockRejectedValue(new Error('boom')), {
|
|
176
176
|
invalidateOn: 'error',
|
|
177
177
|
});
|
|
178
|
-
const invalidateOnSettled =
|
|
178
|
+
const invalidateOnSettled = createMutation(
|
|
179
179
|
jest.fn().mockRejectedValue(new Error('boom again')),
|
|
180
180
|
{
|
|
181
181
|
invalidateOn: 'settled',
|
|
@@ -196,7 +196,7 @@ describe('Tracked Query Invalidation', () => {
|
|
|
196
196
|
});
|
|
197
197
|
const manager = setupQueryManager(queryClient);
|
|
198
198
|
const cacheGetSpy = jest.spyOn(queryClient.getQueryCache(), 'get');
|
|
199
|
-
const [
|
|
199
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
200
200
|
'applicationId',
|
|
201
201
|
] as const);
|
|
202
202
|
|
|
@@ -205,19 +205,19 @@ describe('Tracked Query Invalidation', () => {
|
|
|
205
205
|
{ deps: { applicationId: 'app-1' }, view: { page: 1 } },
|
|
206
206
|
] as const;
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
createQuery(removedQueryKey, jest.fn().mockResolvedValue('page-1'), {
|
|
209
209
|
enabled: false,
|
|
210
210
|
});
|
|
211
211
|
queryClient.removeQueries({ exact: true, queryKey: removedQueryKey });
|
|
212
212
|
|
|
213
|
-
|
|
213
|
+
createQuery(
|
|
214
214
|
['product', { deps: { applicationId: 'app-1' }, view: { page: 2 } }],
|
|
215
215
|
jest.fn().mockResolvedValue('page-2'),
|
|
216
216
|
{ enabled: false }
|
|
217
217
|
);
|
|
218
218
|
cacheGetSpy.mockClear();
|
|
219
219
|
|
|
220
|
-
const mutation =
|
|
220
|
+
const mutation = createMutation(jest.fn().mockResolvedValue({ ok: true as const }));
|
|
221
221
|
|
|
222
222
|
await mutation.mutate({ applicationId: 'app-1' });
|
|
223
223
|
|
|
@@ -230,14 +230,14 @@ describe('Tracked Query Invalidation', () => {
|
|
|
230
230
|
});
|
|
231
231
|
const manager = setupQueryManager(queryClient);
|
|
232
232
|
const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries');
|
|
233
|
-
const [
|
|
233
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
234
234
|
'applicationId',
|
|
235
235
|
] as const);
|
|
236
236
|
const queryKey = ['product', { deps: { applicationId: 'app-1' }, view: { page: 1 } }] as const;
|
|
237
|
-
const query =
|
|
237
|
+
const query = createQuery(queryKey, jest.fn().mockResolvedValue('product'), {
|
|
238
238
|
enabled: false,
|
|
239
239
|
});
|
|
240
|
-
const mutation =
|
|
240
|
+
const mutation = createMutation(jest.fn().mockResolvedValue({ ok: true as const }));
|
|
241
241
|
|
|
242
242
|
queryClient.removeQueries({ exact: true, queryKey });
|
|
243
243
|
|
|
@@ -256,14 +256,14 @@ describe('Tracked Query Invalidation', () => {
|
|
|
256
256
|
});
|
|
257
257
|
const manager = setupQueryManager(queryClient);
|
|
258
258
|
const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries');
|
|
259
|
-
const [
|
|
259
|
+
const [createQuery, createMutation] = manager.createQueryAndMutation([
|
|
260
260
|
'applicationId',
|
|
261
261
|
] as const);
|
|
262
262
|
const queryKey = ['product', { deps: { applicationId: 'app-1' }, view: { page: 1 } }] as const;
|
|
263
|
-
const query =
|
|
263
|
+
const query = createQuery(queryKey, jest.fn().mockResolvedValue('product'), {
|
|
264
264
|
enabled: false,
|
|
265
265
|
});
|
|
266
|
-
const mutation =
|
|
266
|
+
const mutation = createMutation(jest.fn().mockResolvedValue({ ok: true as const }));
|
|
267
267
|
|
|
268
268
|
queryClient.removeQueries({ exact: true, queryKey });
|
|
269
269
|
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Re-export all mutation-related types and functions.
|
|
2
|
-
export * from './mutation';
|
|
2
|
+
export * from './mutation.js';
|
|
3
3
|
// Re-export all query-related types and functions.
|
|
4
|
-
export * from './query';
|
|
4
|
+
export * from './query.js';
|
|
5
5
|
// Re-export all provider-related types and functions for cache management.
|
|
6
|
-
export * from './provider';
|
|
6
|
+
export * from './provider.js';
|
|
7
7
|
// Re-export tracked dependency types used by the additive tracked facade.
|
|
8
8
|
export type {
|
|
9
9
|
TrackedDependencyRecord,
|
package/src/mutation.ts
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
pickTrackedDependencies,
|
|
25
25
|
resolveTrackedQueries,
|
|
26
26
|
toTrackedDependencyEntries,
|
|
27
|
-
} from './tracking';
|
|
27
|
+
} from './tracking.js';
|
|
28
28
|
|
|
29
29
|
// Re-export MutationStatus for consistent naming within the service.
|
|
30
30
|
export type MutationStatus = TanstackMutationStatus;
|
|
@@ -88,9 +88,9 @@ export type MutationServiceOptions<
|
|
|
88
88
|
> = Omit<MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationFn'>;
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
|
-
* Function signature for the mutation factory.
|
|
91
|
+
* Function signature for the untracked mutation factory.
|
|
92
92
|
*/
|
|
93
|
-
export interface
|
|
93
|
+
export interface CreateUntrackedMutation {
|
|
94
94
|
<TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown>(
|
|
95
95
|
// The asynchronous function that performs the mutation.
|
|
96
96
|
mutationFn: MutationFunction<TData, TVariables>,
|
|
@@ -124,9 +124,9 @@ export interface TrackedMutationServiceOptions<
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/**
|
|
127
|
-
* Function signature for
|
|
127
|
+
* Function signature for the default mutation factory with automatic invalidation.
|
|
128
128
|
*/
|
|
129
|
-
export interface
|
|
129
|
+
export interface CreateMutation {
|
|
130
130
|
<
|
|
131
131
|
TDeps extends TrackedDependencyRecord = TrackedDependencyRecord,
|
|
132
132
|
TData = unknown,
|
|
@@ -142,7 +142,7 @@ export interface CreateTrackedMutation {
|
|
|
142
142
|
/**
|
|
143
143
|
* Prepares the mutation factory by binding it to a specific QueryClient instance.
|
|
144
144
|
*/
|
|
145
|
-
export function setupMutation(queryClient: QueryClient):
|
|
145
|
+
export function setupMutation(queryClient: QueryClient): CreateUntrackedMutation {
|
|
146
146
|
// Returns the actual factory function for creating individual mutation services.
|
|
147
147
|
return function createMutation<
|
|
148
148
|
TData = unknown,
|
|
@@ -158,7 +158,7 @@ export function setupMutation(queryClient: QueryClient): CreateMutation {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
/**
|
|
161
|
-
* Prepares
|
|
161
|
+
* Prepares the default mutation factory that coordinates invalidation through the shared registry.
|
|
162
162
|
*
|
|
163
163
|
* The implementation intentionally wraps the normal mutation service instead of re-implementing
|
|
164
164
|
* TanStack lifecycle behavior. TanStack still owns retries, callbacks, and state transitions;
|
|
@@ -168,8 +168,8 @@ export function setupTrackedMutation(
|
|
|
168
168
|
queryClient: QueryClient,
|
|
169
169
|
trackingRegistry: TrackingRegistry,
|
|
170
170
|
defaultDependencyKeys?: readonly string[]
|
|
171
|
-
):
|
|
172
|
-
return function
|
|
171
|
+
): CreateMutation {
|
|
172
|
+
return function createMutation<
|
|
173
173
|
TDeps extends TrackedDependencyRecord = TrackedDependencyRecord,
|
|
174
174
|
TData = unknown,
|
|
175
175
|
TError = Error,
|
package/src/provider.ts
CHANGED
|
@@ -7,17 +7,17 @@ import {
|
|
|
7
7
|
// Import mutation and query setup functions and their factory types.
|
|
8
8
|
import {
|
|
9
9
|
type CreateMutation,
|
|
10
|
-
type
|
|
10
|
+
type CreateUntrackedMutation,
|
|
11
11
|
type MutationService,
|
|
12
12
|
type TrackedMutationServiceOptions,
|
|
13
13
|
setupMutation,
|
|
14
14
|
setupTrackedMutation,
|
|
15
|
-
} from './mutation';
|
|
16
|
-
import { type CreateQuery, type
|
|
15
|
+
} from './mutation.js';
|
|
16
|
+
import { type CreateQuery, type CreateUntrackedQuery, setupQuery, setupTrackedQuery } from './query';
|
|
17
17
|
import {
|
|
18
18
|
createTrackingRegistry,
|
|
19
19
|
type TrackedDependencyValue,
|
|
20
|
-
} from './tracking';
|
|
20
|
+
} from './tracking.js';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Mutation factory returned by the paired tracked helper.
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
* This omits `dependencyKeys` on purpose because the paired helper already captured those keys
|
|
26
26
|
* once at setup time and injects them automatically for each tracked mutation it creates.
|
|
27
27
|
*/
|
|
28
|
-
export interface
|
|
28
|
+
export interface CreateMutationWithDefaults<TDependencyKey extends string> {
|
|
29
29
|
<TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown>(
|
|
30
30
|
mutationFn: MutationFunction<TData, TVariables>,
|
|
31
31
|
options?: Omit<
|
|
@@ -44,26 +44,26 @@ export interface CreateTrackedMutationWithDefaults<TDependencyKey extends string
|
|
|
44
44
|
/**
|
|
45
45
|
* Paired tracked helper that captures dependency keys once for default mutation resolution.
|
|
46
46
|
*/
|
|
47
|
-
export interface
|
|
47
|
+
export interface CreateQueryAndMutation {
|
|
48
48
|
<const TDependencyKeys extends readonly string[]>(
|
|
49
49
|
dependencyKeys: TDependencyKeys
|
|
50
|
-
): readonly [
|
|
50
|
+
): readonly [CreateQuery, CreateMutationWithDefaults<TDependencyKeys[number]>];
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Defines the public API for the query manager facade.
|
|
55
55
|
*/
|
|
56
56
|
export interface QueryManager {
|
|
57
|
-
// Factory for creating a mutation service within the context of this provider.
|
|
57
|
+
// Factory for creating a dependency-tracked mutation service within the context of this provider.
|
|
58
58
|
createMutation: CreateMutation;
|
|
59
|
-
// Factory for creating a query service within the context of this provider.
|
|
59
|
+
// Factory for creating a dependency-tracked query service within the context of this provider.
|
|
60
60
|
createQuery: CreateQuery;
|
|
61
|
-
// Factory for creating
|
|
62
|
-
|
|
63
|
-
// Factory for creating
|
|
64
|
-
|
|
61
|
+
// Factory for creating an untracked query service within the context of this provider.
|
|
62
|
+
createUntrackedQuery: CreateUntrackedQuery;
|
|
63
|
+
// Factory for creating an untracked mutation service within the context of this provider.
|
|
64
|
+
createUntrackedMutation: CreateUntrackedMutation;
|
|
65
65
|
// Convenience helper that shares dependency keys between tracked queries and mutations.
|
|
66
|
-
|
|
66
|
+
createQueryAndMutation: CreateQueryAndMutation;
|
|
67
67
|
// Cancels active queries for the specified filters.
|
|
68
68
|
cancelQueries: QueryClient['cancelQueries'];
|
|
69
69
|
// Synchronously retrieves a snapshot of the current query data.
|
|
@@ -89,8 +89,10 @@ export function setupQueryManager(queryClient: QueryClient): QueryManager {
|
|
|
89
89
|
// One shared registry is the whole point of the manager-only tracked API. Queries and
|
|
90
90
|
// mutations created from the same manager can now coordinate invalidation through it.
|
|
91
91
|
const trackingRegistry = createTrackingRegistry();
|
|
92
|
-
const
|
|
93
|
-
const
|
|
92
|
+
const queryFactory = setupTrackedQuery(queryClient, trackingRegistry);
|
|
93
|
+
const mutationFactory = setupTrackedMutation(queryClient, trackingRegistry);
|
|
94
|
+
const untrackedQueryFactory = setupQuery(queryClient);
|
|
95
|
+
const untrackedMutationFactory = setupMutation(queryClient);
|
|
94
96
|
|
|
95
97
|
queryClient.getQueryCache().subscribe((event) => {
|
|
96
98
|
if (event.type === 'removed') {
|
|
@@ -104,18 +106,18 @@ export function setupQueryManager(queryClient: QueryClient): QueryManager {
|
|
|
104
106
|
// Return the implementation of the QueryManager interface.
|
|
105
107
|
return {
|
|
106
108
|
// Bind mutation factory to this QueryClient.
|
|
107
|
-
createMutation:
|
|
109
|
+
createMutation: mutationFactory,
|
|
108
110
|
// Bind query factory to this QueryClient.
|
|
109
|
-
createQuery:
|
|
110
|
-
// Bind
|
|
111
|
-
|
|
112
|
-
// Bind
|
|
113
|
-
|
|
111
|
+
createQuery: queryFactory,
|
|
112
|
+
// Bind untracked query factory to this QueryClient.
|
|
113
|
+
createUntrackedQuery: untrackedQueryFactory,
|
|
114
|
+
// Bind untracked mutation factory to this QueryClient.
|
|
115
|
+
createUntrackedMutation: untrackedMutationFactory,
|
|
114
116
|
// Provide a paired helper that captures dependency keys once.
|
|
115
|
-
|
|
117
|
+
createQueryAndMutation: <const TDependencyKeys extends readonly string[]>(
|
|
116
118
|
dependencyKeys: TDependencyKeys
|
|
117
119
|
) => {
|
|
118
|
-
const
|
|
120
|
+
const createMutationWithDefaults: CreateMutationWithDefaults<
|
|
119
121
|
TDependencyKeys[number]
|
|
120
122
|
> = <TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown>(
|
|
121
123
|
mutationFn: MutationFunction<TData, TVariables>,
|
|
@@ -132,7 +134,7 @@ export function setupQueryManager(queryClient: QueryClient): QueryManager {
|
|
|
132
134
|
) =>
|
|
133
135
|
// Inject the dependency keys once so the paired mutation factory can derive dependency
|
|
134
136
|
// values directly from mutation variables without repeating the mapping each time.
|
|
135
|
-
|
|
137
|
+
mutationFactory<
|
|
136
138
|
Record<TDependencyKeys[number], TrackedDependencyValue>,
|
|
137
139
|
TData,
|
|
138
140
|
TError,
|
|
@@ -143,7 +145,7 @@ export function setupQueryManager(queryClient: QueryClient): QueryManager {
|
|
|
143
145
|
dependencyKeys,
|
|
144
146
|
});
|
|
145
147
|
|
|
146
|
-
return [
|
|
148
|
+
return [queryFactory, createMutationWithDefaults] as const;
|
|
147
149
|
},
|
|
148
150
|
// Proxy for canceling queries with this client context.
|
|
149
151
|
cancelQueries: queryClient.cancelQueries.bind(queryClient),
|
package/src/query.ts
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
type TrackingRegistry,
|
|
30
30
|
type TrackedQueryKey,
|
|
31
31
|
extractTrackedDependencies,
|
|
32
|
-
} from './tracking';
|
|
32
|
+
} from './tracking.js';
|
|
33
33
|
|
|
34
34
|
// Re-export FetchStatus and QueryStatus for internal naming consistency.
|
|
35
35
|
export type QueryFetchStatus = FetchStatus;
|
|
@@ -89,9 +89,9 @@ export interface QueryInvalidateOptions
|
|
|
89
89
|
Pick<InvalidateQueryFilters, 'refetchType'> {}
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
* Function signature for the query factory.
|
|
92
|
+
* Function signature for the untracked query factory.
|
|
93
93
|
*/
|
|
94
|
-
export interface
|
|
94
|
+
export interface CreateUntrackedQuery {
|
|
95
95
|
<
|
|
96
96
|
TQueryFnData = unknown,
|
|
97
97
|
TError = Error,
|
|
@@ -109,12 +109,13 @@ export interface CreateQuery {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
|
-
* Function signature for
|
|
112
|
+
* Function signature for the default query factory that derives dependencies from the final
|
|
113
|
+
* query-key segment.
|
|
113
114
|
*
|
|
114
115
|
* The tracked query handle deliberately stays API-compatible with the normal query service.
|
|
115
116
|
* The only extra behavior is invisible: dependency registration and on-demand re-registration.
|
|
116
117
|
*/
|
|
117
|
-
export interface
|
|
118
|
+
export interface CreateQuery {
|
|
118
119
|
<
|
|
119
120
|
TDeps extends TrackedDependencyRecord,
|
|
120
121
|
TQueryFnData = unknown,
|
|
@@ -167,7 +168,7 @@ export function isQueryLoading(query: QueryMetaState): boolean {
|
|
|
167
168
|
/**
|
|
168
169
|
* Prepares the query factory by binding it to a specific QueryClient instance.
|
|
169
170
|
*/
|
|
170
|
-
export function setupQuery(queryClient: QueryClient):
|
|
171
|
+
export function setupQuery(queryClient: QueryClient): CreateUntrackedQuery {
|
|
171
172
|
// Returns the actual factory function for creating individual query services.
|
|
172
173
|
return function createQuery<
|
|
173
174
|
TQueryFnData = unknown,
|
|
@@ -185,7 +186,7 @@ export function setupQuery(queryClient: QueryClient): CreateQuery {
|
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
/**
|
|
188
|
-
* Prepares
|
|
189
|
+
* Prepares the default query factory that registers and re-registers query dependencies on demand.
|
|
189
190
|
*
|
|
190
191
|
* Tracked queries register immediately on creation, but TanStack is still free to garbage-collect
|
|
191
192
|
* the underlying query when it becomes idle. When that happens, the provider-level cache
|
|
@@ -197,8 +198,8 @@ export function setupQuery(queryClient: QueryClient): CreateQuery {
|
|
|
197
198
|
export function setupTrackedQuery(
|
|
198
199
|
queryClient: QueryClient,
|
|
199
200
|
trackingRegistry: TrackingRegistry
|
|
200
|
-
):
|
|
201
|
-
return function
|
|
201
|
+
): CreateQuery {
|
|
202
|
+
return function createQuery<
|
|
202
203
|
TDeps extends TrackedDependencyRecord,
|
|
203
204
|
TQueryFnData = unknown,
|
|
204
205
|
TError = Error,
|