@ttt-productions/query-core 0.14.3 → 0.14.4
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/dist/domain-events/cache-invalidation.d.ts +12 -4
- package/dist/domain-events/cache-invalidation.d.ts.map +1 -1
- package/dist/domain-events/cache-invalidation.js +14 -4
- package/dist/domain-events/cache-invalidation.js.map +1 -1
- package/dist/domain-events/create-domain-event-invalidator.d.ts +9 -2
- package/dist/domain-events/create-domain-event-invalidator.d.ts.map +1 -1
- package/dist/domain-events/create-domain-event-invalidator.js +2 -2
- package/dist/domain-events/create-domain-event-invalidator.js.map +1 -1
- package/package.json +1 -1
|
@@ -27,9 +27,17 @@ export declare function serializeInvalidation(inv: CacheInvalidation): string;
|
|
|
27
27
|
/**
|
|
28
28
|
* Dispatch a deduplicated list of cache invalidations.
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* Returns a promise that resolves once every `invalidateQueries` call it issued
|
|
31
|
+
* has settled — i.e. once the refetches those invalidations triggered have
|
|
32
|
+
* landed. The dispatch itself stays synchronous (every cancellation and
|
|
33
|
+
* invalidation is issued before this function returns), so a fire-and-forget
|
|
34
|
+
* caller keeps the prior behavior exactly, while a mutation `onSuccess` that
|
|
35
|
+
* RETURNS or awaits the promise stays pending until the refreshed data is in
|
|
36
|
+
* the cache. The promise never rejects: `invalidateQueries` refetches without
|
|
37
|
+
* `throwOnError`, so a failed refetch surfaces on its own query, never as a
|
|
38
|
+
* failure of the committed action that triggered it. The scoped
|
|
39
|
+
* `cancelQueries` calls stay fire-and-forget — cancellation takes effect
|
|
40
|
+
* synchronously and is not part of the refresh being awaited.
|
|
33
41
|
*
|
|
34
42
|
* Before each invalidation, any query it matches that is mid-PENDING-INITIAL-READ
|
|
35
43
|
* is cancelled (see `cancelPendingInitialReads`) so a read that started before
|
|
@@ -45,5 +53,5 @@ export declare function serializeInvalidation(inv: CacheInvalidation): string;
|
|
|
45
53
|
* refetch at all, so cancelling would abandon the only in-flight read the
|
|
46
54
|
* consumer has and leave it with no data and no pending request.
|
|
47
55
|
*/
|
|
48
|
-
export declare function applyInvalidations(queryClient: QueryClient, invalidations: ReadonlyArray<CacheInvalidation>): void
|
|
56
|
+
export declare function applyInvalidations(queryClient: QueryClient, invalidations: ReadonlyArray<CacheInvalidation>): Promise<void>;
|
|
49
57
|
//# sourceMappingURL=cache-invalidation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-invalidation.d.ts","sourceRoot":"","sources":["../../src/domain-events/cache-invalidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAgB,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAExF,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEpD,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GACjE;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;IACjC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEN,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG,iBAAiB,CAEjG;AAED,wBAAgB,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG,iBAAiB,CAElG;AAED,wBAAgB,SAAS,CACvB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,EAChC,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GACnC,iBAAiB,CAEnB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAGpE;AAiCD
|
|
1
|
+
{"version":3,"file":"cache-invalidation.d.ts","sourceRoot":"","sources":["../../src/domain-events/cache-invalidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAgB,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAExF,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEpD,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GACjE;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;IACjC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEN,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG,iBAAiB,CAEjG;AAED,wBAAgB,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG,iBAAiB,CAElG;AAED,wBAAgB,SAAS,CACvB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,EAChC,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,GACnC,iBAAiB,CAEnB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAGpE;AAiCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAC9C,OAAO,CAAC,IAAI,CAAC,CAkBf"}
|
|
@@ -48,9 +48,17 @@ function cancelPendingInitialReads(queryClient, filters) {
|
|
|
48
48
|
/**
|
|
49
49
|
* Dispatch a deduplicated list of cache invalidations.
|
|
50
50
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
51
|
+
* Returns a promise that resolves once every `invalidateQueries` call it issued
|
|
52
|
+
* has settled — i.e. once the refetches those invalidations triggered have
|
|
53
|
+
* landed. The dispatch itself stays synchronous (every cancellation and
|
|
54
|
+
* invalidation is issued before this function returns), so a fire-and-forget
|
|
55
|
+
* caller keeps the prior behavior exactly, while a mutation `onSuccess` that
|
|
56
|
+
* RETURNS or awaits the promise stays pending until the refreshed data is in
|
|
57
|
+
* the cache. The promise never rejects: `invalidateQueries` refetches without
|
|
58
|
+
* `throwOnError`, so a failed refetch surfaces on its own query, never as a
|
|
59
|
+
* failure of the committed action that triggered it. The scoped
|
|
60
|
+
* `cancelQueries` calls stay fire-and-forget — cancellation takes effect
|
|
61
|
+
* synchronously and is not part of the refresh being awaited.
|
|
54
62
|
*
|
|
55
63
|
* Before each invalidation, any query it matches that is mid-PENDING-INITIAL-READ
|
|
56
64
|
* is cancelled (see `cancelPendingInitialReads`) so a read that started before
|
|
@@ -68,6 +76,7 @@ function cancelPendingInitialReads(queryClient, filters) {
|
|
|
68
76
|
*/
|
|
69
77
|
export function applyInvalidations(queryClient, invalidations) {
|
|
70
78
|
const seen = new Set();
|
|
79
|
+
const refreshes = [];
|
|
71
80
|
for (const inv of invalidations) {
|
|
72
81
|
const sig = serializeInvalidation(inv);
|
|
73
82
|
if (seen.has(sig))
|
|
@@ -78,7 +87,8 @@ export function applyInvalidations(queryClient, invalidations) {
|
|
|
78
87
|
if (refetchType !== "none") {
|
|
79
88
|
cancelPendingInitialReads(queryClient, filters);
|
|
80
89
|
}
|
|
81
|
-
|
|
90
|
+
refreshes.push(queryClient.invalidateQueries({ ...filters, refetchType }));
|
|
82
91
|
}
|
|
92
|
+
return Promise.all(refreshes).then(() => undefined);
|
|
83
93
|
}
|
|
84
94
|
//# sourceMappingURL=cache-invalidation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-invalidation.js","sourceRoot":"","sources":["../../src/domain-events/cache-invalidation.ts"],"names":[],"mappings":"AAcA,MAAM,UAAU,KAAK,CAAC,QAAkB,EAAE,IAAoC;IAC5E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,QAAkB,EAAE,IAAoC;IAC7E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,WAAmB,EACnB,KAAgC,EAChC,IAAoC;IAEpC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAsB;IAC1D,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,aAAa,GAAG,CAAC,WAAW,EAAE,CAAC;IACpE,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;AACvD,CAAC;AAED,kFAAkF;AAClF,SAAS,mBAAmB,CAAC,GAAsB;IACjD,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzE,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC3E,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAS,yBAAyB,CAAC,WAAwB,EAAE,OAAqB;IAChF,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACjE,IAAI,KAAK,CAAC,KAAK,CAAC,WAAW,KAAK,UAAU;YAAE,SAAS;QACrD,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QAC7C,KAAK,WAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"cache-invalidation.js","sourceRoot":"","sources":["../../src/domain-events/cache-invalidation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Query, QueryClient, QueryFilters, QueryKey } from \"@tanstack/react-query\";\n\nexport type RefetchType = \"active\" | \"all\" | \"none\";\n\nexport type CacheInvalidation =\n | { kind: \"exact\"; queryKey: QueryKey; refetchType?: RefetchType }\n | { kind: \"prefix\"; queryKey: QueryKey; refetchType?: RefetchType }\n | {\n kind: \"predicate\";\n description: string;\n match: (query: Query) => boolean;\n refetchType?: RefetchType;\n };\n\nexport function exact(queryKey: QueryKey, opts?: { refetchType?: RefetchType }): CacheInvalidation {\n return { kind: \"exact\", queryKey, refetchType: opts?.refetchType };\n}\n\nexport function prefix(queryKey: QueryKey, opts?: { refetchType?: RefetchType }): CacheInvalidation {\n return { kind: \"prefix\", queryKey, refetchType: opts?.refetchType };\n}\n\nexport function predicate(\n description: string,\n match: (query: Query) => boolean,\n opts?: { refetchType?: RefetchType },\n): CacheInvalidation {\n return { kind: \"predicate\", description, match, refetchType: opts?.refetchType };\n}\n\nexport function serializeInvalidation(inv: CacheInvalidation): string {\n if (inv.kind === \"predicate\") return `predicate:${inv.description}`;\n return `${inv.kind}:${JSON.stringify(inv.queryKey)}`;\n}\n\n/** The cache filter that selects exactly the queries one invalidation targets. */\nfunction invalidationFilters(inv: CacheInvalidation): QueryFilters {\n if (inv.kind === \"exact\") return { queryKey: inv.queryKey, exact: true };\n if (inv.kind === \"prefix\") return { queryKey: inv.queryKey, exact: false };\n return { predicate: inv.match };\n}\n\n/**\n * Cancel every query matched by `filters` that is in a PENDING INITIAL READ —\n * currently fetching with no data yet.\n *\n * TanStack's `Query.fetch` only cancels a running request on refetch when the\n * query already holds data; an initial fetch in flight is REUSED instead, so\n * the invalidation's refetch resolves with the value the server returned BEFORE\n * the mutation committed and then marks the query fresh. Cancelling first makes\n * the invalidation's refetch a genuinely new request: the retryer is rejected\n * synchronously (its `onCancel` reverts state to idle in the same tick), so the\n * `invalidateQueries` call that follows starts a fresh fetch, and the abandoned\n * promise's late, stale resolution is discarded.\n *\n * Cancellation is always scoped to one concrete query key — never a bare\n * `cancelQueries()`.\n */\nfunction cancelPendingInitialReads(queryClient: QueryClient, filters: QueryFilters): void {\n for (const query of queryClient.getQueryCache().findAll(filters)) {\n if (query.state.fetchStatus !== \"fetching\") continue;\n if (query.state.data !== undefined) continue;\n void queryClient.cancelQueries({ queryKey: query.queryKey, exact: true });\n }\n}\n\n/**\n * Dispatch a deduplicated list of cache invalidations.\n *\n * Returns a promise that resolves once every `invalidateQueries` call it issued\n * has settled — i.e. once the refetches those invalidations triggered have\n * landed. The dispatch itself stays synchronous (every cancellation and\n * invalidation is issued before this function returns), so a fire-and-forget\n * caller keeps the prior behavior exactly, while a mutation `onSuccess` that\n * RETURNS or awaits the promise stays pending until the refreshed data is in\n * the cache. The promise never rejects: `invalidateQueries` refetches without\n * `throwOnError`, so a failed refetch surfaces on its own query, never as a\n * failure of the committed action that triggered it. The scoped\n * `cancelQueries` calls stay fire-and-forget — cancellation takes effect\n * synchronously and is not part of the refresh being awaited.\n *\n * Before each invalidation, any query it matches that is mid-PENDING-INITIAL-READ\n * is cancelled (see `cancelPendingInitialReads`) so a read that started before\n * the write committed can never land as the query's first — and freshly-marked —\n * value.\n *\n * `refetchType` governs whether that cancellation happens:\n * - `'active'` (the default) and `'all'` cancel-then-invalidate every matched\n * pending initial read — including one TanStack's refetch pass will not\n * restart, since a stale first value would otherwise land and mark the query\n * fresh, while a cancelled one simply refetches for its next observer.\n * - `'none'` invalidates WITHOUT cancelling: the caller has asked for no\n * refetch at all, so cancelling would abandon the only in-flight read the\n * consumer has and leave it with no data and no pending request.\n */\nexport function applyInvalidations(\n queryClient: QueryClient,\n invalidations: ReadonlyArray<CacheInvalidation>,\n): Promise<void> {\n const seen = new Set<string>();\n const refreshes: Promise<void>[] = [];\n for (const inv of invalidations) {\n const sig = serializeInvalidation(inv);\n if (seen.has(sig)) continue;\n seen.add(sig);\n\n const refetchType: RefetchType = inv.refetchType ?? \"active\";\n const filters = invalidationFilters(inv);\n\n if (refetchType !== \"none\") {\n cancelPendingInitialReads(queryClient, filters);\n }\n\n refreshes.push(queryClient.invalidateQueries({ ...filters, refetchType }));\n }\n return Promise.all(refreshes).then(() => undefined);\n}\n"]}
|
|
@@ -16,8 +16,15 @@ export interface DomainEventInvalidator<TEvent extends {
|
|
|
16
16
|
type: string;
|
|
17
17
|
ids: unknown;
|
|
18
18
|
}> {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Dispatch the event's invalidations. The returned promise resolves once
|
|
21
|
+
* every refetch they triggered has settled, and never rejects — return or
|
|
22
|
+
* await it from a mutation's `onSuccess` to keep the mutation pending until
|
|
23
|
+
* the refreshed data lands; ignore it for fire-and-forget dispatch.
|
|
24
|
+
*/
|
|
25
|
+
notify(queryClient: QueryClient, event: TEvent): Promise<void>;
|
|
26
|
+
/** `notify` for several events, deduplicating their invalidations as one batch. */
|
|
27
|
+
notifyAll(queryClient: QueryClient, events: ReadonlyArray<TEvent>): Promise<void>;
|
|
21
28
|
/** Test/debug helpers. */
|
|
22
29
|
readonly helpers: {
|
|
23
30
|
exact: typeof exact;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-domain-event-invalidator.d.ts","sourceRoot":"","sources":["../../src/domain-events/create-domain-event-invalidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAEL,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,iBAAiB,EACvB,MAAM,yBAAyB,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,+BAA+B,CAAC,MAAM,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,IAAI;KAC1F,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CACrB,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC,KAAK,CAAC,KACrC,aAAa,CAAC,iBAAiB,CAAC;CACtC,CAAC;AAEF,MAAM,WAAW,sBAAsB,CAAC,MAAM,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE;IACnF,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"create-domain-event-invalidator.d.ts","sourceRoot":"","sources":["../../src/domain-events/create-domain-event-invalidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAEL,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,iBAAiB,EACvB,MAAM,yBAAyB,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,+BAA+B,CAAC,MAAM,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,IAAI;KAC1F,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CACrB,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC,KAAK,CAAC,KACrC,aAAa,CAAC,iBAAiB,CAAC;CACtC,CAAC;AAEF,MAAM,WAAW,sBAAsB,CAAC,MAAM,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE;IACnF;;;;;OAKG;IACH,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,mFAAmF;IACnF,SAAS,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE;QAChB,KAAK,EAAE,OAAO,KAAK,CAAC;QACpB,MAAM,EAAE,OAAO,MAAM,CAAC;QACtB,SAAS,EAAE,OAAO,SAAS,CAAC;KAC7B,CAAC;IACF,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,+BAA+B,CAAC,MAAM,CAAC,CAAC;CAC5D;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,EACxF,QAAQ,EAAE,+BAA+B,CAAC,MAAM,CAAC,GAChD,sBAAsB,CAAC,MAAM,CAAC,CA4BhC"}
|
|
@@ -11,7 +11,7 @@ export function createDomainEventInvalidator(registry) {
|
|
|
11
11
|
function notify(queryClient, event) {
|
|
12
12
|
const fn = lookup(event.type);
|
|
13
13
|
const invalidations = fn(event.ids);
|
|
14
|
-
applyInvalidations(queryClient, invalidations);
|
|
14
|
+
return applyInvalidations(queryClient, invalidations);
|
|
15
15
|
}
|
|
16
16
|
function notifyAll(queryClient, events) {
|
|
17
17
|
const all = [];
|
|
@@ -19,7 +19,7 @@ export function createDomainEventInvalidator(registry) {
|
|
|
19
19
|
const fn = lookup(event.type);
|
|
20
20
|
all.push(...fn(event.ids));
|
|
21
21
|
}
|
|
22
|
-
applyInvalidations(queryClient, all);
|
|
22
|
+
return applyInvalidations(queryClient, all);
|
|
23
23
|
}
|
|
24
24
|
return {
|
|
25
25
|
notify,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-domain-event-invalidator.js","sourceRoot":"","sources":["../../src/domain-events/create-domain-event-invalidator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,KAAK,EACL,MAAM,EACN,SAAS,GAEV,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"create-domain-event-invalidator.js","sourceRoot":"","sources":["../../src/domain-events/create-domain-event-invalidator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,KAAK,EACL,MAAM,EACN,SAAS,GAEV,MAAM,yBAAyB,CAAC;AAgCjC;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAAiD;IAEjD,SAAS,MAAM,CAA+B,IAAW;QACvD,OAAO,QAAQ,CAAC,IAAI,CAEiB,CAAC;IACxC,CAAC;IAED,SAAS,MAAM,CAAC,WAAwB,EAAE,KAAa;QACrD,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAsB,CAAC,CAAC;QAChD,MAAM,aAAa,GAAG,EAAE,CAAC,KAAK,CAAC,GAAuD,CAAC,CAAC;QACxF,OAAO,kBAAkB,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,SAAS,CAAC,WAAwB,EAAE,MAA6B;QACxE,MAAM,GAAG,GAAwB,EAAE,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAsB,CAAC,CAAC;YAChD,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAuD,CAAC,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,kBAAkB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,MAAM;QACN,SAAS;QACT,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE;QACrC,QAAQ;KACT,CAAC;AACJ,CAAC","sourcesContent":["import type { QueryClient } from \"@tanstack/react-query\";\nimport {\n applyInvalidations,\n exact,\n prefix,\n predicate,\n type CacheInvalidation,\n} from \"./cache-invalidation.js\";\n\n/**\n * Registry shape: each event type maps to a function from the event's `ids`\n * payload to the list of cache invalidations that event should trigger.\n */\nexport type DomainEventInvalidationRegistry<TEvent extends { type: string; ids: unknown }> = {\n [K in TEvent[\"type\"]]: (\n ids: Extract<TEvent, { type: K }>[\"ids\"],\n ) => ReadonlyArray<CacheInvalidation>;\n};\n\nexport interface DomainEventInvalidator<TEvent extends { type: string; ids: unknown }> {\n /**\n * Dispatch the event's invalidations. The returned promise resolves once\n * every refetch they triggered has settled, and never rejects — return or\n * await it from a mutation's `onSuccess` to keep the mutation pending until\n * the refreshed data lands; ignore it for fire-and-forget dispatch.\n */\n notify(queryClient: QueryClient, event: TEvent): Promise<void>;\n /** `notify` for several events, deduplicating their invalidations as one batch. */\n notifyAll(queryClient: QueryClient, events: ReadonlyArray<TEvent>): Promise<void>;\n /** Test/debug helpers. */\n readonly helpers: {\n exact: typeof exact;\n prefix: typeof prefix;\n predicate: typeof predicate;\n };\n /** Direct access to the registry, mainly for tests. */\n readonly registry: DomainEventInvalidationRegistry<TEvent>;\n}\n\n/**\n * Build a domain-event → cache-invalidation notifier from a typed registry.\n * The registry's keys are statically tied to `TEvent[\"type\"]`, so missing or\n * extra entries are compile errors.\n */\nexport function createDomainEventInvalidator<TEvent extends { type: string; ids: unknown }>(\n registry: DomainEventInvalidationRegistry<TEvent>,\n): DomainEventInvalidator<TEvent> {\n function lookup<TType extends TEvent[\"type\"]>(type: TType) {\n return registry[type] as (\n ids: Extract<TEvent, { type: TType }>[\"ids\"],\n ) => ReadonlyArray<CacheInvalidation>;\n }\n\n function notify(queryClient: QueryClient, event: TEvent): Promise<void> {\n const fn = lookup(event.type as TEvent[\"type\"]);\n const invalidations = fn(event.ids as Extract<TEvent, { type: TEvent[\"type\"] }>[\"ids\"]);\n return applyInvalidations(queryClient, invalidations);\n }\n\n function notifyAll(queryClient: QueryClient, events: ReadonlyArray<TEvent>): Promise<void> {\n const all: CacheInvalidation[] = [];\n for (const event of events) {\n const fn = lookup(event.type as TEvent[\"type\"]);\n all.push(...fn(event.ids as Extract<TEvent, { type: TEvent[\"type\"] }>[\"ids\"]));\n }\n return applyInvalidations(queryClient, all);\n }\n\n return {\n notify,\n notifyAll,\n helpers: { exact, prefix, predicate },\n registry,\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/query-core",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.4",
|
|
4
4
|
"description": "Shared TanStack Query (React Query) client defaults, query key helpers, and Firestore integration hooks for TTT Productions apps",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|