@qiaopeng/tanstack-query-plus 0.5.9 → 0.5.10
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 +86 -55
- package/dist/{types/base.d.ts → base-CHnwqfyz.d.cts} +12 -14
- package/dist/base-CHnwqfyz.d.ts +52 -0
- package/dist/chunk-52ZO6Y67.cjs +1121 -0
- package/dist/chunk-52ZO6Y67.cjs.map +1 -0
- package/dist/chunk-5J6OXSLW.cjs +36 -0
- package/dist/chunk-5J6OXSLW.cjs.map +1 -0
- package/dist/chunk-6MAYHLTE.cjs +310 -0
- package/dist/chunk-6MAYHLTE.cjs.map +1 -0
- package/dist/chunk-ADS2QTMP.js +144 -0
- package/dist/chunk-ADS2QTMP.js.map +1 -0
- package/dist/chunk-APXNNHBD.cjs +374 -0
- package/dist/chunk-APXNNHBD.cjs.map +1 -0
- package/dist/chunk-AXMWOGNX.js +134 -0
- package/dist/chunk-AXMWOGNX.js.map +1 -0
- package/dist/chunk-B4KO3K3E.cjs +521 -0
- package/dist/chunk-B4KO3K3E.cjs.map +1 -0
- package/dist/chunk-BK3OTIBD.cjs +15 -0
- package/dist/chunk-BK3OTIBD.cjs.map +1 -0
- package/dist/chunk-BYAOQALW.js +13 -0
- package/dist/chunk-BYAOQALW.js.map +1 -0
- package/dist/chunk-CRTVS7VI.cjs +162 -0
- package/dist/chunk-CRTVS7VI.cjs.map +1 -0
- package/dist/chunk-EXITP7QO.js +288 -0
- package/dist/chunk-EXITP7QO.js.map +1 -0
- package/dist/chunk-GMO3PRZZ.js +565 -0
- package/dist/chunk-GMO3PRZZ.js.map +1 -0
- package/dist/chunk-HRO2DWKZ.js +12 -0
- package/dist/chunk-HRO2DWKZ.js.map +1 -0
- package/dist/chunk-JHDKUQSB.js +1069 -0
- package/dist/chunk-JHDKUQSB.js.map +1 -0
- package/dist/chunk-JN2Y6RSY.js +23 -0
- package/dist/chunk-JN2Y6RSY.js.map +1 -0
- package/dist/chunk-JRJSKRZW.cjs +29 -0
- package/dist/chunk-JRJSKRZW.cjs.map +1 -0
- package/dist/chunk-KC62H4VJ.js +123 -0
- package/dist/chunk-KC62H4VJ.js.map +1 -0
- package/dist/chunk-LHEHSLD5.js +31 -0
- package/dist/chunk-LHEHSLD5.js.map +1 -0
- package/dist/chunk-N4264P7N.cjs +156 -0
- package/dist/chunk-N4264P7N.cjs.map +1 -0
- package/dist/chunk-NF5QYPYC.cjs +133 -0
- package/dist/chunk-NF5QYPYC.cjs.map +1 -0
- package/dist/chunk-OFLCHKKE.cjs +28 -0
- package/dist/chunk-OFLCHKKE.cjs.map +1 -0
- package/dist/chunk-PCNSWVA5.cjs +602 -0
- package/dist/chunk-PCNSWVA5.cjs.map +1 -0
- package/dist/chunk-STOMAA2X.js +85 -0
- package/dist/chunk-STOMAA2X.js.map +1 -0
- package/dist/chunk-UVF5S6LX.cjs +15 -0
- package/dist/chunk-UVF5S6LX.cjs.map +1 -0
- package/dist/chunk-WEIXCDCA.cjs +90 -0
- package/dist/chunk-WEIXCDCA.cjs.map +1 -0
- package/dist/chunk-X3ZTSLBQ.js +355 -0
- package/dist/chunk-X3ZTSLBQ.js.map +1 -0
- package/dist/chunk-YEV73J4J.js +504 -0
- package/dist/chunk-YEV73J4J.js.map +1 -0
- package/dist/chunk-YW5PNTRU.cjs +14 -0
- package/dist/chunk-YW5PNTRU.cjs.map +1 -0
- package/dist/chunk-ZNXSWUIS.js +12 -0
- package/dist/chunk-ZNXSWUIS.js.map +1 -0
- package/dist/chunk-ZUEMBY4W.js +21 -0
- package/dist/chunk-ZUEMBY4W.js.map +1 -0
- package/dist/components/index.cjs +60 -0
- package/dist/components/index.cjs.map +1 -0
- package/dist/components/index.d.cts +43 -0
- package/dist/components/index.d.ts +43 -4
- package/dist/components/index.js +3 -4
- package/dist/components/index.js.map +1 -0
- package/dist/core/devtools.cjs +25 -0
- package/dist/core/devtools.cjs.map +1 -0
- package/dist/core/devtools.d.cts +17 -0
- package/dist/core/devtools.d.ts +9 -7
- package/dist/core/devtools.js +4 -16
- package/dist/core/devtools.js.map +1 -0
- package/dist/core/index.cjs +220 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +196 -0
- package/dist/core/index.d.ts +196 -9
- package/dist/core/index.js +7 -8
- package/dist/core/index.js.map +1 -0
- package/dist/features/index.cjs +76 -0
- package/dist/features/index.cjs.map +1 -0
- package/dist/features/index.d.cts +86 -0
- package/dist/features/index.d.ts +86 -4
- package/dist/features/index.js +7 -3
- package/dist/features/index.js.map +1 -0
- package/dist/hooks/index.cjs +209 -0
- package/dist/hooks/index.cjs.map +1 -0
- package/dist/hooks/index.d.cts +377 -0
- package/dist/hooks/index.d.ts +377 -10
- package/dist/hooks/index.js +8 -9
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useInViewPrefetch.cjs +33 -0
- package/dist/hooks/useInViewPrefetch.cjs.map +1 -0
- package/dist/hooks/useInViewPrefetch.d.cts +12 -0
- package/dist/hooks/useInViewPrefetch.d.ts +6 -4
- package/dist/hooks/useInViewPrefetch.js +30 -20
- package/dist/hooks/useInViewPrefetch.js.map +1 -0
- package/dist/index.cjs +811 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +36 -0
- package/dist/index.d.ts +36 -8
- package/dist/index.js +89 -7
- package/dist/index.js.map +1 -0
- package/dist/{types/offline.d.ts → offline-DVPtgoAS.d.ts} +15 -13
- package/dist/offline-xxeA_-6V.d.cts +99 -0
- package/dist/persistence-MRtkmhqq.d.cts +216 -0
- package/dist/persistence-tIrEb0pR.d.ts +216 -0
- package/dist/react-query/index.cjs +52 -0
- package/dist/react-query/index.cjs.map +1 -0
- package/dist/react-query/index.d.cts +1 -0
- package/dist/react-query/index.d.ts +1 -3
- package/dist/react-query/index.js +3 -1
- package/dist/react-query/index.js.map +1 -0
- package/dist/types/index.cjs +43 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +157 -0
- package/dist/types/index.d.ts +116 -12
- package/dist/types/index.js +6 -8
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.cjs +234 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +272 -0
- package/dist/utils/index.d.ts +272 -10
- package/dist/utils/index.js +9 -9
- package/dist/utils/index.js.map +1 -0
- package/package.json +13 -3
- package/dist/PersistQueryClientProvider.d.ts +0 -22
- package/dist/PersistQueryClientProvider.d.ts.map +0 -1
- package/dist/PersistQueryClientProvider.js +0 -57
- package/dist/components/LoadingFallback.d.ts +0 -16
- package/dist/components/LoadingFallback.d.ts.map +0 -1
- package/dist/components/LoadingFallback.js +0 -27
- package/dist/components/QueryErrorBoundary.d.ts +0 -12
- package/dist/components/QueryErrorBoundary.d.ts.map +0 -1
- package/dist/components/QueryErrorBoundary.js +0 -9
- package/dist/components/SuspenseWrapper.d.ts +0 -14
- package/dist/components/SuspenseWrapper.d.ts.map +0 -1
- package/dist/components/SuspenseWrapper.js +0 -9
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/internal/ErrorBoundary.d.ts +0 -27
- package/dist/components/internal/ErrorBoundary.d.ts.map +0 -1
- package/dist/components/internal/ErrorBoundary.js +0 -37
- package/dist/core/config.d.ts +0 -80
- package/dist/core/config.d.ts.map +0 -1
- package/dist/core/config.js +0 -327
- package/dist/core/devtools.d.ts.map +0 -1
- package/dist/core/env.d.ts +0 -4
- package/dist/core/env.d.ts.map +0 -1
- package/dist/core/env.js +0 -26
- package/dist/core/focusManager.d.ts +0 -33
- package/dist/core/focusManager.d.ts.map +0 -1
- package/dist/core/focusManager.js +0 -122
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/keys.d.ts +0 -59
- package/dist/core/keys.d.ts.map +0 -1
- package/dist/core/keys.js +0 -107
- package/dist/core/queryOptions.d.ts +0 -19
- package/dist/core/queryOptions.d.ts.map +0 -1
- package/dist/core/queryOptions.js +0 -32
- package/dist/features/index.d.ts.map +0 -1
- package/dist/features/offline.d.ts +0 -49
- package/dist/features/offline.d.ts.map +0 -1
- package/dist/features/offline.js +0 -300
- package/dist/features/persistence.d.ts +0 -36
- package/dist/features/persistence.d.ts.map +0 -1
- package/dist/features/persistence.js +0 -187
- package/dist/hooks/batchQueries.d.ts +0 -129
- package/dist/hooks/batchQueries.d.ts.map +0 -1
- package/dist/hooks/batchQueries.js +0 -301
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/useDataGuardMutation.d.ts +0 -39
- package/dist/hooks/useDataGuardMutation.d.ts.map +0 -1
- package/dist/hooks/useDataGuardMutation.js +0 -137
- package/dist/hooks/useDataGuardQuery.d.ts +0 -28
- package/dist/hooks/useDataGuardQuery.d.ts.map +0 -1
- package/dist/hooks/useDataGuardQuery.js +0 -71
- package/dist/hooks/useFocusManager.d.ts +0 -41
- package/dist/hooks/useFocusManager.d.ts.map +0 -1
- package/dist/hooks/useFocusManager.js +0 -109
- package/dist/hooks/useInViewPrefetch.d.ts.map +0 -1
- package/dist/hooks/useInfiniteQuery.d.ts +0 -33
- package/dist/hooks/useInfiniteQuery.d.ts.map +0 -1
- package/dist/hooks/useInfiniteQuery.js +0 -61
- package/dist/hooks/useMutation.d.ts +0 -25
- package/dist/hooks/useMutation.d.ts.map +0 -1
- package/dist/hooks/useMutation.js +0 -180
- package/dist/hooks/usePrefetch.d.ts +0 -54
- package/dist/hooks/usePrefetch.d.ts.map +0 -1
- package/dist/hooks/usePrefetch.js +0 -229
- package/dist/hooks/useQuery.d.ts +0 -21
- package/dist/hooks/useQuery.d.ts.map +0 -1
- package/dist/hooks/useQuery.js +0 -46
- package/dist/hooks/useSuspenseQuery.d.ts +0 -11
- package/dist/hooks/useSuspenseQuery.d.ts.map +0 -1
- package/dist/hooks/useSuspenseQuery.js +0 -19
- package/dist/index.d.ts.map +0 -1
- package/dist/react-query/index.d.ts.map +0 -1
- package/dist/types/base.d.ts.map +0 -1
- package/dist/types/base.js +0 -26
- package/dist/types/dataGuard.d.ts +0 -69
- package/dist/types/dataGuard.d.ts.map +0 -1
- package/dist/types/dataGuard.js +0 -10
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/infinite.d.ts +0 -39
- package/dist/types/infinite.d.ts.map +0 -1
- package/dist/types/infinite.js +0 -1
- package/dist/types/offline.d.ts.map +0 -1
- package/dist/types/offline.js +0 -8
- package/dist/types/optimistic.d.ts +0 -126
- package/dist/types/optimistic.d.ts.map +0 -1
- package/dist/types/optimistic.js +0 -7
- package/dist/types/persistence.d.ts +0 -9
- package/dist/types/persistence.d.ts.map +0 -1
- package/dist/types/persistence.js +0 -1
- package/dist/types/selectors.d.ts +0 -11
- package/dist/types/selectors.d.ts.map +0 -1
- package/dist/types/selectors.js +0 -1
- package/dist/types/suspense.d.ts +0 -67
- package/dist/types/suspense.d.ts.map +0 -1
- package/dist/types/suspense.js +0 -1
- package/dist/utils/dataGuard.d.ts +0 -37
- package/dist/utils/dataGuard.d.ts.map +0 -1
- package/dist/utils/dataGuard.js +0 -251
- package/dist/utils/fieldMapper.d.ts +0 -9
- package/dist/utils/fieldMapper.d.ts.map +0 -1
- package/dist/utils/fieldMapper.js +0 -27
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/network.d.ts +0 -9
- package/dist/utils/network.d.ts.map +0 -1
- package/dist/utils/network.js +0 -43
- package/dist/utils/optimisticUtils.d.ts +0 -45
- package/dist/utils/optimisticUtils.d.ts.map +0 -1
- package/dist/utils/optimisticUtils.js +0 -116
- package/dist/utils/placeholderData.d.ts +0 -3
- package/dist/utils/placeholderData.d.ts.map +0 -1
- package/dist/utils/placeholderData.js +0 -28
- package/dist/utils/prefetchManager.d.ts +0 -111
- package/dist/utils/prefetchManager.d.ts.map +0 -1
- package/dist/utils/prefetchManager.js +0 -246
- package/dist/utils/queryKey.d.ts +0 -26
- package/dist/utils/queryKey.d.ts.map +0 -1
- package/dist/utils/queryKey.js +0 -89
- package/dist/utils/selectors.d.ts +0 -30
- package/dist/utils/selectors.d.ts.map +0 -1
- package/dist/utils/selectors.js +0 -18
- package/dist/utils/storage.d.ts +0 -7
- package/dist/utils/storage.d.ts.map +0 -1
- package/dist/utils/storage.js +0 -84
package/dist/utils/dataGuard.js
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import { startsWithKeyPrefix } from "./queryKey.js";
|
|
2
|
-
/**
|
|
3
|
-
* 简单的字符串哈希函数(DJB2算法变体)
|
|
4
|
-
*/
|
|
5
|
-
function simpleHash(str) {
|
|
6
|
-
let hash = 0;
|
|
7
|
-
for (let i = 0; i < str.length; i++) {
|
|
8
|
-
const char = str.charCodeAt(i);
|
|
9
|
-
hash = ((hash << 5) - hash) + char;
|
|
10
|
-
hash = hash | 0; // 转换为32位整数
|
|
11
|
-
}
|
|
12
|
-
return Math.abs(hash).toString(36);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* 对象键排序(确保一致的哈希值)
|
|
16
|
-
*/
|
|
17
|
-
function sortObjectKeys(obj) {
|
|
18
|
-
if (obj === null || obj === undefined)
|
|
19
|
-
return obj;
|
|
20
|
-
if (typeof obj !== 'object')
|
|
21
|
-
return obj;
|
|
22
|
-
if (Array.isArray(obj))
|
|
23
|
-
return obj.map(sortObjectKeys);
|
|
24
|
-
const sorted = {};
|
|
25
|
-
Object.keys(obj).sort().forEach(key => {
|
|
26
|
-
sorted[key] = sortObjectKeys(obj[key]);
|
|
27
|
-
});
|
|
28
|
-
return sorted;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* 计算对象的哈希值(键排序后计算,确保一致性)
|
|
32
|
-
*/
|
|
33
|
-
export function hashObject(obj) {
|
|
34
|
-
try {
|
|
35
|
-
const sorted = sortObjectKeys(obj);
|
|
36
|
-
return simpleHash(JSON.stringify(sorted));
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return simpleHash(String(obj));
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* 自适应数据防护:根据数据特征自动选择最佳防护策略
|
|
44
|
-
*
|
|
45
|
-
* 策略优先级:
|
|
46
|
-
* 1. version(版本号)- 最可靠
|
|
47
|
-
* 2. updatedAt(时间戳)- 次优
|
|
48
|
-
* 3. hash(内容哈希)- 兜底
|
|
49
|
-
*/
|
|
50
|
-
export function applyDataGuard(newData, cached, queryKey, options = {}) {
|
|
51
|
-
const { maxDataAge = 10000, enableVersionCheck = true, enableTimestampCheck = true, enableHashCheck = true } = options;
|
|
52
|
-
// 如果没有缓存,接受新数据
|
|
53
|
-
if (!cached) {
|
|
54
|
-
return {
|
|
55
|
-
shouldReject: false,
|
|
56
|
-
reason: "No cached data",
|
|
57
|
-
strategy: "none",
|
|
58
|
-
guardDetails: {}
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
let shouldReject = false;
|
|
62
|
-
let reason = "";
|
|
63
|
-
let strategy = "none";
|
|
64
|
-
let guardDetails = {};
|
|
65
|
-
// ============================================
|
|
66
|
-
// 策略1:版本号比较(最可靠)
|
|
67
|
-
// ============================================
|
|
68
|
-
if (enableVersionCheck && cached.version !== undefined && newData.version !== undefined) {
|
|
69
|
-
strategy = "version";
|
|
70
|
-
if (newData.version < cached.version) {
|
|
71
|
-
shouldReject = true;
|
|
72
|
-
reason = `版本号回退:缓存版本 ${cached.version} > 新数据版本 ${newData.version}`;
|
|
73
|
-
guardDetails = {
|
|
74
|
-
cachedVersion: cached.version,
|
|
75
|
-
newVersion: newData.version,
|
|
76
|
-
diff: cached.version - newData.version
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
else if (newData.version === cached.version) {
|
|
80
|
-
guardDetails = {
|
|
81
|
-
version: newData.version,
|
|
82
|
-
status: "identical"
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
guardDetails = {
|
|
87
|
-
cachedVersion: cached.version,
|
|
88
|
-
newVersion: newData.version,
|
|
89
|
-
status: "updated"
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// ============================================
|
|
94
|
-
// 策略2:时间戳比较(次优)
|
|
95
|
-
// ============================================
|
|
96
|
-
else if (enableTimestampCheck && cached.updatedAt && newData.updatedAt) {
|
|
97
|
-
strategy = "timestamp";
|
|
98
|
-
try {
|
|
99
|
-
const cachedTime = new Date(cached.updatedAt).getTime();
|
|
100
|
-
const newTime = new Date(newData.updatedAt).getTime();
|
|
101
|
-
const timeDiff = cachedTime - newTime;
|
|
102
|
-
const dataAge = Date.now() - newTime;
|
|
103
|
-
guardDetails = {
|
|
104
|
-
cachedTime: cached.updatedAt,
|
|
105
|
-
newTime: newData.updatedAt,
|
|
106
|
-
timeDiff,
|
|
107
|
-
dataAge
|
|
108
|
-
};
|
|
109
|
-
// 新数据的时间戳更旧
|
|
110
|
-
if (newTime < cachedTime) {
|
|
111
|
-
// 如果数据年龄超过阈值,拒绝
|
|
112
|
-
if (dataAge > maxDataAge) {
|
|
113
|
-
shouldReject = true;
|
|
114
|
-
reason = `时间戳过期:新数据时间 ${newData.updatedAt} 早于缓存 ${cached.updatedAt},且数据年龄 ${dataAge}ms 超过阈值 ${maxDataAge}ms`;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
// 数据年龄在可接受范围内,记录警告但接受
|
|
118
|
-
guardDetails.warning = `时间戳略旧但在可接受范围内(${dataAge}ms < ${maxDataAge}ms)`;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
guardDetails.error = `时间戳解析失败: ${error}`;
|
|
124
|
-
// 时间戳解析失败,不使用时间戳策略
|
|
125
|
-
// 将在下一个 else if 中尝试 hash 策略
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
// ============================================
|
|
129
|
-
// 策略3:内容哈希比较(兜底)
|
|
130
|
-
// ============================================
|
|
131
|
-
else if (enableHashCheck) {
|
|
132
|
-
strategy = "hash";
|
|
133
|
-
const newHash = hashObject(newData.items);
|
|
134
|
-
const cachedHash = cached._hash;
|
|
135
|
-
guardDetails = {
|
|
136
|
-
cachedHash,
|
|
137
|
-
newHash,
|
|
138
|
-
identical: cachedHash === newHash
|
|
139
|
-
};
|
|
140
|
-
if (cachedHash && cachedHash === newHash) {
|
|
141
|
-
// 内容完全相同,不需要更新
|
|
142
|
-
shouldReject = true;
|
|
143
|
-
reason = "内容哈希相同,数据未变化";
|
|
144
|
-
}
|
|
145
|
-
else if (cachedHash &&
|
|
146
|
-
cached._recentlyUpdatedIds &&
|
|
147
|
-
(Array.isArray(cached._recentlyUpdatedIds)
|
|
148
|
-
? cached._recentlyUpdatedIds.length > 0
|
|
149
|
-
: cached._recentlyUpdatedIds.size > 0)) {
|
|
150
|
-
// 检查最近更新的项是否被回退
|
|
151
|
-
let hasRevert = false;
|
|
152
|
-
for (const id of cached._recentlyUpdatedIds) {
|
|
153
|
-
const cachedItem = cached.items.find(item => item.id === id);
|
|
154
|
-
const newItem = newData.items.find(item => item.id === id);
|
|
155
|
-
if (cachedItem && newItem) {
|
|
156
|
-
const cachedItemHash = hashObject(cachedItem);
|
|
157
|
-
const newItemHash = hashObject(newItem);
|
|
158
|
-
if (cachedItemHash !== newItemHash) {
|
|
159
|
-
// 简单启发式:如果缓存项有更多字段,可能是新的
|
|
160
|
-
if (Object.keys(cachedItem).length > Object.keys(newItem).length) {
|
|
161
|
-
hasRevert = true;
|
|
162
|
-
guardDetails.revertedItem = { id, cachedItem, newItem };
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (hasRevert) {
|
|
169
|
-
shouldReject = true;
|
|
170
|
-
reason = "检测到最近更新的项可能被回退";
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return {
|
|
175
|
-
shouldReject,
|
|
176
|
-
reason,
|
|
177
|
-
strategy,
|
|
178
|
-
guardDetails
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* 为查询数据添加哈希标记
|
|
183
|
-
*/
|
|
184
|
-
export function addHashToData(data) {
|
|
185
|
-
return {
|
|
186
|
-
...data,
|
|
187
|
-
_hash: hashObject(data.items)
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* 标记最近更新的项
|
|
192
|
-
*/
|
|
193
|
-
export function markRecentlyUpdated(data, updatedId) {
|
|
194
|
-
const existing = data._recentlyUpdatedIds
|
|
195
|
-
? (Array.isArray(data._recentlyUpdatedIds) ? [...data._recentlyUpdatedIds] : Array.from(data._recentlyUpdatedIds))
|
|
196
|
-
: [];
|
|
197
|
-
if (!existing.includes(updatedId)) {
|
|
198
|
-
existing.push(updatedId);
|
|
199
|
-
}
|
|
200
|
-
return {
|
|
201
|
-
...data,
|
|
202
|
-
_recentlyUpdatedIds: existing
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* 清理最近更新的标记
|
|
207
|
-
*/
|
|
208
|
-
export function clearRecentlyUpdated(data, updatedId) {
|
|
209
|
-
if (!data._recentlyUpdatedIds)
|
|
210
|
-
return data;
|
|
211
|
-
const existing = Array.isArray(data._recentlyUpdatedIds) ? data._recentlyUpdatedIds : Array.from(data._recentlyUpdatedIds);
|
|
212
|
-
const remaining = existing.filter((id) => id !== updatedId);
|
|
213
|
-
return {
|
|
214
|
-
...data,
|
|
215
|
-
_recentlyUpdatedIds: remaining.length > 0 ? remaining : undefined
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* 更新所有家族缓存的元数据(版本号、时间戳、哈希)
|
|
220
|
-
*/
|
|
221
|
-
export function updateFamilyMetadata(queryClient, familyKey, response) {
|
|
222
|
-
const cache = queryClient.getQueryCache();
|
|
223
|
-
const queries = cache.findAll({
|
|
224
|
-
predicate: (q) => startsWithKeyPrefix(q.queryKey, familyKey)
|
|
225
|
-
});
|
|
226
|
-
queries.forEach((q) => {
|
|
227
|
-
const old = queryClient.getQueryData(q.queryKey);
|
|
228
|
-
if (old) {
|
|
229
|
-
const updated = { ...old };
|
|
230
|
-
// 更新版本号
|
|
231
|
-
if (response.version !== undefined) {
|
|
232
|
-
updated.version = response.version;
|
|
233
|
-
}
|
|
234
|
-
else if (old.version !== undefined) {
|
|
235
|
-
updated.version = old.version + 1;
|
|
236
|
-
}
|
|
237
|
-
// 更新时间戳
|
|
238
|
-
if (response.updatedAt) {
|
|
239
|
-
updated.updatedAt = response.updatedAt;
|
|
240
|
-
}
|
|
241
|
-
else if (old.updatedAt !== undefined) {
|
|
242
|
-
updated.updatedAt = new Date().toISOString();
|
|
243
|
-
}
|
|
244
|
-
// 更新哈希(安全检查:确保 items 存在)
|
|
245
|
-
if (old._hash !== undefined && updated.items) {
|
|
246
|
-
updated._hash = hashObject(updated.items);
|
|
247
|
-
}
|
|
248
|
-
queryClient.setQueryData(q.queryKey, updated);
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { QueryClient } from "@tanstack/react-query";
|
|
2
|
-
export interface FieldMappingConfig {
|
|
3
|
-
nameField: string;
|
|
4
|
-
configKey: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function createFieldEnricher<T = any>(queryKey: any, mappings: Record<string, FieldMappingConfig>): (data: T, queryClient: QueryClient) => T;
|
|
7
|
-
export declare function createTempId(prefix?: string): string;
|
|
8
|
-
export declare function createOptimisticBase(customFields?: Record<string, any>): Record<string, any>;
|
|
9
|
-
//# sourceMappingURL=fieldMapper.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fieldMapper.d.ts","sourceRoot":"","sources":["../../src/utils/fieldMapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,MAAM,WAAW,kBAAkB;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC5E,wBAAgB,mBAAmB,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,IAC9F,MAAM,CAAC,EAAE,aAAa,WAAW,KAAG,CAAC,CAe9C;AACD,wBAAgB,YAAY,CAAC,MAAM,SAAS,GAAG,MAAM,CAAgF;AACrI,wBAAgB,oBAAoB,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAG5F"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export function createFieldEnricher(queryKey, mappings) {
|
|
2
|
-
return (data, queryClient) => {
|
|
3
|
-
const config = queryClient.getQueryData(queryKey);
|
|
4
|
-
if (!config)
|
|
5
|
-
return data;
|
|
6
|
-
const result = { ...data };
|
|
7
|
-
Object.entries(mappings).forEach(([idField, { nameField, configKey }]) => {
|
|
8
|
-
const idValue = data[idField];
|
|
9
|
-
if (idValue == null)
|
|
10
|
-
return;
|
|
11
|
-
const options = config[configKey];
|
|
12
|
-
if (!options?.length)
|
|
13
|
-
return;
|
|
14
|
-
const optionMap = new Map(options.map((item) => [String(item.value), item.label]));
|
|
15
|
-
const label = optionMap.get(String(idValue));
|
|
16
|
-
if (label) {
|
|
17
|
-
result[nameField] = label;
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
return result;
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
export function createTempId(prefix = "temp") { return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`; }
|
|
24
|
-
export function createOptimisticBase(customFields) {
|
|
25
|
-
const now = new Date().toISOString();
|
|
26
|
-
return { createTime: now, updateTime: now, createUser: "", updateUser: "", deleteStatus: 0, ...customFields };
|
|
27
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
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,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,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,mBAAmB,EAAE,KAAK,eAAe,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC7O,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,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/utils/network.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { NetworkInformation } from "../types/base";
|
|
2
|
-
export interface NavigatorWithConnection extends Navigator {
|
|
3
|
-
connection?: NetworkInformation;
|
|
4
|
-
}
|
|
5
|
-
export declare function isSlowNetwork(): boolean;
|
|
6
|
-
export declare function getNetworkInfo(): NetworkInformation | null;
|
|
7
|
-
export declare function isFastNetwork(): boolean;
|
|
8
|
-
export declare function getNetworkSpeed(): "fast" | "medium" | "slow" | "unknown";
|
|
9
|
-
//# sourceMappingURL=network.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/utils/network.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,MAAM,WAAW,uBAAwB,SAAQ,SAAS;IAAG,UAAU,CAAC,EAAE,kBAAkB,CAAA;CAAE;AAE9F,wBAAgB,aAAa,IAAI,OAAO,CAMvC;AACD,wBAAgB,cAAc,IAAI,kBAAkB,GAAG,IAAI,CAI1D;AACD,wBAAgB,aAAa,IAAI,OAAO,CAIvC;AACD,wBAAgB,eAAe,IAAI,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAUxE"}
|
package/dist/utils/network.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
function hasConnectionAPI(nav) { return "connection" in nav; }
|
|
2
|
-
export function isSlowNetwork() {
|
|
3
|
-
if (typeof navigator === "undefined") {
|
|
4
|
-
return false;
|
|
5
|
-
}
|
|
6
|
-
if (!hasConnectionAPI(navigator)) {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
const connection = navigator.connection;
|
|
10
|
-
if (!connection) {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
return connection.effectiveType === "slow-2g" || connection.effectiveType === "2g" || connection.saveData === true;
|
|
14
|
-
}
|
|
15
|
-
export function getNetworkInfo() {
|
|
16
|
-
if (typeof navigator === "undefined") {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
if (!hasConnectionAPI(navigator)) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
return navigator.connection || null;
|
|
23
|
-
}
|
|
24
|
-
export function isFastNetwork() {
|
|
25
|
-
const networkInfo = getNetworkInfo();
|
|
26
|
-
if (!networkInfo) {
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
return networkInfo.effectiveType === "4g" && networkInfo.saveData !== true;
|
|
30
|
-
}
|
|
31
|
-
export function getNetworkSpeed() {
|
|
32
|
-
const networkInfo = getNetworkInfo();
|
|
33
|
-
if (!networkInfo || !networkInfo.effectiveType) {
|
|
34
|
-
return "unknown";
|
|
35
|
-
}
|
|
36
|
-
switch (networkInfo.effectiveType) {
|
|
37
|
-
case "4g": return "fast";
|
|
38
|
-
case "3g": return "medium";
|
|
39
|
-
case "2g":
|
|
40
|
-
case "slow-2g": return "slow";
|
|
41
|
-
default: return "unknown";
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { QueryKey } from "@tanstack/react-query";
|
|
2
|
-
import type { ListOperationConfig, OptimisticUpdateConfig } from "../types/optimistic";
|
|
3
|
-
import type { EntityWithId } from "../types/selectors";
|
|
4
|
-
import { ListOperationType } from "../types/optimistic.js";
|
|
5
|
-
/**
|
|
6
|
-
* Loose equality check for IDs (string vs number)
|
|
7
|
-
*/
|
|
8
|
-
export declare function idsAreEqual(a: unknown, b: unknown): boolean;
|
|
9
|
-
export declare const listUpdater: {
|
|
10
|
-
add: <T extends EntityWithId>(items: T[] | undefined, newItem: T) => T[];
|
|
11
|
-
update: <T extends EntityWithId>(items: T[] | undefined, updatedItem: Partial<T> & {
|
|
12
|
-
id: T["id"];
|
|
13
|
-
}) => T[];
|
|
14
|
-
remove: <T extends EntityWithId>(items: T[] | undefined, itemId: T["id"]) => T[];
|
|
15
|
-
};
|
|
16
|
-
export declare function createAddItemConfig<T extends EntityWithId>(queryKey: QueryKey, options?: {
|
|
17
|
-
addToTop?: boolean;
|
|
18
|
-
onRollback?: (error: Error) => void;
|
|
19
|
-
}): OptimisticUpdateConfig<T[], T>;
|
|
20
|
-
export declare function createUpdateItemConfig<T extends EntityWithId>(queryKey: QueryKey, options?: {
|
|
21
|
-
onRollback?: (error: Error) => void;
|
|
22
|
-
}): OptimisticUpdateConfig<T[], Partial<T> & {
|
|
23
|
-
id: T["id"];
|
|
24
|
-
}>;
|
|
25
|
-
export declare function createRemoveItemConfig<T extends EntityWithId>(queryKey: QueryKey, options?: {
|
|
26
|
-
onRollback?: (error: Error) => void;
|
|
27
|
-
}): OptimisticUpdateConfig<T[], T["id"]>;
|
|
28
|
-
export type ListOperationVariables<T extends EntityWithId, TOperation extends ListOperationType> = TOperation extends ListOperationType.ADD ? T : TOperation extends ListOperationType.UPDATE ? Partial<T> & {
|
|
29
|
-
id: T["id"];
|
|
30
|
-
} : TOperation extends ListOperationType.REMOVE ? T["id"] : never;
|
|
31
|
-
export declare function createListOperationConfig<T extends EntityWithId, TOperation extends ListOperationType = ListOperationType>(config: ListOperationConfig<T>): OptimisticUpdateConfig<T[], ListOperationVariables<T, TOperation>>;
|
|
32
|
-
export declare function batchUpdateItems<T extends EntityWithId>(items: T[] | undefined | null, updates: Array<Partial<T> & {
|
|
33
|
-
id: T["id"];
|
|
34
|
-
}>): T[];
|
|
35
|
-
export declare function batchRemoveItems<T extends EntityWithId>(items: T[] | undefined | null, itemIds: Array<T["id"]>): T[];
|
|
36
|
-
export declare function reorderItems<T extends EntityWithId>(items: T[] | undefined | null, fromIndex: number, toIndex: number): T[];
|
|
37
|
-
export declare function conditionalUpdateItems<T extends EntityWithId>(items: T[] | undefined | null, predicate: (item: T) => boolean, updater: (item: T) => Partial<T>): T[];
|
|
38
|
-
export declare function applyListOperationToPaginated<T extends EntityWithId>(data: {
|
|
39
|
-
items: T[];
|
|
40
|
-
total?: number;
|
|
41
|
-
}, operation: ListOperationType, payload: Partial<T>): {
|
|
42
|
-
items: T[];
|
|
43
|
-
total?: number;
|
|
44
|
-
};
|
|
45
|
-
//# sourceMappingURL=optimisticUtils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"optimisticUtils.d.ts","sourceRoot":"","sources":["../../src/utils/optimisticUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { ListOperationType } from "../types/optimistic.js";
|
|
2
|
-
/**
|
|
3
|
-
* Loose equality check for IDs (string vs number)
|
|
4
|
-
*/
|
|
5
|
-
export function idsAreEqual(a, b) {
|
|
6
|
-
if (a === b)
|
|
7
|
-
return true;
|
|
8
|
-
if (a === undefined || a === null || b === undefined || b === null)
|
|
9
|
-
return false;
|
|
10
|
-
return String(a) === String(b);
|
|
11
|
-
}
|
|
12
|
-
export const listUpdater = {
|
|
13
|
-
add: (items, newItem) => {
|
|
14
|
-
const currentItems = items || [];
|
|
15
|
-
const existingIndex = currentItems.findIndex((item) => idsAreEqual(item.id, newItem.id));
|
|
16
|
-
if (existingIndex >= 0) {
|
|
17
|
-
const updatedItems = [...currentItems];
|
|
18
|
-
updatedItems[existingIndex] = newItem;
|
|
19
|
-
return updatedItems;
|
|
20
|
-
}
|
|
21
|
-
return [newItem, ...currentItems];
|
|
22
|
-
},
|
|
23
|
-
update: (items, updatedItem) => {
|
|
24
|
-
const currentItems = items || [];
|
|
25
|
-
return currentItems.map((item) => (idsAreEqual(item.id, updatedItem.id) ? { ...item, ...updatedItem } : item));
|
|
26
|
-
},
|
|
27
|
-
remove: (items, itemId) => {
|
|
28
|
-
const currentItems = items || [];
|
|
29
|
-
return currentItems.filter((item) => !idsAreEqual(item.id, itemId));
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
export function createAddItemConfig(queryKey, options) {
|
|
33
|
-
return { queryKey, updater: (oldData, newItem) => { const currentItems = oldData || []; if (options?.addToTop !== false) {
|
|
34
|
-
return [newItem, ...currentItems];
|
|
35
|
-
} return [...currentItems, newItem]; }, rollback: options?.onRollback ? (_previousData, error) => { options.onRollback(error); } : undefined, enabled: true };
|
|
36
|
-
}
|
|
37
|
-
export function createUpdateItemConfig(queryKey, options) {
|
|
38
|
-
return { queryKey, updater: (oldData, updatedItem) => { return listUpdater.update(oldData, updatedItem); }, rollback: options?.onRollback ? (_previousData, error) => { options.onRollback(error); } : undefined, enabled: true };
|
|
39
|
-
}
|
|
40
|
-
export function createRemoveItemConfig(queryKey, options) {
|
|
41
|
-
return { queryKey, updater: (oldData, itemId) => { return listUpdater.remove(oldData, itemId); }, rollback: options?.onRollback ? (_previousData, error) => { options.onRollback(error); } : undefined, enabled: true };
|
|
42
|
-
}
|
|
43
|
-
export function createListOperationConfig(config) {
|
|
44
|
-
return {
|
|
45
|
-
queryKey: config.queryKey,
|
|
46
|
-
updater: (oldData, variables) => {
|
|
47
|
-
switch (config.operation) {
|
|
48
|
-
case ListOperationType.ADD:
|
|
49
|
-
return listUpdater.add(oldData, variables);
|
|
50
|
-
case ListOperationType.UPDATE:
|
|
51
|
-
return listUpdater.update(oldData, variables);
|
|
52
|
-
case ListOperationType.REMOVE:
|
|
53
|
-
return listUpdater.remove(oldData, variables);
|
|
54
|
-
default:
|
|
55
|
-
return oldData || [];
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
rollback: config.onRollback
|
|
59
|
-
? (previousData, error) => {
|
|
60
|
-
const opType = config.operation === ListOperationType.ADD
|
|
61
|
-
? "create"
|
|
62
|
-
: config.operation === ListOperationType.REMOVE
|
|
63
|
-
? "delete"
|
|
64
|
-
: "update";
|
|
65
|
-
config.onRollback(error, { previousData, timestamp: Date.now(), operationType: opType });
|
|
66
|
-
}
|
|
67
|
-
: undefined,
|
|
68
|
-
enabled: true
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
export function batchUpdateItems(items, updates) {
|
|
72
|
-
let currentItems = items || [];
|
|
73
|
-
updates.forEach((update) => { currentItems = listUpdater.update(currentItems, update); });
|
|
74
|
-
return currentItems;
|
|
75
|
-
}
|
|
76
|
-
export function batchRemoveItems(items, itemIds) {
|
|
77
|
-
let currentItems = items || [];
|
|
78
|
-
itemIds.forEach((itemId) => { currentItems = listUpdater.remove(currentItems, itemId); });
|
|
79
|
-
return currentItems;
|
|
80
|
-
}
|
|
81
|
-
export function reorderItems(items, fromIndex, toIndex) {
|
|
82
|
-
const currentItems = [...(items || [])];
|
|
83
|
-
if (fromIndex < 0 || fromIndex >= currentItems.length || toIndex < 0 || toIndex >= currentItems.length) {
|
|
84
|
-
return currentItems;
|
|
85
|
-
}
|
|
86
|
-
const [movedItem] = currentItems.splice(fromIndex, 1);
|
|
87
|
-
currentItems.splice(toIndex, 0, movedItem);
|
|
88
|
-
return currentItems;
|
|
89
|
-
}
|
|
90
|
-
export function conditionalUpdateItems(items, predicate, updater) {
|
|
91
|
-
const currentItems = items || [];
|
|
92
|
-
return currentItems.map((item) => { if (predicate(item)) {
|
|
93
|
-
return { ...item, ...updater(item) };
|
|
94
|
-
} return item; });
|
|
95
|
-
}
|
|
96
|
-
export function applyListOperationToPaginated(data, operation, payload) {
|
|
97
|
-
let items = data.items || [];
|
|
98
|
-
if (operation === ListOperationType.ADD) {
|
|
99
|
-
items = listUpdater.add(items, payload);
|
|
100
|
-
}
|
|
101
|
-
else if (operation === ListOperationType.UPDATE) {
|
|
102
|
-
items = listUpdater.update(items, payload);
|
|
103
|
-
}
|
|
104
|
-
else if (operation === ListOperationType.REMOVE) {
|
|
105
|
-
const id = payload?.id;
|
|
106
|
-
items = listUpdater.remove(items, id);
|
|
107
|
-
}
|
|
108
|
-
const total = typeof data.total === "number"
|
|
109
|
-
? operation === ListOperationType.ADD
|
|
110
|
-
? data.total + 1
|
|
111
|
-
: operation === ListOperationType.REMOVE
|
|
112
|
-
? Math.max(0, data.total - 1)
|
|
113
|
-
: data.total
|
|
114
|
-
: data.total;
|
|
115
|
-
return { ...data, items, total };
|
|
116
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"placeholderData.d.ts","sourceRoot":"","sources":["../../src/utils/placeholderData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,wBAAgB,qBAAqB,CAAC,CAAC,GAAG,GAAG,EAAE,YAAY,EAAE,CAAC,GAAG,SAAS,GAAG,CAAC,GAAG,SAAS,CAuBzF"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export { keepPreviousData } from "@tanstack/react-query";
|
|
2
|
-
export function stableListPlaceholder(previousData) {
|
|
3
|
-
if (previousData === undefined || previousData === null)
|
|
4
|
-
return previousData;
|
|
5
|
-
if (Array.isArray(previousData)) {
|
|
6
|
-
return [];
|
|
7
|
-
}
|
|
8
|
-
if (typeof previousData === "object") {
|
|
9
|
-
const obj = { ...previousData };
|
|
10
|
-
if (Array.isArray(obj.Rows)) {
|
|
11
|
-
obj.Rows = [];
|
|
12
|
-
if (typeof obj.Total === "number")
|
|
13
|
-
obj.Total = obj.Total;
|
|
14
|
-
return obj;
|
|
15
|
-
}
|
|
16
|
-
if (Array.isArray(obj.items)) {
|
|
17
|
-
obj.items = [];
|
|
18
|
-
if (typeof obj.total === "number")
|
|
19
|
-
obj.total = obj.total;
|
|
20
|
-
return obj;
|
|
21
|
-
}
|
|
22
|
-
if (Array.isArray(obj.data)) {
|
|
23
|
-
obj.data = [];
|
|
24
|
-
return obj;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return previousData;
|
|
28
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import type { QueryClient, QueryFunction, QueryKey } from "@tanstack/react-query";
|
|
2
|
-
export interface PrefetchConfig {
|
|
3
|
-
priority?: "high" | "medium" | "low";
|
|
4
|
-
delay?: number;
|
|
5
|
-
staleTime?: number;
|
|
6
|
-
allowSlowNetwork?: boolean;
|
|
7
|
-
}
|
|
8
|
-
export interface PrefetchTask {
|
|
9
|
-
queryKey: QueryKey;
|
|
10
|
-
queryFn: QueryFunction<any>;
|
|
11
|
-
config: PrefetchConfig;
|
|
12
|
-
timestamp: number;
|
|
13
|
-
id: string;
|
|
14
|
-
predictionScore?: number;
|
|
15
|
-
}
|
|
16
|
-
export type NetworkSpeed = "slow" | "medium" | "fast" | "unknown";
|
|
17
|
-
export interface PrefetchStats {
|
|
18
|
-
queueSize: number;
|
|
19
|
-
historySize: number;
|
|
20
|
-
networkSpeed: NetworkSpeed;
|
|
21
|
-
isProcessing: boolean;
|
|
22
|
-
totalPrefetches: number;
|
|
23
|
-
successfulPrefetches: number;
|
|
24
|
-
failedPrefetches: number;
|
|
25
|
-
averagePrefetchTime: number;
|
|
26
|
-
skippedPrefetches: number;
|
|
27
|
-
}
|
|
28
|
-
export interface InteractionRecord {
|
|
29
|
-
queryKey: QueryKey;
|
|
30
|
-
timestamp: number;
|
|
31
|
-
type: "view" | "hover" | "click" | "focus";
|
|
32
|
-
}
|
|
33
|
-
export interface PredictionResult {
|
|
34
|
-
queryKey: QueryKey;
|
|
35
|
-
score: number;
|
|
36
|
-
reason: string;
|
|
37
|
-
}
|
|
38
|
-
export declare class SmartPrefetchManager {
|
|
39
|
-
private queryClient;
|
|
40
|
-
private prefetchQueue;
|
|
41
|
-
private prefetchHistory;
|
|
42
|
-
private networkSpeed;
|
|
43
|
-
private isProcessing;
|
|
44
|
-
private maxQueueSize;
|
|
45
|
-
private maxHistorySize;
|
|
46
|
-
private totalPrefetches;
|
|
47
|
-
private successfulPrefetches;
|
|
48
|
-
private failedPrefetches;
|
|
49
|
-
private skippedPrefetches;
|
|
50
|
-
private prefetchTimes;
|
|
51
|
-
private maxPrefetchTimesSize;
|
|
52
|
-
private interactionHistory;
|
|
53
|
-
private maxInteractionHistorySize;
|
|
54
|
-
private queryAccessCounts;
|
|
55
|
-
private querySequences;
|
|
56
|
-
private maxSequenceSize;
|
|
57
|
-
private networkCleanup?;
|
|
58
|
-
constructor(queryClient: QueryClient);
|
|
59
|
-
private initNetworkMonitoring;
|
|
60
|
-
private updateNetworkSpeed;
|
|
61
|
-
getNetworkSpeed(): NetworkSpeed;
|
|
62
|
-
isSlowNetwork(): boolean;
|
|
63
|
-
shouldPrefetch(queryKey: QueryKey, config?: PrefetchConfig): boolean;
|
|
64
|
-
addPrefetchTask(queryKey: QueryKey, queryFn: QueryFunction<any>, config?: PrefetchConfig): boolean;
|
|
65
|
-
private processQueue;
|
|
66
|
-
private getSortedTasks;
|
|
67
|
-
prefetchNow<TData = unknown>(queryKey: QueryKey, queryFn: QueryFunction<TData>, config?: PrefetchConfig): Promise<void>;
|
|
68
|
-
private addToHistory;
|
|
69
|
-
clearHistory(): void;
|
|
70
|
-
clearQueue(): void;
|
|
71
|
-
reset(): void;
|
|
72
|
-
destroy(): void;
|
|
73
|
-
recordInteraction(queryKey: QueryKey, type?: "view" | "hover" | "click" | "focus"): void;
|
|
74
|
-
getPredictions(currentQueryKey?: QueryKey, limit?: number): PredictionResult[];
|
|
75
|
-
prefetchPredicted(currentQueryKey: QueryKey | undefined, queryFnMap: Map<string, QueryFunction<any>>, config?: PrefetchConfig): Promise<void>;
|
|
76
|
-
clearInteractionHistory(): void;
|
|
77
|
-
private recordPrefetchTime;
|
|
78
|
-
private getAveragePrefetchTime;
|
|
79
|
-
getStats(): PrefetchStats;
|
|
80
|
-
getPerformanceReport(): {
|
|
81
|
-
stats: PrefetchStats;
|
|
82
|
-
successRate: number;
|
|
83
|
-
predictions: {
|
|
84
|
-
totalInteractions: number;
|
|
85
|
-
uniqueQueries: number;
|
|
86
|
-
sequencePatterns: number;
|
|
87
|
-
};
|
|
88
|
-
queue: {
|
|
89
|
-
size: number;
|
|
90
|
-
byPriority: {
|
|
91
|
-
high: number;
|
|
92
|
-
medium: number;
|
|
93
|
-
low: number;
|
|
94
|
-
};
|
|
95
|
-
};
|
|
96
|
-
};
|
|
97
|
-
resetStats(): void;
|
|
98
|
-
private getQueryKeyString;
|
|
99
|
-
private delay;
|
|
100
|
-
setMaxQueueSize(size: number): void;
|
|
101
|
-
setMaxHistorySize(size: number): void;
|
|
102
|
-
getQueuedTasks(): PrefetchTask[];
|
|
103
|
-
removeTask(queryKey: QueryKey): boolean;
|
|
104
|
-
hasTask(queryKey: QueryKey): boolean;
|
|
105
|
-
updateTaskPriority(queryKey: QueryKey, priority: "high" | "medium" | "low"): boolean;
|
|
106
|
-
pauseQueue(): void;
|
|
107
|
-
resumeQueue(): void;
|
|
108
|
-
}
|
|
109
|
-
export declare function getPrefetchManager(queryClient: QueryClient): SmartPrefetchManager;
|
|
110
|
-
export declare function resetPrefetchManager(): void;
|
|
111
|
-
//# sourceMappingURL=prefetchManager.d.ts.map
|