@qiaopeng/tanstack-query-plus 0.2.5 → 0.2.7

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.
@@ -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":"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"}
1
+ {"version":3,"file":"useMutation.d.ts","sourceRoot":"","sources":["../../src/hooks/useMutation.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { useQueryClient, useMutation as useTanStackMutation } from "@tanstack/react-query";
2
2
  import { DEFAULT_MUTATION_CONFIG } from "../core/config.js";
3
+ import { syncEntityAcrossFamily, syncEntityAcrossFamilyOptimistic, DEFAULT_FAMILY_SYNC } from "../utils/consistency.js";
3
4
  function deriveFamilyKey(queryKey) {
4
5
  const arr = Array.isArray(queryKey) ? [...queryKey] : [queryKey];
5
6
  while (arr.length > 1) {
@@ -22,7 +23,7 @@ function isListFamilyKey(queryKey) {
22
23
  }
23
24
  export function useMutation(options) {
24
25
  const queryClient = useQueryClient();
25
- const { optimistic, onMutate, onError, onSuccess, onSettled, ...restOptions } = options;
26
+ const { optimistic, onMutate, onError, onSuccess, onSettled, consistency, ...restOptions } = options;
26
27
  const mutationConfig = {
27
28
  ...restOptions,
28
29
  retry: restOptions.retry ?? DEFAULT_MUTATION_CONFIG?.retry,
@@ -65,9 +66,18 @@ export function useMutation(options) {
65
66
  });
66
67
  }
67
68
  queryClient.setQueryData(optimistic.queryKey, (oldData) => optimistic.updater(oldData, mappedVariables));
69
+ let familyRollbackData = [];
70
+ const shouldSync = (consistency?.mode ?? "sync+invalidate") === "sync+invalidate";
71
+ if (shouldSync && optimistic?.queryKey) {
72
+ const familyKey = optimistic.familyKey ?? deriveFamilyKey(optimistic.queryKey);
73
+ const payload = typeof variables === "object" && variables !== null ? (variables.data ?? variables) : variables;
74
+ const op = typeof variables?.operation === "string" ? variables.operation : "update";
75
+ const cfg = consistency?.familySync ?? DEFAULT_FAMILY_SYNC;
76
+ familyRollbackData = syncEntityAcrossFamilyOptimistic(queryClient, familyKey, cfg, op, payload);
77
+ }
68
78
  const mutateCallback = onMutate;
69
79
  const userContext = onMutate ? await mutateCallback(variables) : undefined;
70
- return { previousData, userContext };
80
+ return { previousData, userContext, familyRollbackData };
71
81
  }
72
82
  catch (error) {
73
83
  return { userContext: undefined };
@@ -77,6 +87,11 @@ export function useMutation(options) {
77
87
  if (context?.previousData !== undefined) {
78
88
  queryClient.setQueryData(optimistic.queryKey, context.previousData);
79
89
  }
90
+ if (context?.familyRollbackData) {
91
+ context.familyRollbackData.forEach(item => {
92
+ queryClient.setQueryData(item.queryKey, item.previousData);
93
+ });
94
+ }
80
95
  if (optimistic.rollback && context?.previousData !== undefined) {
81
96
  try {
82
97
  optimistic.rollback(context.previousData, error);
@@ -89,6 +104,14 @@ export function useMutation(options) {
89
104
  }
90
105
  };
91
106
  mutationConfig.onSuccess = (data, variables, context) => {
107
+ const shouldSync = (consistency?.mode ?? "sync+invalidate") === "sync+invalidate";
108
+ if (shouldSync && optimistic?.queryKey) {
109
+ const familyKey = optimistic.familyKey ?? deriveFamilyKey(optimistic.queryKey);
110
+ const payload = typeof variables === "object" && variables !== null ? (variables.data ?? variables) : variables;
111
+ const op = typeof variables?.operation === "string" ? variables.operation : "update";
112
+ const cfg = consistency?.familySync ?? DEFAULT_FAMILY_SYNC;
113
+ syncEntityAcrossFamily(queryClient, familyKey, cfg, op, payload);
114
+ }
92
115
  const scope = optimistic.invalidateScope ?? (isListFamilyKey(optimistic.queryKey) ? "family" : "exact");
93
116
  const invalidations = [];
94
117
  if (scope !== "none") {
@@ -103,6 +126,9 @@ export function useMutation(options) {
103
126
  if (Array.isArray(optimistic.relatedKeys) && optimistic.relatedKeys.length > 0) {
104
127
  optimistic.relatedKeys.forEach((k) => invalidations.push({ queryKey: k }));
105
128
  }
129
+ if (Array.isArray(optimistic.invalidates) && optimistic.invalidates.length > 0) {
130
+ optimistic.invalidates.forEach((k) => invalidations.push({ queryKey: k }));
131
+ }
106
132
  if (invalidations.length > 0) {
107
133
  const seen = new Set();
108
134
  const tasks = invalidations
@@ -142,6 +168,14 @@ export function useListMutation(mutationFn, queryKey, options) {
142
168
  const queryClient = useQueryClient();
143
169
  return useTanStackMutation({
144
170
  mutationFn,
171
+ onSuccess: (_data, variables) => {
172
+ const mode = options?.consistency?.mode ?? "sync+invalidate";
173
+ if (mode === "sync+invalidate") {
174
+ const familyKey = deriveFamilyKey(queryKey);
175
+ const cfg = options?.consistency?.familySync ?? DEFAULT_FAMILY_SYNC;
176
+ syncEntityAcrossFamily(queryClient, familyKey, cfg, variables.operation, variables.data);
177
+ }
178
+ },
145
179
  onSettled: () => {
146
180
  const familyKey = deriveFamilyKey(queryKey);
147
181
  queryClient.invalidateQueries({ queryKey: familyKey, exact: false });
@@ -10,6 +10,10 @@ export interface MutationContext<TData = unknown, TContext = unknown> {
10
10
  previousData?: TData;
11
11
  userContext?: TContext;
12
12
  conditionMet?: boolean;
13
+ familyRollbackData?: Array<{
14
+ queryKey: QueryKey;
15
+ previousData: unknown;
16
+ }>;
13
17
  }
14
18
  export interface MutationOptions<TData, TError, TVariables, TContext = unknown> extends UseMutationOptions<TData, TError, TVariables, TContext> {
15
19
  optimistic?: {
@@ -21,6 +25,20 @@ export interface MutationOptions<TData, TError, TVariables, TContext = unknown>
21
25
  invalidateScope?: "none" | "exact" | "family";
22
26
  familyKey?: QueryKey;
23
27
  relatedKeys?: QueryKey[];
28
+ invalidates?: QueryKey[];
29
+ };
30
+ consistency?: {
31
+ familySync?: {
32
+ idField?: string;
33
+ listSelector?: (data: unknown) => {
34
+ items: unknown[];
35
+ total?: number;
36
+ } | null;
37
+ writeBack?: (old: unknown, items: unknown[], total?: number) => unknown;
38
+ maxKeys?: number;
39
+ enableForOperations?: Array<"update" | "delete">;
40
+ };
41
+ mode?: "sync+invalidate" | "invalidate-only";
24
42
  };
25
43
  }
26
44
  //# 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,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;CACH"}
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,CAAC;IAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAAE;AAC1N,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;QACzB,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"}
@@ -1,14 +1,25 @@
1
1
  import type { QueryClient, QueryKey } from "@tanstack/react-query";
2
- export interface FamilyQueryMatchOptions {
3
- baseKey: QueryKey;
4
- maxKeys?: number;
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) => unknown[] | {
10
- items: unknown[];
6
+ listSelector?: (data: unknown) => {
7
+ items: EntityWithId[];
11
8
  total?: number;
12
9
  } | null;
13
- }): void;
10
+ writeBack?: (old: unknown, items: EntityWithId[], total?: number) => unknown;
11
+ maxKeys?: number;
12
+ enableForOperations?: Array<"update" | "delete">;
13
+ };
14
+ export declare function defaultListSelector(data: unknown): {
15
+ items: EntityWithId[];
16
+ total?: number;
17
+ } | null;
18
+ export declare function defaultWriteBack(old: unknown, items: EntityWithId[], total?: number): unknown;
19
+ export declare const DEFAULT_FAMILY_SYNC: FamilySyncConfig;
20
+ export declare function syncEntityAcrossFamily(queryClient: QueryClient, familyPrefix: QueryKey, cfg: FamilySyncConfig, operation: string, payload: Partial<EntityWithId>): void;
21
+ export declare function syncEntityAcrossFamilyOptimistic(queryClient: QueryClient, familyPrefix: QueryKey, cfg: FamilySyncConfig, operation: string, payload: Partial<EntityWithId>): Array<{
22
+ queryKey: QueryKey;
23
+ previousData: unknown;
24
+ }>;
14
25
  //# 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;AAEnE,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,QAAQ,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAiBD,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,uBAAuB,GAAG,QAAQ,EAAE,CAQxG;AAeD,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,EAAE,GAAG;QAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CA6BzO"}
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;AAC1R,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CASnG;AACD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAe7F;AACD,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;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,QAAQ,EACtB,GAAG,EAAE,gBAAgB,EACrB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAC7B,KAAK,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAAC,CA6CtD"}
@@ -1,68 +1,121 @@
1
- function isObjectEqual(a, b) {
2
- if (typeof a === "object" && a !== null && typeof b === "object" && b !== null) {
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
- return a === b;
6
- }
7
- function startsWithKey(key, prefix) {
8
- if (prefix.length > key.length)
8
+ catch {
9
+ return false;
10
+ }
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)))
9
17
  return false;
10
- for (let i = 0; i < prefix.length; i++) {
11
- if (!isObjectEqual(key[i], prefix[i]))
12
- return false;
18
+ } return true; }
19
+ export 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 };
13
30
  }
14
- return true;
31
+ return null;
15
32
  }
16
- export function findFamilyQueries(queryClient, options) {
17
- const { baseKey, maxKeys } = options;
18
- const queries = queryClient.getQueryCache().findAll({ predicate: (q) => startsWithKey(q.queryKey, baseKey) });
19
- const keys = queries.map((q) => q.queryKey);
20
- if (typeof maxKeys === "number" && maxKeys > 0) {
21
- return keys.slice(0, maxKeys);
33
+ export 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;
41
+ }
42
+ if (Array.isArray(obj.items)) {
43
+ obj.items = items;
44
+ if (typeof total !== "undefined")
45
+ obj.total = total;
46
+ return obj;
47
+ }
22
48
  }
23
- return keys;
49
+ return { items, total };
24
50
  }
25
- function updateArrayById(items, updated, idField) {
26
- const list = Array.isArray(items) ? items : [];
27
- const id = updated[idField];
28
- if (id === undefined)
29
- return list;
30
- return list.map((item) => {
31
- const currentId = item[idField];
32
- if (currentId === id) {
33
- return { ...item, ...updated };
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))
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 });
34
71
  }
35
- return item;
72
+ else if (op === "delete" && idValue !== undefined) {
73
+ items = listUpdater.remove(items, idValue);
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);
36
78
  });
37
79
  }
38
- export function syncEntityAcrossFamily(queryClient, keys, updatedEntity, options) {
39
- const idField = options.idField ?? "id";
40
- keys.forEach((key) => {
41
- const oldData = queryClient.getQueryData(key);
42
- if (Array.isArray(oldData)) {
43
- const next = updateArrayById(oldData, updatedEntity, idField);
44
- queryClient.setQueryData(key, next);
80
+ export function syncEntityAcrossFamilyOptimistic(queryClient, familyPrefix, cfg, operation, payload) {
81
+ const rollbackData = [];
82
+ const enabledOps = cfg.enableForOperations ?? ["update", "delete"];
83
+ const op = String(operation).toLowerCase();
84
+ if (!enabledOps.includes(op))
85
+ return rollbackData;
86
+ const idField = cfg.idField ?? "id";
87
+ const cache = queryClient.getQueryCache();
88
+ const queries = cache.findAll({ predicate: (q) => startsWithKeyPrefix(q.queryKey, familyPrefix) });
89
+ const limited = typeof cfg.maxKeys === "number" && cfg.maxKeys > 0 ? queries.slice(0, cfg.maxKeys) : queries;
90
+ limited.forEach((q) => {
91
+ const key = q.queryKey;
92
+ const old = queryClient.getQueryData(key);
93
+ const picked = (cfg.listSelector ?? defaultListSelector)(old);
94
+ if (!picked || !Array.isArray(picked.items))
45
95
  return;
46
- }
47
- if (oldData && typeof oldData === "object") {
48
- const selector = options.listSelector;
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
- }
96
+ const idValue = payload?.[idField];
97
+ let items = picked.items;
98
+ let shouldUpdate = false;
99
+ if (op === "update" && idValue !== undefined) {
100
+ const exists = items.some(item => item[idField] === idValue);
101
+ if (exists) {
102
+ items = listUpdater.update(items, { ...payload, id: idValue });
103
+ shouldUpdate = true;
59
104
  }
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);
105
+ }
106
+ else if (op === "delete" && idValue !== undefined) {
107
+ const exists = items.some(item => item[idField] === idValue);
108
+ if (exists) {
109
+ items = listUpdater.remove(items, idValue);
110
+ shouldUpdate = true;
65
111
  }
66
112
  }
113
+ if (shouldUpdate) {
114
+ rollbackData.push({ queryKey: key, previousData: old });
115
+ const total = typeof picked.total === "number" && op === "delete" ? Math.max(0, picked.total - 1) : picked.total;
116
+ const next = (cfg.writeBack ?? defaultWriteBack)(old, items, total);
117
+ queryClient.setQueryData(key, next);
118
+ }
67
119
  });
120
+ return rollbackData;
68
121
  }
@@ -6,4 +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 { startsWithKeyPrefix, syncEntityAcrossFamily, DEFAULT_FAMILY_SYNC, type FamilySyncConfig } from "./consistency.js";
9
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"}
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"}
@@ -6,3 +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 { 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,EAAgC,MAAM,qBAAqB,CAAC;AACrH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,eAAO,MAAM,WAAW;UAChB,CAAC,SAAS,YAAY,SAAS,CAAC,EAAE,GAAG,SAAS,WAAW,CAAC,KAAG,CAAC,EAAE;aAU7D,CAAC,SAAS,YAAY,SAAS,CAAC,EAAE,GAAG,SAAS,eAAe,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;KAAE,KAAG,CAAC,EAAE;aAI/F,CAAC,SAAS,YAAY,SAAS,CAAC,EAAE,GAAG,SAAS,UAAU,CAAC,CAAC,IAAI,CAAC,KAAG,CAAC,EAAE;CAI/E,CAAC;AACF,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,GAAG,sBAAsB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAErL;AACD,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,GAAG,sBAAsB,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAE/L;AACD,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,GAAG,sBAAsB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAE1K;AACD,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,YAAY,EAAE,UAAU,SAAS,iBAAiB,IAAI,UAAU,SAAS,iBAAiB,CAAC,GAAG,GAAG,CAAC,GAAG,UAAU,SAAS,iBAAiB,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;CAAE,GAAG,UAAU,SAAS,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;AAC7R,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,YAAY,EAAE,UAAU,SAAS,iBAAiB,GAAG,iBAAiB,EAAE,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CA2B9N;AACD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,GAAG,CAAC,EAAE,CAIzI;AACD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAIpH;AACD,wBAAgB,YAAY,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,CAM3H;AACD,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAGpK"}
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,EAAgC,MAAM,qBAAqB,CAAC;AACrH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,eAAO,MAAM,WAAW;UAChB,CAAC,SAAS,YAAY,SAAS,CAAC,EAAE,GAAG,SAAS,WAAW,CAAC,KAAG,CAAC,EAAE;aAU7D,CAAC,SAAS,YAAY,SAAS,CAAC,EAAE,GAAG,SAAS,eAAe,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;KAAE,KAAG,CAAC,EAAE;aAI/F,CAAC,SAAS,YAAY,SAAS,CAAC,EAAE,GAAG,SAAS,UAAU,CAAC,CAAC,IAAI,CAAC,KAAG,CAAC,EAAE;CAI/E,CAAC;AACF,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,GAAG,sBAAsB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAErL;AACD,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,GAAG,sBAAsB,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAE/L;AACD,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,GAAG,sBAAsB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAE1K;AACD,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,YAAY,EAAE,UAAU,SAAS,iBAAiB,IAAI,UAAU,SAAS,iBAAiB,CAAC,GAAG,GAAG,CAAC,GAAG,UAAU,SAAS,iBAAiB,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;CAAE,GAAG,UAAU,SAAS,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;AAC7R,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,YAAY,EAAE,UAAU,SAAS,iBAAiB,GAAG,iBAAiB,EAAE,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CA2B9N;AACD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,GAAG,CAAC,EAAE,CAIzI;AACD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAIpH;AACD,wBAAgB,YAAY,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,CAM3H;AACD,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAGpK;AACD,wBAAgB,6BAA6B,CAAC,CAAC,SAAS,YAAY,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAa7L"}
@@ -83,3 +83,24 @@ export function conditionalUpdateItems(items, predicate, updater) {
83
83
  return { ...item, ...updater(item) };
84
84
  } return item; });
85
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qiaopeng/tanstack-query-plus",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Enhanced TanStack Query toolkit: defaults, hooks, persistence, offline, utils",
5
5
  "author": "qiaopeng",
6
6
  "license": "MIT",