@qiaopeng/tanstack-query-plus 0.2.4 → 0.2.6
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/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/queryOptions.d.ts +5 -0
- package/dist/core/queryOptions.d.ts.map +1 -1
- package/dist/core/queryOptions.js +14 -0
- package/dist/hooks/useMutation.d.ts +7 -1
- package/dist/hooks/useMutation.d.ts.map +1 -1
- package/dist/hooks/useMutation.js +111 -19
- package/dist/types/index.d.ts +14 -9
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -1
- package/dist/utils/consistency.d.ts +11 -9
- package/dist/utils/consistency.d.ts.map +1 -1
- package/dist/utils/consistency.js +66 -55
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/optimisticUtils.d.ts +7 -0
- package/dist/utils/optimisticUtils.d.ts.map +1 -1
- package/dist/utils/optimisticUtils.js +31 -1
- package/package.json +1 -1
package/dist/core/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export { isDev, isProd, isTest } from "./env.js";
|
|
|
5
5
|
export { focusManager, type FocusManagerConfig, getSmartFocusManager, pauseFocusManager, resetSmartFocusManager, resumeFocusManager, setupFocusManager, SmartFocusManager } from "./focusManager.js";
|
|
6
6
|
export { areKeysEqual, containsEntity, createComplexKey, createDomainKeyFactory, createFilteredKey, createMutationKeyFactory, createPaginatedKey, createSearchKey, createSortedKey, extractEntityId, matchesKeyPattern, normalizeQueryKey, queryKeys, validateQueryKey } from "./keys.js";
|
|
7
7
|
export { createAppQueryOptions, createAppQueryOptionsWithSelect } from "./queryOptions.js";
|
|
8
|
+
export { createListQueryOptions, type ListQueryConfig } from "./queryOptions.js";
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,2BAA2B,EAC3B,cAAc,EACd,cAAc,EACd,cAAc,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpH,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EACL,YAAY,EACZ,KAAK,kBAAkB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,2BAA2B,EAC3B,cAAc,EACd,cAAc,EACd,cAAc,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpH,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EACL,YAAY,EACZ,KAAK,kBAAkB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -5,3 +5,4 @@ export { isDev, isProd, isTest } from "./env.js";
|
|
|
5
5
|
export { focusManager, getSmartFocusManager, pauseFocusManager, resetSmartFocusManager, resumeFocusManager, setupFocusManager, SmartFocusManager } from "./focusManager.js";
|
|
6
6
|
export { areKeysEqual, containsEntity, createComplexKey, createDomainKeyFactory, createFilteredKey, createMutationKeyFactory, createPaginatedKey, createSearchKey, createSortedKey, extractEntityId, matchesKeyPattern, normalizeQueryKey, queryKeys, validateQueryKey } from "./keys.js";
|
|
7
7
|
export { createAppQueryOptions, createAppQueryOptionsWithSelect } from "./queryOptions.js";
|
|
8
|
+
export { createListQueryOptions } from "./queryOptions.js";
|
|
@@ -11,4 +11,9 @@ export interface SelectQueryConfig<TData, TSelected = TData> extends Omit<BaseQu
|
|
|
11
11
|
select: (data: TData) => TSelected;
|
|
12
12
|
}
|
|
13
13
|
export declare function createAppQueryOptionsWithSelect<TData, TSelected = TData>(config: SelectQueryConfig<TData, TSelected>): UseQueryOptions<TData, DefaultError, TSelected, QueryKey>;
|
|
14
|
+
export interface ListQueryConfig<TData> extends Omit<BaseQueryConfig<TData>, "staleTime" | "gcTime"> {
|
|
15
|
+
staleTime?: number;
|
|
16
|
+
gcTime?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function createListQueryOptions<TData>(config: ListQueryConfig<TData>): UseQueryOptions<TData, DefaultError, TData, QueryKey>;
|
|
14
19
|
//# sourceMappingURL=queryOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryOptions.d.ts","sourceRoot":"","sources":["../../src/core/queryOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIpG,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAalI;AAED,MAAM,WAAW,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CAAE,SAAQ,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC1G,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC;CACpC;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,CAAC,CAahL"}
|
|
1
|
+
{"version":3,"file":"queryOptions.d.ts","sourceRoot":"","sources":["../../src/core/queryOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIpG,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAalI;AAED,MAAM,WAAW,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CAAE,SAAQ,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC1G,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC;CACpC;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,CAAC,CAahL;AAED,MAAM,WAAW,eAAe,CAAC,KAAK,CAAE,SAAQ,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;IAClG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAanI"}
|
|
@@ -28,3 +28,17 @@ export function createAppQueryOptionsWithSelect(config) {
|
|
|
28
28
|
refetchOnMount: true
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
+
export function createListQueryOptions(config) {
|
|
32
|
+
return queryOptions({
|
|
33
|
+
queryKey: config.queryKey,
|
|
34
|
+
queryFn: config.queryFn,
|
|
35
|
+
staleTime: config.staleTime ?? 0,
|
|
36
|
+
gcTime: config.gcTime ?? DEFAULT_GC_TIME,
|
|
37
|
+
enabled: config.enabled,
|
|
38
|
+
retry: defaultQueryRetryStrategy,
|
|
39
|
+
retryDelay: exponentialBackoff,
|
|
40
|
+
refetchOnWindowFocus: true,
|
|
41
|
+
refetchOnReconnect: true,
|
|
42
|
+
refetchOnMount: true
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { MutationFunction, MutationKey, QueryClient, QueryKey, UseMutationO
|
|
|
2
2
|
import type { MutationContext, MutationOptions } from "../types";
|
|
3
3
|
import type { EntityWithId } from "../types/selectors";
|
|
4
4
|
export type { MutationKey };
|
|
5
|
+
import { FamilySyncConfig } from "../utils/consistency.js";
|
|
5
6
|
export interface MutationDefaultsConfig {
|
|
6
7
|
[key: string]: TanStackUseMutationOptions<any, any, any, any>;
|
|
7
8
|
}
|
|
@@ -10,11 +11,16 @@ export declare function setupMutationDefaults(queryClient: QueryClient, config:
|
|
|
10
11
|
export declare function useListMutation<T extends EntityWithId>(mutationFn: MutationFunction<T, {
|
|
11
12
|
operation: string;
|
|
12
13
|
data: Partial<T>;
|
|
13
|
-
}>, queryKey: QueryKey, options?: TanStackUseMutationOptions<T, Error, {
|
|
14
|
+
}>, queryKey: QueryKey, options?: (TanStackUseMutationOptions<T, Error, {
|
|
14
15
|
operation: string;
|
|
15
16
|
data: Partial<T>;
|
|
16
17
|
}> & {
|
|
17
18
|
mutationKey?: readonly unknown[];
|
|
19
|
+
}) & {
|
|
20
|
+
consistency?: {
|
|
21
|
+
familySync?: FamilySyncConfig;
|
|
22
|
+
mode?: "sync+invalidate" | "invalidate-only";
|
|
23
|
+
};
|
|
18
24
|
}): UseMutationResult<T, Error, {
|
|
19
25
|
operation: string;
|
|
20
26
|
data: Partial<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMutation.d.ts","sourceRoot":"","sources":["../../src/hooks/useMutation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,kBAAkB,IAAI,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACvK,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"useMutation.d.ts","sourceRoot":"","sources":["../../src/hooks/useMutation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,29 @@
|
|
|
1
|
-
import { findFamilyQueries, syncEntityAcrossFamily } from "../utils/consistency.js";
|
|
2
1
|
import { useQueryClient, useMutation as useTanStackMutation } from "@tanstack/react-query";
|
|
3
2
|
import { DEFAULT_MUTATION_CONFIG } from "../core/config.js";
|
|
3
|
+
import { syncEntityAcrossFamily, DEFAULT_FAMILY_SYNC } from "../utils/consistency.js";
|
|
4
|
+
function deriveFamilyKey(queryKey) {
|
|
5
|
+
const arr = Array.isArray(queryKey) ? [...queryKey] : [queryKey];
|
|
6
|
+
while (arr.length > 1) {
|
|
7
|
+
const last = arr[arr.length - 1];
|
|
8
|
+
if (last && typeof last === "object" && !Array.isArray(last)) {
|
|
9
|
+
arr.pop();
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
if (typeof last === "string" && (last === "paginated" || last === "filtered" || last === "sorted" || last === "search" || last === "complex")) {
|
|
13
|
+
arr.pop();
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
return arr;
|
|
19
|
+
}
|
|
20
|
+
function isListFamilyKey(queryKey) {
|
|
21
|
+
const parts = Array.isArray(queryKey) ? queryKey : [queryKey];
|
|
22
|
+
return parts.includes("list") || parts.includes("paginated");
|
|
23
|
+
}
|
|
4
24
|
export function useMutation(options) {
|
|
5
25
|
const queryClient = useQueryClient();
|
|
6
|
-
const { optimistic, onMutate, onError, onSuccess, onSettled, ...restOptions } = options;
|
|
26
|
+
const { optimistic, onMutate, onError, onSuccess, onSettled, consistency, ...restOptions } = options;
|
|
7
27
|
const mutationConfig = {
|
|
8
28
|
...restOptions,
|
|
9
29
|
retry: restOptions.retry ?? DEFAULT_MUTATION_CONFIG?.retry,
|
|
@@ -32,7 +52,7 @@ export function useMutation(options) {
|
|
|
32
52
|
return { userContext };
|
|
33
53
|
}
|
|
34
54
|
try {
|
|
35
|
-
await queryClient.cancelQueries({ queryKey: optimistic.queryKey });
|
|
55
|
+
await queryClient.cancelQueries({ queryKey: optimistic.queryKey, exact: true });
|
|
36
56
|
const previousData = queryClient.getQueryData(optimistic.queryKey);
|
|
37
57
|
let mappedVariables = variables;
|
|
38
58
|
if (optimistic.fieldMapping && typeof variables === "object" && variables !== null) {
|
|
@@ -70,20 +90,45 @@ export function useMutation(options) {
|
|
|
70
90
|
}
|
|
71
91
|
};
|
|
72
92
|
mutationConfig.onSuccess = (data, variables, context) => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
const shouldSync = (consistency?.mode ?? "sync+invalidate") === "sync+invalidate";
|
|
94
|
+
if (shouldSync && optimistic?.queryKey) {
|
|
95
|
+
const familyKey = optimistic.familyKey ?? deriveFamilyKey(optimistic.queryKey);
|
|
96
|
+
const payload = typeof variables === "object" && variables !== null ? (variables.data ?? variables) : variables;
|
|
97
|
+
const op = typeof variables?.operation === "string" ? variables.operation : "update";
|
|
98
|
+
const cfg = consistency?.familySync ?? DEFAULT_FAMILY_SYNC;
|
|
99
|
+
syncEntityAcrossFamily(queryClient, familyKey, cfg, op, payload);
|
|
100
|
+
}
|
|
101
|
+
const scope = optimistic.invalidateScope ?? (isListFamilyKey(optimistic.queryKey) ? "family" : "exact");
|
|
102
|
+
const invalidations = [];
|
|
103
|
+
if (scope !== "none") {
|
|
104
|
+
if (scope === "family") {
|
|
105
|
+
const familyKey = optimistic.familyKey ?? deriveFamilyKey(optimistic.queryKey);
|
|
106
|
+
invalidations.push({ queryKey: familyKey });
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
invalidations.push({ queryKey: optimistic.queryKey });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (Array.isArray(optimistic.relatedKeys) && optimistic.relatedKeys.length > 0) {
|
|
113
|
+
optimistic.relatedKeys.forEach((k) => invalidations.push({ queryKey: k }));
|
|
114
|
+
}
|
|
115
|
+
if (invalidations.length > 0) {
|
|
116
|
+
const seen = new Set();
|
|
117
|
+
const tasks = invalidations
|
|
118
|
+
.map((cfg) => ({ ...cfg, exact: false }))
|
|
119
|
+
.filter((cfg) => {
|
|
120
|
+
const key = JSON.stringify(cfg.queryKey);
|
|
121
|
+
if (seen.has(key))
|
|
122
|
+
return false;
|
|
123
|
+
seen.add(key);
|
|
124
|
+
return true;
|
|
125
|
+
});
|
|
126
|
+
if (tasks.length === 1) {
|
|
127
|
+
queryClient.invalidateQueries(tasks[0]);
|
|
128
|
+
}
|
|
129
|
+
else if (tasks.length > 1) {
|
|
130
|
+
invalidateQueriesBatch(queryClient, tasks);
|
|
85
131
|
}
|
|
86
|
-
catch { }
|
|
87
132
|
}
|
|
88
133
|
if (onSuccess) {
|
|
89
134
|
const successCallback = onSuccess;
|
|
@@ -104,7 +149,23 @@ export function setupMutationDefaults(queryClient, config) {
|
|
|
104
149
|
}
|
|
105
150
|
export function useListMutation(mutationFn, queryKey, options) {
|
|
106
151
|
const queryClient = useQueryClient();
|
|
107
|
-
return useTanStackMutation({
|
|
152
|
+
return useTanStackMutation({
|
|
153
|
+
mutationFn,
|
|
154
|
+
onSuccess: (_data, variables) => {
|
|
155
|
+
const mode = options?.consistency?.mode ?? "sync+invalidate";
|
|
156
|
+
if (mode === "sync+invalidate") {
|
|
157
|
+
const familyKey = deriveFamilyKey(queryKey);
|
|
158
|
+
const cfg = options?.consistency?.familySync ?? DEFAULT_FAMILY_SYNC;
|
|
159
|
+
syncEntityAcrossFamily(queryClient, familyKey, cfg, variables.operation, variables.data);
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
onSettled: () => {
|
|
163
|
+
const familyKey = deriveFamilyKey(queryKey);
|
|
164
|
+
queryClient.invalidateQueries({ queryKey: familyKey, exact: false });
|
|
165
|
+
},
|
|
166
|
+
...options,
|
|
167
|
+
mutationKey: options?.mutationKey
|
|
168
|
+
});
|
|
108
169
|
}
|
|
109
170
|
export function useBatchMutation(mutationFn, options) {
|
|
110
171
|
return useTanStackMutation({ mutationFn, ...options, mutationKey: options?.mutationKey });
|
|
@@ -122,7 +183,7 @@ export function useConditionalOptimisticMutation(mutationFn, condition, options)
|
|
|
122
183
|
return { userContext, conditionMet: false };
|
|
123
184
|
}
|
|
124
185
|
try {
|
|
125
|
-
await queryClient.cancelQueries({ queryKey: optimistic.queryKey });
|
|
186
|
+
await queryClient.cancelQueries({ queryKey: optimistic.queryKey, exact: true });
|
|
126
187
|
const previousData = queryClient.getQueryData(optimistic.queryKey);
|
|
127
188
|
queryClient.setQueryData(optimistic.queryKey, (oldData) => optimistic.updater(oldData, variables));
|
|
128
189
|
const mutateCallback = onMutate;
|
|
@@ -156,7 +217,38 @@ export function useConditionalOptimisticMutation(mutationFn, condition, options)
|
|
|
156
217
|
};
|
|
157
218
|
mutationConfig.onSettled = (data, error, variables, context) => {
|
|
158
219
|
if (context?.conditionMet) {
|
|
159
|
-
|
|
220
|
+
const scope = optimistic.invalidateScope ?? (isListFamilyKey(optimistic.queryKey) ? "family" : "exact");
|
|
221
|
+
const invalidations = [];
|
|
222
|
+
if (scope !== "none") {
|
|
223
|
+
if (scope === "family") {
|
|
224
|
+
const familyKey = optimistic.familyKey ?? deriveFamilyKey(optimistic.queryKey);
|
|
225
|
+
invalidations.push({ queryKey: familyKey });
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
invalidations.push({ queryKey: optimistic.queryKey });
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (Array.isArray(optimistic.relatedKeys) && optimistic.relatedKeys.length > 0) {
|
|
232
|
+
optimistic.relatedKeys.forEach((k) => invalidations.push({ queryKey: k }));
|
|
233
|
+
}
|
|
234
|
+
if (invalidations.length > 0) {
|
|
235
|
+
const seen = new Set();
|
|
236
|
+
const tasks = invalidations
|
|
237
|
+
.map((cfg) => ({ ...cfg, exact: false }))
|
|
238
|
+
.filter((cfg) => {
|
|
239
|
+
const key = JSON.stringify(cfg.queryKey);
|
|
240
|
+
if (seen.has(key))
|
|
241
|
+
return false;
|
|
242
|
+
seen.add(key);
|
|
243
|
+
return true;
|
|
244
|
+
});
|
|
245
|
+
if (tasks.length === 1) {
|
|
246
|
+
queryClient.invalidateQueries(tasks[0]);
|
|
247
|
+
}
|
|
248
|
+
else if (tasks.length > 1) {
|
|
249
|
+
invalidateQueriesBatch(queryClient, tasks);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
160
252
|
}
|
|
161
253
|
if (onSettled) {
|
|
162
254
|
const settledCallback = onSettled;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ export * from "./optimistic.js";
|
|
|
6
6
|
export * from "./persistence.js";
|
|
7
7
|
export * from "./selectors.js";
|
|
8
8
|
export * from "./suspense.js";
|
|
9
|
-
export * from "./consistency.js";
|
|
10
9
|
export interface MutationContext<TData = unknown, TContext = unknown> {
|
|
11
10
|
previousData?: TData;
|
|
12
11
|
userContext?: TContext;
|
|
@@ -19,16 +18,22 @@ export interface MutationOptions<TData, TError, TVariables, TContext = unknown>
|
|
|
19
18
|
enabled?: boolean;
|
|
20
19
|
fieldMapping?: Record<string, string>;
|
|
21
20
|
rollback?: <TQueryData = unknown>(previousData: TQueryData, error: Error) => void;
|
|
21
|
+
invalidateScope?: "none" | "exact" | "family";
|
|
22
|
+
familyKey?: QueryKey;
|
|
23
|
+
relatedKeys?: QueryKey[];
|
|
22
24
|
};
|
|
23
25
|
consistency?: {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
familySync?: {
|
|
27
|
+
idField?: string;
|
|
28
|
+
listSelector?: (data: unknown) => {
|
|
29
|
+
items: unknown[];
|
|
30
|
+
total?: number;
|
|
31
|
+
} | null;
|
|
32
|
+
writeBack?: (old: unknown, items: unknown[], total?: number) => unknown;
|
|
33
|
+
maxKeys?: number;
|
|
34
|
+
enableForOperations?: Array<"update" | "delete">;
|
|
35
|
+
};
|
|
36
|
+
mode?: "sync+invalidate" | "invalidate-only";
|
|
32
37
|
};
|
|
33
38
|
}
|
|
34
39
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC1E,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC1E,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,MAAM,WAAW,eAAe,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IAAI,YAAY,CAAC,EAAE,KAAK,CAAC;IAAC,WAAW,CAAC,EAAE,QAAQ,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE;AAC9I,MAAM,WAAW,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,GAAG,OAAO,CAAE,SAAQ,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC;IAC7I,UAAU,CAAC,EAAE;QACX,QAAQ,EAAE,QAAQ,CAAC;QACnB,OAAO,EAAE,CAAC,UAAU,GAAG,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,SAAS,EAAE,SAAS,EAAE,UAAU,KAAK,UAAU,GAAG,SAAS,CAAC;QAClH,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,QAAQ,CAAC,EAAE,CAAC,UAAU,GAAG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;QAClF,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;QAC9C,SAAS,CAAC,EAAE,QAAQ,CAAC;QACrB,WAAW,CAAC,EAAE,QAAQ,EAAE,CAAC;KAC1B,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE;YACX,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK;gBAAE,KAAK,EAAE,OAAO,EAAE,CAAC;gBAAC,KAAK,CAAC,EAAE,MAAM,CAAA;aAAE,GAAG,IAAI,CAAC;YAC9E,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;YACxE,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,mBAAmB,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC;SAClD,CAAC;QACF,IAAI,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAAC;KAC9C,CAAC;CACH"}
|
package/dist/types/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { QueryClient, QueryKey } from "@tanstack/react-query";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
export declare function findFamilyQueries(queryClient: QueryClient, options: FamilyQueryMatchOptions): QueryKey[];
|
|
7
|
-
export declare function syncEntityAcrossFamily(queryClient: QueryClient, keys: QueryKey[], updatedEntity: unknown, options: {
|
|
2
|
+
import type { EntityWithId } from "../types/selectors";
|
|
3
|
+
export declare function startsWithKeyPrefix(key: QueryKey, prefix: QueryKey): boolean;
|
|
4
|
+
export type FamilySyncConfig = {
|
|
8
5
|
idField?: string;
|
|
9
|
-
listSelector?: (data: unknown) =>
|
|
10
|
-
items:
|
|
6
|
+
listSelector?: (data: unknown) => {
|
|
7
|
+
items: EntityWithId[];
|
|
11
8
|
total?: number;
|
|
12
9
|
} | null;
|
|
13
|
-
|
|
10
|
+
writeBack?: (old: unknown, items: EntityWithId[], total?: number) => unknown;
|
|
11
|
+
maxKeys?: number;
|
|
12
|
+
enableForOperations?: Array<"update" | "delete">;
|
|
13
|
+
};
|
|
14
|
+
export declare const DEFAULT_FAMILY_SYNC: FamilySyncConfig;
|
|
15
|
+
export declare function syncEntityAcrossFamily(queryClient: QueryClient, familyPrefix: QueryKey, cfg: FamilySyncConfig, operation: string, payload: Partial<EntityWithId>): void;
|
|
14
16
|
//# sourceMappingURL=consistency.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consistency.d.ts","sourceRoot":"","sources":["../../src/utils/consistency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"consistency.d.ts","sourceRoot":"","sources":["../../src/utils/consistency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAA2O;AACxT,MAAM,MAAM,gBAAgB,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK;QAAE,KAAK,EAAE,YAAY,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAA;CAAE,CAAC;AA2B1R,eAAO,MAAM,mBAAmB,EAAE,gBAA4J,CAAC;AAC/L,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAqBvK"}
|
|
@@ -1,68 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { listUpdater } from "./optimisticUtils.js";
|
|
2
|
+
function ensureArray(key) { return Array.isArray(key) ? key : [key]; }
|
|
3
|
+
function deepEqual(a, b) { if (a === b)
|
|
4
|
+
return true; if (typeof a === "object" && a !== null && typeof b === "object" && b !== null) {
|
|
5
|
+
try {
|
|
3
6
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
4
7
|
}
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
function startsWithKey(key, prefix) {
|
|
8
|
-
if (prefix.length > key.length)
|
|
8
|
+
catch {
|
|
9
9
|
return false;
|
|
10
|
-
for (let i = 0; i < prefix.length; i++) {
|
|
11
|
-
if (!isObjectEqual(key[i], prefix[i]))
|
|
12
|
-
return false;
|
|
13
10
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
} return false; }
|
|
12
|
+
export function startsWithKeyPrefix(key, prefix) { const k = ensureArray(key); const p = ensureArray(prefix); if (p.length > k.length)
|
|
13
|
+
return false; for (let i = 0; i < p.length; i++) {
|
|
14
|
+
const a = k[i];
|
|
15
|
+
const b = p[i];
|
|
16
|
+
if (!(a === b || deepEqual(a, b)))
|
|
17
|
+
return false;
|
|
18
|
+
} return true; }
|
|
19
|
+
function defaultListSelector(data) {
|
|
20
|
+
if (!data)
|
|
21
|
+
return null;
|
|
22
|
+
if (Array.isArray(data))
|
|
23
|
+
return { items: data };
|
|
24
|
+
if (typeof data === "object") {
|
|
25
|
+
const obj = data;
|
|
26
|
+
if (Array.isArray(obj.items))
|
|
27
|
+
return { items: obj.items, total: typeof obj.total === "number" ? obj.total : undefined };
|
|
28
|
+
if (Array.isArray(obj.Rows))
|
|
29
|
+
return { items: obj.Rows, total: typeof obj.Total === "number" ? obj.Total : undefined };
|
|
22
30
|
}
|
|
23
|
-
return
|
|
31
|
+
return null;
|
|
24
32
|
}
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return { ...item, ...updated };
|
|
33
|
+
function defaultWriteBack(old, items, total) {
|
|
34
|
+
if (old && typeof old === "object") {
|
|
35
|
+
const obj = { ...old };
|
|
36
|
+
if (Array.isArray(obj.Rows)) {
|
|
37
|
+
obj.Rows = items;
|
|
38
|
+
if (typeof total !== "undefined")
|
|
39
|
+
obj.Total = total;
|
|
40
|
+
return obj;
|
|
34
41
|
}
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
if (Array.isArray(obj.items)) {
|
|
43
|
+
obj.items = items;
|
|
44
|
+
if (typeof total !== "undefined")
|
|
45
|
+
obj.total = total;
|
|
46
|
+
return obj;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { items, total };
|
|
37
50
|
}
|
|
38
|
-
export
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
export const DEFAULT_FAMILY_SYNC = { idField: "id", listSelector: defaultListSelector, writeBack: defaultWriteBack, maxKeys: 50, enableForOperations: ["update", "delete"] };
|
|
52
|
+
export function syncEntityAcrossFamily(queryClient, familyPrefix, cfg, operation, payload) {
|
|
53
|
+
const enabledOps = cfg.enableForOperations ?? ["update", "delete"];
|
|
54
|
+
const op = String(operation).toLowerCase();
|
|
55
|
+
if (!enabledOps.includes(op))
|
|
56
|
+
return;
|
|
57
|
+
const idField = cfg.idField ?? "id";
|
|
58
|
+
const cache = queryClient.getQueryCache();
|
|
59
|
+
const queries = cache.findAll({ predicate: (q) => startsWithKeyPrefix(q.queryKey, familyPrefix) });
|
|
60
|
+
const limited = typeof cfg.maxKeys === "number" && cfg.maxKeys > 0 ? queries.slice(0, cfg.maxKeys) : queries;
|
|
61
|
+
limited.forEach((q) => {
|
|
62
|
+
const key = q.queryKey;
|
|
63
|
+
const old = queryClient.getQueryData(key);
|
|
64
|
+
const picked = (cfg.listSelector ?? defaultListSelector)(old);
|
|
65
|
+
if (!picked || !Array.isArray(picked.items))
|
|
45
66
|
return;
|
|
67
|
+
const idValue = payload?.[idField];
|
|
68
|
+
let items = picked.items;
|
|
69
|
+
if (op === "update" && idValue !== undefined) {
|
|
70
|
+
items = listUpdater.update(items, { ...payload, id: idValue });
|
|
46
71
|
}
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
if (selector) {
|
|
50
|
-
const selected = selector(oldData);
|
|
51
|
-
if (selected === null)
|
|
52
|
-
return;
|
|
53
|
-
if (selected && Array.isArray(selected.items)) {
|
|
54
|
-
const nextItems = updateArrayById(selected.items, updatedEntity, idField);
|
|
55
|
-
const next = { ...oldData, items: nextItems };
|
|
56
|
-
queryClient.setQueryData(key, next);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (Object.prototype.hasOwnProperty.call(oldData, "items")) {
|
|
61
|
-
const items = oldData["items"];
|
|
62
|
-
const nextItems = updateArrayById(items, updatedEntity, idField);
|
|
63
|
-
const next = { ...oldData, items: nextItems };
|
|
64
|
-
queryClient.setQueryData(key, next);
|
|
65
|
-
}
|
|
72
|
+
else if (op === "delete" && idValue !== undefined) {
|
|
73
|
+
items = listUpdater.remove(items, idValue);
|
|
66
74
|
}
|
|
75
|
+
const total = typeof picked.total === "number" && op === "delete" ? Math.max(0, picked.total - 1) : picked.total;
|
|
76
|
+
const next = (cfg.writeBack ?? defaultWriteBack)(old, items, total);
|
|
77
|
+
queryClient.setQueryData(key, next);
|
|
67
78
|
});
|
|
68
79
|
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export { getPrefetchManager, type InteractionRecord, type NetworkSpeed, type Pre
|
|
|
6
6
|
export { createQueryKeyFactory, createSimpleQueryKeyFactory, extractParamsFromKey, isQueryKeyEqual, type NormalizeConfig, normalizeQueryParams, type QueryKeyFactory, type QueryKeyFactoryConfig } from "./queryKey.js";
|
|
7
7
|
export { compose, selectById, selectByIds, selectCount, selectField, selectFields, selectFirst, selectItems, selectLast, selectMap, selectors, selectTotal, selectWhere } from "./selectors.js";
|
|
8
8
|
export { deepClone, formatBytes, getStorageUsage, isStorageAvailable } from "./storage.js";
|
|
9
|
-
export {
|
|
9
|
+
export { startsWithKeyPrefix, syncEntityAcrossFamily, DEFAULT_FAMILY_SYNC, type FamilySyncConfig } from "./consistency.js";
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACpH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC3H,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,KAAK,sBAAsB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC1P,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACpO,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACxN,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChM,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC3F,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACpH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC3H,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,KAAK,sBAAsB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC1P,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACpO,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACxN,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChM,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/utils/index.js
CHANGED
|
@@ -6,4 +6,4 @@ export { getPrefetchManager, resetPrefetchManager, SmartPrefetchManager } from "
|
|
|
6
6
|
export { createQueryKeyFactory, createSimpleQueryKeyFactory, extractParamsFromKey, isQueryKeyEqual, normalizeQueryParams } from "./queryKey.js";
|
|
7
7
|
export { compose, selectById, selectByIds, selectCount, selectField, selectFields, selectFirst, selectItems, selectLast, selectMap, selectors, selectTotal, selectWhere } from "./selectors.js";
|
|
8
8
|
export { deepClone, formatBytes, getStorageUsage, isStorageAvailable } from "./storage.js";
|
|
9
|
-
export {
|
|
9
|
+
export { startsWithKeyPrefix, syncEntityAcrossFamily, DEFAULT_FAMILY_SYNC } from "./consistency.js";
|
|
@@ -31,4 +31,11 @@ export declare function batchUpdateItems<T extends EntityWithId>(items: T[] | un
|
|
|
31
31
|
export declare function batchRemoveItems<T extends EntityWithId>(items: T[] | undefined | null, itemIds: Array<T["id"]>): T[];
|
|
32
32
|
export declare function reorderItems<T extends EntityWithId>(items: T[] | undefined | null, fromIndex: number, toIndex: number): T[];
|
|
33
33
|
export declare function conditionalUpdateItems<T extends EntityWithId>(items: T[] | undefined | null, predicate: (item: T) => boolean, updater: (item: T) => Partial<T>): T[];
|
|
34
|
+
export declare function applyListOperationToPaginated<T extends EntityWithId>(data: {
|
|
35
|
+
items: T[];
|
|
36
|
+
total?: number;
|
|
37
|
+
}, operation: ListOperationType, payload: Partial<T>): {
|
|
38
|
+
items: T[];
|
|
39
|
+
total?: number;
|
|
40
|
+
};
|
|
34
41
|
//# sourceMappingURL=optimisticUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimisticUtils.d.ts","sourceRoot":"","sources":["../../src/utils/optimisticUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"optimisticUtils.d.ts","sourceRoot":"","sources":["../../src/utils/optimisticUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,7 +45,16 @@ export function createListOperationConfig(config) {
|
|
|
45
45
|
return oldData || [];
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
|
-
rollback: config.onRollback
|
|
48
|
+
rollback: config.onRollback
|
|
49
|
+
? (previousData, error) => {
|
|
50
|
+
const opType = config.operation === ListOperationType.ADD
|
|
51
|
+
? "create"
|
|
52
|
+
: config.operation === ListOperationType.REMOVE
|
|
53
|
+
? "delete"
|
|
54
|
+
: "update";
|
|
55
|
+
config.onRollback(error, { previousData, timestamp: Date.now(), operationType: opType });
|
|
56
|
+
}
|
|
57
|
+
: undefined,
|
|
49
58
|
enabled: true
|
|
50
59
|
};
|
|
51
60
|
}
|
|
@@ -74,3 +83,24 @@ export function conditionalUpdateItems(items, predicate, updater) {
|
|
|
74
83
|
return { ...item, ...updater(item) };
|
|
75
84
|
} return item; });
|
|
76
85
|
}
|
|
86
|
+
export function applyListOperationToPaginated(data, operation, payload) {
|
|
87
|
+
let items = data.items || [];
|
|
88
|
+
if (operation === ListOperationType.ADD) {
|
|
89
|
+
items = listUpdater.add(items, payload);
|
|
90
|
+
}
|
|
91
|
+
else if (operation === ListOperationType.UPDATE) {
|
|
92
|
+
items = listUpdater.update(items, payload);
|
|
93
|
+
}
|
|
94
|
+
else if (operation === ListOperationType.REMOVE) {
|
|
95
|
+
const id = payload?.id;
|
|
96
|
+
items = listUpdater.remove(items, id);
|
|
97
|
+
}
|
|
98
|
+
const total = typeof data.total === "number"
|
|
99
|
+
? operation === ListOperationType.ADD
|
|
100
|
+
? data.total + 1
|
|
101
|
+
: operation === ListOperationType.REMOVE
|
|
102
|
+
? Math.max(0, data.total - 1)
|
|
103
|
+
: data.total
|
|
104
|
+
: data.total;
|
|
105
|
+
return { ...data, items, total };
|
|
106
|
+
}
|