@qiaopeng/tanstack-query-plus 0.5.8 → 0.5.9
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 +69 -40
- package/dist/PersistQueryClientProvider.d.ts.map +1 -1
- package/dist/PersistQueryClientProvider.js +17 -7
- package/dist/core/config.d.ts +4 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +10 -4
- package/dist/core/queryOptions.d.ts.map +1 -1
- package/dist/core/queryOptions.js +9 -21
- package/dist/features/index.d.ts +1 -1
- package/dist/features/index.d.ts.map +1 -1
- package/dist/features/index.js +1 -1
- package/dist/features/offline.d.ts +1 -0
- package/dist/features/offline.d.ts.map +1 -1
- package/dist/features/offline.js +33 -2
- package/dist/features/persistence.d.ts.map +1 -1
- package/dist/features/persistence.js +3 -2
- package/dist/hooks/useDataGuardMutation.d.ts.map +1 -1
- package/dist/hooks/useDataGuardMutation.js +1 -15
- package/dist/hooks/useMutation.js +3 -3
- package/dist/types/dataGuard.d.ts +1 -1
- package/dist/types/dataGuard.d.ts.map +1 -1
- package/dist/utils/dataGuard.d.ts.map +1 -1
- package/dist/utils/dataGuard.js +16 -22
- 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/queryKey.d.ts +2 -0
- package/dist/utils/queryKey.d.ts.map +1 -1
- package/dist/utils/queryKey.js +12 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -295,9 +295,11 @@ function App() {
|
|
|
295
295
|
retryDelay: exponentialBackoff,
|
|
296
296
|
refetchOnWindowFocus: true,
|
|
297
297
|
refetchOnReconnect: true,
|
|
298
|
+
refetchOnMount: true,
|
|
298
299
|
},
|
|
299
300
|
mutations: {
|
|
300
301
|
retry: 0, // Mutation 默认不重试
|
|
302
|
+
retryDelay: exponentialBackoff,
|
|
301
303
|
gcTime: 600000,
|
|
302
304
|
}
|
|
303
305
|
}
|
|
@@ -325,7 +327,13 @@ function App() {
|
|
|
325
327
|
import { getConfigByEnvironment } from '@qiaopeng/tanstack-query-plus/core'
|
|
326
328
|
|
|
327
329
|
// 根据环境自动选择配置
|
|
328
|
-
const
|
|
330
|
+
const env =
|
|
331
|
+
process.env.NODE_ENV === 'production'
|
|
332
|
+
? 'production'
|
|
333
|
+
: process.env.NODE_ENV === 'test'
|
|
334
|
+
? 'test'
|
|
335
|
+
: 'development'
|
|
336
|
+
const config = getConfigByEnvironment(env)
|
|
329
337
|
const queryClient = new QueryClient({ defaultOptions: config })
|
|
330
338
|
```
|
|
331
339
|
|
|
@@ -340,6 +348,8 @@ const queryClient = new QueryClient({ defaultOptions: config })
|
|
|
340
348
|
|
|
341
349
|
*智能重试:4XX 不重试,5XX 最多 1 次,网络错误最多 2 次
|
|
342
350
|
|
|
351
|
+
补充:还支持 `getConfigByEnvironment('longCache')` 与 `getConfigByEnvironment('realtime')` 两种预设,分别适用于“长缓存”与“高实时”场景。
|
|
352
|
+
|
|
343
353
|
### 3.5 自定义重试策略
|
|
344
354
|
|
|
345
355
|
如果默认的重试策略不满足你的需求,可以使用 `createSafeRetryStrategy` 和 `createErrorSafeConfig` 来自定义:
|
|
@@ -1129,13 +1139,21 @@ batchDelete.mutate(['id1', 'id2', 'id3'])
|
|
|
1129
1139
|
2. 使用离线队列在恢复网络后批量执行(稳健且可持久化):
|
|
1130
1140
|
|
|
1131
1141
|
```tsx
|
|
1132
|
-
import { createOfflineQueueManager, mutationRegistry } from '@qiaopeng/tanstack-query-plus/features'
|
|
1142
|
+
import { createOfflineQueueManager, mutationRegistry, serializeMutationKey } from '@qiaopeng/tanstack-query-plus/features'
|
|
1143
|
+
import { MutationOperationType } from '@qiaopeng/tanstack-query-plus/types'
|
|
1133
1144
|
|
|
1134
1145
|
const queue = createOfflineQueueManager({ storageKey: 'todo-ops', concurrency: 3 })
|
|
1135
1146
|
|
|
1136
|
-
function registerDelete(id: string) {
|
|
1137
|
-
|
|
1138
|
-
|
|
1147
|
+
async function registerDelete(id: string) {
|
|
1148
|
+
const key = serializeMutationKey(['todos', 'delete', id])
|
|
1149
|
+
mutationRegistry.register(key, () => api.deleteTodo(id))
|
|
1150
|
+
await queue.add({
|
|
1151
|
+
type: MutationOperationType.DELETE,
|
|
1152
|
+
mutationKey: ['todos', 'delete', id],
|
|
1153
|
+
variables: { id },
|
|
1154
|
+
mutationFn: () => api.deleteTodo(id),
|
|
1155
|
+
priority: 1
|
|
1156
|
+
})
|
|
1139
1157
|
}
|
|
1140
1158
|
```
|
|
1141
1159
|
|
|
@@ -2710,7 +2728,8 @@ console.log({
|
|
|
2710
2728
|
对于需要在离线时也能操作的应用,可以使用离线队列管理器:
|
|
2711
2729
|
|
|
2712
2730
|
```tsx
|
|
2713
|
-
import { createOfflineQueueManager, mutationRegistry } from '@qiaopeng/tanstack-query-plus/features'
|
|
2731
|
+
import { createOfflineQueueManager, isOnline, mutationRegistry, serializeMutationKey } from '@qiaopeng/tanstack-query-plus/features'
|
|
2732
|
+
import { MutationOperationType } from '@qiaopeng/tanstack-query-plus/types'
|
|
2714
2733
|
|
|
2715
2734
|
// 创建队列管理器
|
|
2716
2735
|
const queueManager = createOfflineQueueManager({
|
|
@@ -2723,15 +2742,17 @@ const queueManager = createOfflineQueueManager({
|
|
|
2723
2742
|
|
|
2724
2743
|
// 注册 mutation 函数(用于恢复队列时执行)
|
|
2725
2744
|
// 注册函数签名为 () => Promise<unknown>,如需变量请使用闭包或在入队项的 mutationFn 捕获
|
|
2726
|
-
mutationRegistry.register('updateUser', () => updateUserAPI(savedUserData))
|
|
2727
|
-
mutationRegistry.register('createPost', () => createPostAPI(savedPostData))
|
|
2745
|
+
mutationRegistry.register(serializeMutationKey(['updateUser']), () => updateUserAPI(savedUserData))
|
|
2746
|
+
mutationRegistry.register(serializeMutationKey(['createPost']), () => createPostAPI(savedPostData))
|
|
2728
2747
|
|
|
2729
2748
|
// 添加操作到队列
|
|
2730
2749
|
async function handleUpdateUser(userData) {
|
|
2731
2750
|
if (!isOnline()) {
|
|
2732
2751
|
// 离线时添加到队列
|
|
2733
2752
|
await queueManager.add({
|
|
2753
|
+
type: MutationOperationType.UPDATE,
|
|
2734
2754
|
mutationKey: ['updateUser'],
|
|
2755
|
+
variables: userData,
|
|
2735
2756
|
mutationFn: () => updateUserAPI(userData),
|
|
2736
2757
|
priority: 1, // 优先级(数字越大越优先)
|
|
2737
2758
|
})
|
|
@@ -2772,6 +2793,7 @@ queueManager.destroy()
|
|
|
2772
2793
|
```tsx
|
|
2773
2794
|
import { useState, useEffect } from 'react'
|
|
2774
2795
|
import { createOfflineQueueManager } from '@qiaopeng/tanstack-query-plus/features'
|
|
2796
|
+
import { MutationOperationType } from '@qiaopeng/tanstack-query-plus/types'
|
|
2775
2797
|
import { useEnhancedQuery } from '@qiaopeng/tanstack-query-plus/hooks'
|
|
2776
2798
|
import { useQueryClient, usePersistenceStatus } from '@qiaopeng/tanstack-query-plus'
|
|
2777
2799
|
|
|
@@ -2817,7 +2839,9 @@ function TodoApp() {
|
|
|
2817
2839
|
if (!networkStatus) {
|
|
2818
2840
|
// 离线:添加到队列
|
|
2819
2841
|
await offlineQueue.add({
|
|
2842
|
+
type: MutationOperationType.CREATE,
|
|
2820
2843
|
mutationKey: ['addTodo'],
|
|
2844
|
+
variables: todoData,
|
|
2821
2845
|
mutationFn: () => api.createTodo(todoData),
|
|
2822
2846
|
priority: 1,
|
|
2823
2847
|
})
|
|
@@ -3675,7 +3699,13 @@ function UserProfile({ userId }) {
|
|
|
3675
3699
|
import { QueryClient } from '@qiaopeng/tanstack-query-plus'
|
|
3676
3700
|
import { getConfigByEnvironment, ensureBestPractices } from '@qiaopeng/tanstack-query-plus/core'
|
|
3677
3701
|
|
|
3678
|
-
const
|
|
3702
|
+
const env =
|
|
3703
|
+
process.env.NODE_ENV === 'production'
|
|
3704
|
+
? 'production'
|
|
3705
|
+
: process.env.NODE_ENV === 'test'
|
|
3706
|
+
? 'test'
|
|
3707
|
+
: 'development'
|
|
3708
|
+
const baseConfig = getConfigByEnvironment(env)
|
|
3679
3709
|
|
|
3680
3710
|
// 确保配置符合最佳实践
|
|
3681
3711
|
const config = ensureBestPractices({
|
|
@@ -3751,12 +3781,12 @@ function useUser(userId: string): EnhancedQueryResult<User, ApiError> {
|
|
|
3751
3781
|
}
|
|
3752
3782
|
|
|
3753
3783
|
// 类型安全的 mutation
|
|
3754
|
-
function useUpdateUser() {
|
|
3784
|
+
function useUpdateUser(userId: string) {
|
|
3755
3785
|
return useMutation<User, ApiError, Partial<User>>({
|
|
3756
|
-
mutationFn: (
|
|
3786
|
+
mutationFn: (patch) => updateUser(userId, patch),
|
|
3757
3787
|
optimistic: {
|
|
3758
|
-
queryKey: ['user',
|
|
3759
|
-
updater: (old,
|
|
3788
|
+
queryKey: ['user', userId],
|
|
3789
|
+
updater: (old, patch) => (old ? ({ ...old, ...patch }) : old),
|
|
3760
3790
|
},
|
|
3761
3791
|
})
|
|
3762
3792
|
}
|
|
@@ -3886,32 +3916,6 @@ useEnhancedQuery({
|
|
|
3886
3916
|
3. **处理认证过期**:在全局错误处理中处理 401 错误
|
|
3887
3917
|
4. **清理敏感缓存**:用户登出时清除缓存
|
|
3888
3918
|
|
|
3889
|
-
---
|
|
3890
|
-
|
|
3891
|
-
## 总结
|
|
3892
|
-
|
|
3893
|
-
恭喜你完成了本教程!现在你已经掌握了 `@qiaopeng/tanstack-query-plus` 的所有核心功能:
|
|
3894
|
-
|
|
3895
|
-
1. ✅ 配置 Provider 和最佳实践
|
|
3896
|
-
2. ✅ 基础查询和增强查询
|
|
3897
|
-
3. ✅ Query Key 管理
|
|
3898
|
-
4. ✅ 数据变更和乐观更新
|
|
3899
|
-
5. ✅ 无限滚动和分页
|
|
3900
|
-
6. ✅ 批量查询和仪表盘
|
|
3901
|
-
7. ✅ 智能预取策略
|
|
3902
|
-
8. ✅ Suspense 模式
|
|
3903
|
-
9. ✅ 离线支持和持久化
|
|
3904
|
-
10. ✅ 数据防护与安全
|
|
3905
|
-
11. ✅ 焦点管理
|
|
3906
|
-
12. ✅ 工具函数和选择器
|
|
3907
|
-
|
|
3908
|
-
### 下一步
|
|
3909
|
-
|
|
3910
|
-
- 查看 [GitHub 仓库](https://github.com/qiaopengg/qiaopeng-tanstack-query-plus) 获取最新更新
|
|
3911
|
-
- 阅读 [TanStack Query 官方文档](https://tanstack.com/query/latest) 了解更多底层概念
|
|
3912
|
-
- 在 [Issues](https://github.com/qiaopengg/qiaopeng-tanstack-query-plus/issues) 中提问或反馈
|
|
3913
|
-
|
|
3914
|
-
祝你编码愉快!🚀
|
|
3915
3919
|
### 16.9 类型与错误处理规范
|
|
3916
3920
|
|
|
3917
3921
|
- 明确类型参数:在增强 hooks 中显式标注 `TData` 与 `TError`,避免 `any` 漏出
|
|
@@ -3979,7 +3983,7 @@ useEnhancedQuery({
|
|
|
3979
3983
|
- 数据防护:`useDataGuardQueryConfig`、`useDataGuardMutation`
|
|
3980
3984
|
|
|
3981
3985
|
- `@qiaopeng/tanstack-query-plus/features`
|
|
3982
|
-
- 离线:`setupOnlineManager`、`isOnline`、`createOfflineQueueManager`、`OfflineQueueManager`、`mutationRegistry`、`subscribeToOnlineStatus`
|
|
3986
|
+
- 离线:`setupOnlineManager`、`isOnline`、`createOfflineQueueManager`、`OfflineQueueManager`、`mutationRegistry`、`serializeMutationKey`、`subscribeToOnlineStatus`
|
|
3983
3987
|
- 持久化:`createPersistOptions`、`createPersister`、`clearCache`、`clearExpiredCache`、`checkStorageSize`、`getStorageStats`、`migrateToIndexedDB`
|
|
3984
3988
|
|
|
3985
3989
|
- `@qiaopeng/tanstack-query-plus/components`
|
|
@@ -3999,3 +4003,28 @@ useEnhancedQuery({
|
|
|
3999
4003
|
- 原生 API 再导出:`useQuery`、`useMutation`、`useInfiniteQuery`、`useSuspenseQuery` 等(src/react-query/index.ts:1)
|
|
4000
4004
|
|
|
4001
4005
|
提示:完整导出列表可在 `package.json:33` 的 `exports` 字段中查看;顶层入口再导出常用原生 API,子路径按模块分层导出,便于 tree-shaking。
|
|
4006
|
+
|
|
4007
|
+
---
|
|
4008
|
+
|
|
4009
|
+
## 总结
|
|
4010
|
+
|
|
4011
|
+
你已经覆盖了 `@qiaopeng/tanstack-query-plus` 的核心能力:
|
|
4012
|
+
|
|
4013
|
+
1. ✅ 配置 Provider 和最佳实践
|
|
4014
|
+
2. ✅ 基础查询和增强查询
|
|
4015
|
+
3. ✅ Query Key 管理
|
|
4016
|
+
4. ✅ 数据变更和乐观更新
|
|
4017
|
+
5. ✅ 无限滚动和分页
|
|
4018
|
+
6. ✅ 批量查询和仪表盘
|
|
4019
|
+
7. ✅ 智能预取策略
|
|
4020
|
+
8. ✅ Suspense 模式
|
|
4021
|
+
9. ✅ 离线支持和持久化
|
|
4022
|
+
10. ✅ 数据防护与安全
|
|
4023
|
+
11. ✅ 焦点管理
|
|
4024
|
+
12. ✅ 工具函数和选择器
|
|
4025
|
+
|
|
4026
|
+
### 下一步
|
|
4027
|
+
|
|
4028
|
+
- 查看 [GitHub 仓库](https://github.com/qiaopengg/qiaopeng-tanstack-query-plus) 获取最新更新
|
|
4029
|
+
- 阅读 [TanStack Query 官方文档](https://tanstack.com/query/latest) 了解更多底层概念
|
|
4030
|
+
- 在 [Issues](https://github.com/qiaopengg/qiaopeng-tanstack-query-plus/issues) 中提问或反馈
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersistQueryClientProvider.d.ts","sourceRoot":"","sources":["../src/PersistQueryClientProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"PersistQueryClientProvider.d.ts","sourceRoot":"","sources":["../src/PersistQueryClientProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACxC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,wBAAgB,0BAA0B,CAAC,EACzC,QAAQ,EACR,MAAM,EACN,QAAiC,EACjC,iBAAwB,EACxB,oBAA2B,EAC3B,cAAc,EAAE,eAAe,EAC/B,gBAAgB,EACjB,EAAE,+BAA+B,2CAmCjC;AAED,wBAAgB,oBAAoB;;;EASnC;AAED,wBAAgB,qBAAqB;;;EAWpC;AAED,eAAe,0BAA0B,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { QueryClientProvider } from "@tanstack/react-query";
|
|
3
3
|
import { PersistQueryClientProvider as TanStackPersistProvider } from "@tanstack/react-query-persist-client";
|
|
4
|
-
import { useEffect, useState } from "react";
|
|
4
|
+
import { useEffect, useMemo, useState } from "react";
|
|
5
|
+
import { TIME_CONSTANTS } from "./core/config.js";
|
|
5
6
|
import { isOnline, setupOnlineManager, subscribeToOnlineStatus } from "./features/offline.js";
|
|
6
7
|
import { clearCache, createPersister } from "./features/persistence.js";
|
|
7
8
|
export function PersistQueryClientProvider({ children, client, cacheKey = "tanstack-query-cache", enablePersistence = true, enableOfflineSupport = true, onPersistError: _onPersistError, onPersistRestore }) {
|
|
@@ -10,15 +11,24 @@ export function PersistQueryClientProvider({ children, client, cacheKey = "tanst
|
|
|
10
11
|
setupOnlineManager();
|
|
11
12
|
}
|
|
12
13
|
}, [enableOfflineSupport]);
|
|
14
|
+
const persister = useMemo(() => {
|
|
15
|
+
if (!enablePersistence)
|
|
16
|
+
return null;
|
|
17
|
+
return createPersister(cacheKey, undefined, _onPersistError);
|
|
18
|
+
}, [cacheKey, enablePersistence, _onPersistError]);
|
|
19
|
+
const persistOptions = useMemo(() => {
|
|
20
|
+
if (!persister)
|
|
21
|
+
return null;
|
|
22
|
+
return {
|
|
23
|
+
persister,
|
|
24
|
+
maxAge: TIME_CONSTANTS.ONE_DAY
|
|
25
|
+
};
|
|
26
|
+
}, [persister]);
|
|
13
27
|
if (enablePersistence) {
|
|
14
|
-
|
|
15
|
-
if (!persister) {
|
|
28
|
+
if (!persistOptions) {
|
|
16
29
|
return _jsx(QueryClientProvider, { client: client, children: children });
|
|
17
30
|
}
|
|
18
|
-
return (_jsx(TanStackPersistProvider, { client: client, persistOptions:
|
|
19
|
-
persister,
|
|
20
|
-
maxAge: 1000 * 60 * 60 * 24
|
|
21
|
-
}, onSuccess: onPersistRestore, children: children }));
|
|
31
|
+
return (_jsx(TanStackPersistProvider, { client: client, persistOptions: persistOptions, onSuccess: onPersistRestore, children: children }));
|
|
22
32
|
}
|
|
23
33
|
return _jsx(QueryClientProvider, { client: client, children: children });
|
|
24
34
|
}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -26,15 +26,15 @@ export declare function defaultQueryRetryStrategy(failureCount: number, error: u
|
|
|
26
26
|
*/
|
|
27
27
|
export declare function defaultMutationRetryStrategy(failureCount: number, error: unknown): boolean;
|
|
28
28
|
export declare function exponentialBackoff(attemptIndex: number): number;
|
|
29
|
-
export declare const DEFAULT_QUERY_CONFIG: DefaultOptions["queries"]
|
|
30
|
-
export declare const DEFAULT_MUTATION_CONFIG: DefaultOptions["mutations"]
|
|
29
|
+
export declare const DEFAULT_QUERY_CONFIG: NonNullable<DefaultOptions["queries"]>;
|
|
30
|
+
export declare const DEFAULT_MUTATION_CONFIG: NonNullable<DefaultOptions["mutations"]>;
|
|
31
31
|
export declare const GLOBAL_QUERY_CONFIG: DefaultOptions;
|
|
32
32
|
export declare const SMART_RETRY_MUTATION_CONFIG: DefaultOptions["mutations"];
|
|
33
33
|
export declare const DEVELOPMENT_CONFIG: DefaultOptions;
|
|
34
34
|
export declare const PRODUCTION_CONFIG: DefaultOptions;
|
|
35
35
|
export declare const LONG_CACHE_CONFIG: DefaultOptions;
|
|
36
36
|
export declare const REALTIME_CONFIG: DefaultOptions;
|
|
37
|
-
export declare function getConfigByEnvironment(env: "development" | "production" | "test"): DefaultOptions;
|
|
37
|
+
export declare function getConfigByEnvironment(env: "development" | "production" | "test" | "realtime" | "longCache"): DefaultOptions;
|
|
38
38
|
export declare function createCustomConfig(overrides: Partial<DefaultOptions>): DefaultOptions;
|
|
39
39
|
export declare function validateGcTime(staleTime: number, gcTime: number): {
|
|
40
40
|
isValid: boolean;
|
|
@@ -74,7 +74,7 @@ export declare function createErrorSafeConfig(options?: {
|
|
|
74
74
|
maxRetriesOther?: number;
|
|
75
75
|
disableFocus?: boolean;
|
|
76
76
|
disableReconnect?: boolean;
|
|
77
|
-
conditionalRefetchInterval?: number | ((data: unknown, query: any) => number | false);
|
|
77
|
+
conditionalRefetchInterval?: number | ((query: any) => number | false) | ((data: unknown, query: any) => number | false);
|
|
78
78
|
overrides?: Partial<DefaultOptions>;
|
|
79
79
|
}): DefaultOptions;
|
|
80
80
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,eAAO,MAAM,cAAc;;;;;;;;;CASjB,CAAC;AAEX,eAAO,MAAM,kBAAkB,QAAgC,CAAC;AAChE,eAAO,MAAM,eAAe,QAA6B,CAAC;AAkC1D;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAevF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAe1F;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,eAAO,MAAM,oBAAoB,EAAE,cAAc,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,eAAO,MAAM,cAAc;;;;;;;;;CASjB,CAAC;AAEX,eAAO,MAAM,kBAAkB,QAAgC,CAAC;AAChE,eAAO,MAAM,eAAe,QAA6B,CAAC;AAkC1D;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAevF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAe1F;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,cAAc,CAAC,SAAS,CAAC,CAQvE,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,cAAc,CAAC,WAAW,CAAC,CAI5E,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,cAGjC,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,cAAc,CAAC,WAAW,CAInE,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,cAYhC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,cAY/B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,cAa/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAW7B,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,aAAa,GAAG,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,GACpE,cAAc,CA4BhB;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAWrF;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAQxG;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA2B/F;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAyC1E;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,aAAa,GAAE,MAAU,EACzB,aAAa,GAAE,MAAU,EACzB,eAAe,GAAE,MAAU,IAEnB,cAAc,MAAM,EAAE,OAAO,OAAO,KAAG,OAAO,CAgBvD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,GAAE;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0BAA0B,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,KAAK,CAAC,CAAC;IACzH,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CAChC,GAAG,cAAc,CAuCtB"}
|
package/dist/core/config.js
CHANGED
|
@@ -155,6 +155,10 @@ export function getConfigByEnvironment(env) {
|
|
|
155
155
|
return DEVELOPMENT_CONFIG;
|
|
156
156
|
case "production":
|
|
157
157
|
return PRODUCTION_CONFIG;
|
|
158
|
+
case "realtime":
|
|
159
|
+
return REALTIME_CONFIG;
|
|
160
|
+
case "longCache":
|
|
161
|
+
return LONG_CACHE_CONFIG;
|
|
158
162
|
case "test":
|
|
159
163
|
return {
|
|
160
164
|
queries: {
|
|
@@ -226,9 +230,10 @@ export function ensureBestPractices(config) {
|
|
|
226
230
|
const result = { ...config };
|
|
227
231
|
if (result.queries) {
|
|
228
232
|
const queries = { ...result.queries };
|
|
233
|
+
// Handle deprecated cacheTime -> gcTime mapping
|
|
229
234
|
if ("cacheTime" in queries) {
|
|
230
235
|
const cacheTime = queries.cacheTime;
|
|
231
|
-
if (typeof cacheTime === "number" &&
|
|
236
|
+
if (typeof cacheTime === "number" && queries.gcTime === undefined) {
|
|
232
237
|
queries.gcTime = cacheTime;
|
|
233
238
|
}
|
|
234
239
|
delete queries.cacheTime;
|
|
@@ -245,7 +250,7 @@ export function ensureBestPractices(config) {
|
|
|
245
250
|
console.warn(`[TanStack Query Config] 自动调整 gcTime 从 ${gcTime}ms 到 ${queries.gcTime}ms,以确保大于 staleTime (${staleTime}ms)。`);
|
|
246
251
|
}
|
|
247
252
|
}
|
|
248
|
-
if (
|
|
253
|
+
if (queries.retryDelay === undefined) {
|
|
249
254
|
queries.retryDelay = exponentialBackoff;
|
|
250
255
|
}
|
|
251
256
|
if (queries.refetchOnWindowFocus === undefined) {
|
|
@@ -303,10 +308,11 @@ export function createErrorSafeConfig(options = {}) {
|
|
|
303
308
|
};
|
|
304
309
|
if (conditionalRefetchInterval !== undefined) {
|
|
305
310
|
if (typeof conditionalRefetchInterval === "number") {
|
|
306
|
-
queries.refetchInterval = (
|
|
311
|
+
queries.refetchInterval = (query) => (query?.state?.error ? false : conditionalRefetchInterval);
|
|
307
312
|
}
|
|
308
313
|
else {
|
|
309
|
-
|
|
314
|
+
const fn = conditionalRefetchInterval;
|
|
315
|
+
queries.refetchInterval = (query) => (fn.length >= 2 ? fn(query?.state?.data, query) : fn(query));
|
|
310
316
|
}
|
|
311
317
|
}
|
|
312
318
|
const mutations = {
|
|
@@ -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,
|
|
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,CASlI;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,CAShL;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,CASnI"}
|
|
@@ -1,44 +1,32 @@
|
|
|
1
1
|
import { queryOptions } from "@tanstack/react-query";
|
|
2
|
-
import { DEFAULT_GC_TIME,
|
|
2
|
+
import { DEFAULT_GC_TIME, DEFAULT_QUERY_CONFIG, DEFAULT_STALE_TIME } from "./config.js";
|
|
3
3
|
export function createAppQueryOptions(config) {
|
|
4
4
|
return queryOptions({
|
|
5
|
+
...DEFAULT_QUERY_CONFIG,
|
|
5
6
|
queryKey: config.queryKey,
|
|
6
7
|
queryFn: config.queryFn,
|
|
7
|
-
staleTime: config.staleTime ?? DEFAULT_STALE_TIME,
|
|
8
|
-
gcTime: config.gcTime ?? DEFAULT_GC_TIME,
|
|
8
|
+
staleTime: config.staleTime ?? DEFAULT_QUERY_CONFIG.staleTime ?? DEFAULT_STALE_TIME,
|
|
9
|
+
gcTime: config.gcTime ?? DEFAULT_QUERY_CONFIG.gcTime ?? DEFAULT_GC_TIME,
|
|
9
10
|
enabled: config.enabled,
|
|
10
|
-
retry: defaultQueryRetryStrategy,
|
|
11
|
-
retryDelay: exponentialBackoff,
|
|
12
|
-
refetchOnWindowFocus: true,
|
|
13
|
-
refetchOnReconnect: true,
|
|
14
|
-
refetchOnMount: true
|
|
15
11
|
});
|
|
16
12
|
}
|
|
17
13
|
export function createAppQueryOptionsWithSelect(config) {
|
|
18
14
|
return queryOptions({
|
|
15
|
+
...DEFAULT_QUERY_CONFIG,
|
|
19
16
|
queryKey: config.queryKey,
|
|
20
17
|
queryFn: config.queryFn,
|
|
21
18
|
select: config.select,
|
|
22
|
-
staleTime: config.staleTime ?? DEFAULT_STALE_TIME,
|
|
23
|
-
gcTime: config.gcTime ?? DEFAULT_GC_TIME,
|
|
24
|
-
retry: defaultQueryRetryStrategy,
|
|
25
|
-
retryDelay: exponentialBackoff,
|
|
26
|
-
refetchOnWindowFocus: true,
|
|
27
|
-
refetchOnReconnect: true,
|
|
28
|
-
refetchOnMount: true
|
|
19
|
+
staleTime: config.staleTime ?? DEFAULT_QUERY_CONFIG.staleTime ?? DEFAULT_STALE_TIME,
|
|
20
|
+
gcTime: config.gcTime ?? DEFAULT_QUERY_CONFIG.gcTime ?? DEFAULT_GC_TIME,
|
|
29
21
|
});
|
|
30
22
|
}
|
|
31
23
|
export function createListQueryOptions(config) {
|
|
32
24
|
return queryOptions({
|
|
25
|
+
...DEFAULT_QUERY_CONFIG,
|
|
33
26
|
queryKey: config.queryKey,
|
|
34
27
|
queryFn: config.queryFn,
|
|
35
28
|
staleTime: config.staleTime ?? 0,
|
|
36
|
-
gcTime: config.gcTime ?? DEFAULT_GC_TIME,
|
|
29
|
+
gcTime: config.gcTime ?? DEFAULT_QUERY_CONFIG.gcTime ?? DEFAULT_GC_TIME,
|
|
37
30
|
enabled: config.enabled,
|
|
38
|
-
retry: defaultQueryRetryStrategy,
|
|
39
|
-
retryDelay: exponentialBackoff,
|
|
40
|
-
refetchOnWindowFocus: true,
|
|
41
|
-
refetchOnReconnect: true,
|
|
42
|
-
refetchOnMount: true
|
|
43
31
|
});
|
|
44
32
|
}
|
package/dist/features/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { cancelQueriesBatch, invalidateQueriesBatch, setQueryDataBatch } from "../hooks/useMutation.js";
|
|
2
|
-
export { calculateExponentialBackoff, configureOfflineQueries, createOfflineQueueManager, isOnline, mutationRegistry, OfflineQueueManager, setupOnlineManager, subscribeToOnlineStatus } from "./offline.js";
|
|
2
|
+
export { calculateExponentialBackoff, configureOfflineQueries, createOfflineQueueManager, isOnline, mutationRegistry, OfflineQueueManager, serializeMutationKey, setupOnlineManager, subscribeToOnlineStatus } from "./offline.js";
|
|
3
3
|
export { checkStorageSize, clearCache, clearExpiredCache, createPersister, createPersistOptions, getStorageStats, migrateToIndexedDB, type PersistedClient, type Persister, type PersistOptions } from "./persistence.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACnO,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,iBAAiB,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/features/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { cancelQueriesBatch, invalidateQueriesBatch, setQueryDataBatch } from "../hooks/useMutation.js";
|
|
2
|
-
export { calculateExponentialBackoff, configureOfflineQueries, createOfflineQueueManager, isOnline, mutationRegistry, OfflineQueueManager, setupOnlineManager, subscribeToOnlineStatus } from "./offline.js";
|
|
2
|
+
export { calculateExponentialBackoff, configureOfflineQueries, createOfflineQueueManager, isOnline, mutationRegistry, OfflineQueueManager, serializeMutationKey, setupOnlineManager, subscribeToOnlineStatus } from "./offline.js";
|
|
3
3
|
export { checkStorageSize, clearCache, clearExpiredCache, createPersister, createPersistOptions, getStorageStats, migrateToIndexedDB } from "./persistence.js";
|
|
@@ -4,6 +4,7 @@ export declare function setupOnlineManager(): void;
|
|
|
4
4
|
export declare const isOnline: () => boolean;
|
|
5
5
|
export declare function subscribeToOnlineStatus(callback: (online: boolean) => void): () => void;
|
|
6
6
|
export declare function configureOfflineQueries(_queryClient: QueryClient): void;
|
|
7
|
+
export declare function serializeMutationKey(mutationKey: unknown): string;
|
|
7
8
|
export declare function calculateExponentialBackoff(attempt: number, baseDelay?: number, maxDelay?: number): number;
|
|
8
9
|
declare class MutationRegistry implements MutationFunctionRegistry {
|
|
9
10
|
private registry;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"offline.d.ts","sourceRoot":"","sources":["../../src/features/offline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAK7H,wBAAgB,kBAAkB,SAYjC;AACD,eAAO,MAAM,QAAQ,eAAiC,CAAC;AACvD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,cAA+C;AAC1H,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,WAAW,QAAI;
|
|
1
|
+
{"version":3,"file":"offline.d.ts","sourceRoot":"","sources":["../../src/features/offline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAK7H,wBAAgB,kBAAkB,SAYjC;AACD,eAAO,MAAM,QAAQ,eAAiC,CAAC;AACvD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,cAA+C;AAC1H,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,WAAW,QAAI;AAWrE,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,CAOjE;AAGD,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,SAAO,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAIvG;AACD,cAAM,gBAAiB,YAAW,wBAAwB;IACxD,OAAO,CAAC,QAAQ,CAA6C;IAC7D,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IACvD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS;IACtD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAC7B,KAAK,IAAI,IAAI;IACb,OAAO,IAAI,MAAM,EAAE;CACpB;AACD,eAAO,MAAM,gBAAgB,kBAAyB,CAAC;AAEvD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,mBAAmB,CAAqB;gBACpC,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAO9C,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,wBAAwB,EAAE,IAAI,GAAG,WAAW,GAAG,YAAY,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAUlG,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOnD,QAAQ,IAAI,YAAY;IAIxB,aAAa,IAAI,wBAAwB,EAAE;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IACtB,OAAO,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;YAoBhE,gBAAgB;IAuB9B,OAAO,CAAC,0BAA0B;IAsBlC,OAAO,CAAC,aAAa;YAKP,YAAY;IAe1B,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,mBAAmB;IAG3B,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,iBAAiB;IAGzB,OAAO,IAAI,IAAI;CAKhB;AACD,wBAAgB,yBAAyB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,mBAAmB,CAA4C"}
|
package/dist/features/offline.js
CHANGED
|
@@ -18,6 +18,27 @@ export function setupOnlineManager() {
|
|
|
18
18
|
export const isOnline = () => onlineManager.isOnline();
|
|
19
19
|
export function subscribeToOnlineStatus(callback) { return onlineManager.subscribe(callback); }
|
|
20
20
|
export function configureOfflineQueries(_queryClient) { }
|
|
21
|
+
function sortObjectKeys(value) {
|
|
22
|
+
if (value === null || value === undefined)
|
|
23
|
+
return value;
|
|
24
|
+
if (typeof value !== "object")
|
|
25
|
+
return value;
|
|
26
|
+
if (Array.isArray(value))
|
|
27
|
+
return value.map(sortObjectKeys);
|
|
28
|
+
const sorted = {};
|
|
29
|
+
Object.keys(value).sort().forEach((key) => { sorted[key] = sortObjectKeys(value[key]); });
|
|
30
|
+
return sorted;
|
|
31
|
+
}
|
|
32
|
+
export function serializeMutationKey(mutationKey) {
|
|
33
|
+
try {
|
|
34
|
+
if (typeof mutationKey === "string")
|
|
35
|
+
return mutationKey;
|
|
36
|
+
return JSON.stringify(sortObjectKeys(mutationKey));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return String(mutationKey);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
21
42
|
const DEFAULT_QUEUE_CONFIG = { enabled: true, maxSize: 100, persist: true, storageKey: "tanstack-query-offline-queue", autoExecuteInterval: 5000, executeOnReconnect: true, operationTimeout: 30000, concurrency: 3 };
|
|
22
43
|
export function calculateExponentialBackoff(attempt, baseDelay = 1000, maxDelay = 30000) {
|
|
23
44
|
const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
|
|
@@ -43,6 +64,9 @@ export class OfflineQueueManager {
|
|
|
43
64
|
this.unsubscribeOnline = null;
|
|
44
65
|
this.executingOperations = new Set();
|
|
45
66
|
this.config = { ...DEFAULT_QUEUE_CONFIG, ...config };
|
|
67
|
+
if (!this.config.enabled) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
46
70
|
if (this.config.persist) {
|
|
47
71
|
this.loadQueue();
|
|
48
72
|
}
|
|
@@ -54,6 +78,9 @@ export class OfflineQueueManager {
|
|
|
54
78
|
}
|
|
55
79
|
}
|
|
56
80
|
async add(operation) {
|
|
81
|
+
if (!this.config.enabled) {
|
|
82
|
+
throw new Error("Offline queue is disabled");
|
|
83
|
+
}
|
|
57
84
|
const id = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
58
85
|
const newOperation = { ...operation, id, createdAt: new Date(), retryCount: 0 };
|
|
59
86
|
if (this.queue.length >= this.config.maxSize) {
|
|
@@ -90,6 +117,9 @@ export class OfflineQueueManager {
|
|
|
90
117
|
await this.persistQueue();
|
|
91
118
|
} }
|
|
92
119
|
async execute() {
|
|
120
|
+
if (!this.config.enabled) {
|
|
121
|
+
return { success: 0, failed: 0, skipped: this.queue.length };
|
|
122
|
+
}
|
|
93
123
|
if (this.isExecuting) {
|
|
94
124
|
return { success: 0, failed: 0, skipped: this.queue.length };
|
|
95
125
|
}
|
|
@@ -141,8 +171,9 @@ export class OfflineQueueManager {
|
|
|
141
171
|
}
|
|
142
172
|
this.executingOperations.add(operation.id);
|
|
143
173
|
try {
|
|
144
|
-
const mutationKey =
|
|
145
|
-
const
|
|
174
|
+
const mutationKey = serializeMutationKey(operation.mutationKey);
|
|
175
|
+
const legacyMutationKey = Array.isArray(operation.mutationKey) ? operation.mutationKey.join("-") : String(operation.mutationKey);
|
|
176
|
+
const mutationFn = mutationRegistry.get(mutationKey) || mutationRegistry.get(legacyMutationKey) || operation.mutationFn;
|
|
146
177
|
const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error("Operation timeout")), this.config.operationTimeout); });
|
|
147
178
|
await Promise.race([mutationFn(), timeoutPromise]);
|
|
148
179
|
await this.remove(operation.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../src/features/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../src/features/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AAuBvF,MAAM,WAAW,cAAc;IAAG,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE;QAAE,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;KAAE,CAAA;CAAE;AAC1J,wBAAgB,oBAAoB,CAAC,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE;QAAE,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;KAAE,CAAA;CAAE,CAiBtK;AACD,wBAAgB,eAAe,CAAC,UAAU,SAAyB,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,SAAS,GAAG,SAAS,CAa/I;AACD,wBAAgB,UAAU,CAAC,GAAG,SAAyB,GAAG,IAAI,CAA0D;AACxH,wBAAgB,iBAAiB,CAAC,GAAG,SAAyB,EAAE,MAAM,SAAyB,GAAG,IAAI,CAQrG;AACD,wBAAsB,kBAAkB,CAAC,eAAe,oBAAyB,EAAE,YAAY,oBAAyB,EAAE,gBAAgB,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAWlO;AACD,wBAAgB,gBAAgB,CAAC,GAAG,SAAyB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CASjJ;AACD,wBAAgB,eAAe,CAAC,GAAG,SAAyB,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA;CAAE,CAS9L;AACD,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TIME_CONSTANTS } from "../core/config.js";
|
|
1
2
|
function isSerializable(data) {
|
|
2
3
|
try {
|
|
3
4
|
JSON.stringify(data);
|
|
@@ -54,7 +55,7 @@ function createSafeStorage(storage, key) {
|
|
|
54
55
|
};
|
|
55
56
|
}
|
|
56
57
|
export function createPersistOptions(config = {}) {
|
|
57
|
-
const { maxAge =
|
|
58
|
+
const { maxAge = TIME_CONSTANTS.ONE_DAY, onlyPersistSuccess = true, dehydrateOptions } = config;
|
|
58
59
|
return {
|
|
59
60
|
maxAge,
|
|
60
61
|
dehydrateOptions: {
|
|
@@ -120,7 +121,7 @@ export function clearCache(key = "tanstack-query-cache") { try {
|
|
|
120
121
|
window.localStorage.removeItem(key);
|
|
121
122
|
}
|
|
122
123
|
catch { } }
|
|
123
|
-
export function clearExpiredCache(key = "tanstack-query-cache", maxAge =
|
|
124
|
+
export function clearExpiredCache(key = "tanstack-query-cache", maxAge = TIME_CONSTANTS.ONE_DAY) {
|
|
124
125
|
try {
|
|
125
126
|
const stored = window.localStorage.getItem(key);
|
|
126
127
|
if (!stored)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDataGuardMutation.d.ts","sourceRoot":"","sources":["../../src/hooks/useDataGuardMutation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAA8B,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"useDataGuardMutation.d.ts","sourceRoot":"","sources":["../../src/hooks/useDataGuardMutation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAA8B,MAAM,uBAAuB,CAAC;AAOzF,MAAM,WAAW,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAE,SAAQ,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC;IACzI,aAAa;IACb,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,SAAS,eAAe,GAAG,eAAe,EAC/C,MAAM,GAAG,KAAK,EACd,UAAU,SAAS,eAAe,GAAG,eAAe,EACpD,QAAQ,GAAG,OAAO,EAElB,UAAU,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,KAAK,CAAC,EAChD,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,GACtE,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAkHxD"}
|
|
@@ -2,21 +2,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
|
|
2
2
|
import { useMutation } from "./useMutation.js";
|
|
3
3
|
import { ConflictError } from "../types/dataGuard.js";
|
|
4
4
|
import { hashObject, markRecentlyUpdated, clearRecentlyUpdated, updateFamilyMetadata } from "../utils/dataGuard.js";
|
|
5
|
-
|
|
6
|
-
* Check if a query key starts with a given prefix
|
|
7
|
-
*/
|
|
8
|
-
function startsWithKeyPrefix(key, prefix) {
|
|
9
|
-
const k = Array.isArray(key) ? key : [key];
|
|
10
|
-
const p = Array.isArray(prefix) ? prefix : [prefix];
|
|
11
|
-
if (p.length > k.length)
|
|
12
|
-
return false;
|
|
13
|
-
for (let i = 0; i < p.length; i++) {
|
|
14
|
-
if (JSON.stringify(k[i]) !== JSON.stringify(p[i])) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
5
|
+
import { startsWithKeyPrefix } from "../utils/queryKey.js";
|
|
20
6
|
/**
|
|
21
7
|
* 带数据防护的 Mutation Hook
|
|
22
8
|
*
|
|
@@ -34,9 +34,9 @@ export function useMutation(options) {
|
|
|
34
34
|
const { optimistic, onMutate, onError, onSuccess, onSettled, ...restOptions } = options;
|
|
35
35
|
const mutationConfig = {
|
|
36
36
|
...restOptions,
|
|
37
|
-
retry: restOptions.retry ?? DEFAULT_MUTATION_CONFIG
|
|
38
|
-
retryDelay: restOptions.retryDelay ?? DEFAULT_MUTATION_CONFIG
|
|
39
|
-
gcTime: restOptions.gcTime ?? DEFAULT_MUTATION_CONFIG
|
|
37
|
+
retry: restOptions.retry ?? DEFAULT_MUTATION_CONFIG.retry,
|
|
38
|
+
retryDelay: restOptions.retryDelay ?? DEFAULT_MUTATION_CONFIG.retryDelay,
|
|
39
|
+
gcTime: restOptions.gcTime ?? DEFAULT_MUTATION_CONFIG.gcTime
|
|
40
40
|
};
|
|
41
41
|
if (!optimistic) {
|
|
42
42
|
if (onMutate) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataGuard.d.ts","sourceRoot":"","sources":["../../src/types/dataGuard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B,CAAC,CAAC;IAC3C,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"dataGuard.d.ts","sourceRoot":"","sources":["../../src/types/dataGuard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B,CAAC,CAAC;IAC3C,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;CACrE;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,GAAG,CAAC;IACZ,QAAQ,EAAE,GAAG,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sBAAsB;IACtB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,yBAAyB;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB;IACjB,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACpD,eAAe;IACf,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CACpD;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACnB,OAAO,EAAE,GAAG;gBAAZ,OAAO,EAAE,GAAG;CAIhC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataGuard.d.ts","sourceRoot":"","sources":["../../src/utils/dataGuard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC3B,MAAM,uBAAuB,CAAC;AA+
|
|
1
|
+
{"version":3,"file":"dataGuard.d.ts","sourceRoot":"","sources":["../../src/utils/dataGuard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC3B,MAAM,uBAAuB,CAAC;AA+B/B;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAO3C;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,eAAe,EACtD,OAAO,EAAE,0BAA0B,CAAC,CAAC,CAAC,EACtC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,SAAS,EACjD,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,gBAAqB,GAC7B;IACD,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,YAAY,EAAE,GAAG,CAAC;CACnB,CAqJA;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,eAAe,EACrD,IAAI,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAClC,0BAA0B,CAAC,CAAC,CAAC,CAK/B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,eAAe,EAC3D,IAAI,EAAE,0BAA0B,CAAC,CAAC,CAAC,EACnC,SAAS,EAAE,MAAM,GAAG,MAAM,GACzB,0BAA0B,CAAC,CAAC,CAAC,CAY/B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,eAAe,EAC5D,IAAI,EAAE,0BAA0B,CAAC,CAAC,CAAC,EACnC,SAAS,EAAE,MAAM,GAAG,MAAM,GACzB,0BAA0B,CAAC,CAAC,CAAC,CAU/B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,eAAe,EAC5D,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,QAAQ,EACnB,QAAQ,EAAE,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,GAC/C,IAAI,CAiCN"}
|
package/dist/utils/dataGuard.js
CHANGED
|
@@ -1,18 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Check if a query key starts with a given prefix
|
|
3
|
-
*/
|
|
4
|
-
function startsWithKeyPrefix(key, prefix) {
|
|
5
|
-
const k = Array.isArray(key) ? key : [key];
|
|
6
|
-
const p = Array.isArray(prefix) ? prefix : [prefix];
|
|
7
|
-
if (p.length > k.length)
|
|
8
|
-
return false;
|
|
9
|
-
for (let i = 0; i < p.length; i++) {
|
|
10
|
-
if (JSON.stringify(k[i]) !== JSON.stringify(p[i])) {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
1
|
+
import { startsWithKeyPrefix } from "./queryKey.js";
|
|
16
2
|
/**
|
|
17
3
|
* 简单的字符串哈希函数(DJB2算法变体)
|
|
18
4
|
*/
|
|
@@ -156,7 +142,11 @@ export function applyDataGuard(newData, cached, queryKey, options = {}) {
|
|
|
156
142
|
shouldReject = true;
|
|
157
143
|
reason = "内容哈希相同,数据未变化";
|
|
158
144
|
}
|
|
159
|
-
else if (cachedHash &&
|
|
145
|
+
else if (cachedHash &&
|
|
146
|
+
cached._recentlyUpdatedIds &&
|
|
147
|
+
(Array.isArray(cached._recentlyUpdatedIds)
|
|
148
|
+
? cached._recentlyUpdatedIds.length > 0
|
|
149
|
+
: cached._recentlyUpdatedIds.size > 0)) {
|
|
160
150
|
// 检查最近更新的项是否被回退
|
|
161
151
|
let hasRevert = false;
|
|
162
152
|
for (const id of cached._recentlyUpdatedIds) {
|
|
@@ -201,11 +191,15 @@ export function addHashToData(data) {
|
|
|
201
191
|
* 标记最近更新的项
|
|
202
192
|
*/
|
|
203
193
|
export function markRecentlyUpdated(data, updatedId) {
|
|
204
|
-
const
|
|
205
|
-
|
|
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
|
+
}
|
|
206
200
|
return {
|
|
207
201
|
...data,
|
|
208
|
-
_recentlyUpdatedIds:
|
|
202
|
+
_recentlyUpdatedIds: existing
|
|
209
203
|
};
|
|
210
204
|
}
|
|
211
205
|
/**
|
|
@@ -214,11 +208,11 @@ export function markRecentlyUpdated(data, updatedId) {
|
|
|
214
208
|
export function clearRecentlyUpdated(data, updatedId) {
|
|
215
209
|
if (!data._recentlyUpdatedIds)
|
|
216
210
|
return data;
|
|
217
|
-
const
|
|
218
|
-
|
|
211
|
+
const existing = Array.isArray(data._recentlyUpdatedIds) ? data._recentlyUpdatedIds : Array.from(data._recentlyUpdatedIds);
|
|
212
|
+
const remaining = existing.filter((id) => id !== updatedId);
|
|
219
213
|
return {
|
|
220
214
|
...data,
|
|
221
|
-
_recentlyUpdatedIds:
|
|
215
|
+
_recentlyUpdatedIds: remaining.length > 0 ? remaining : undefined
|
|
222
216
|
};
|
|
223
217
|
}
|
|
224
218
|
/**
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { getNetworkInfo, getNetworkSpeed, isFastNetwork, isSlowNetwork, type Nav
|
|
|
3
3
|
export { batchRemoveItems, batchUpdateItems, conditionalUpdateItems, createAddItemConfig, createListOperationConfig, createRemoveItemConfig, createUpdateItemConfig, type ListOperationVariables, listUpdater, reorderItems } from "./optimisticUtils.js";
|
|
4
4
|
export { keepPreviousData, stableListPlaceholder } from "./placeholderData.js";
|
|
5
5
|
export { getPrefetchManager, type InteractionRecord, type NetworkSpeed, type PredictionResult, type PrefetchConfig, type PrefetchStats, type PrefetchTask, resetPrefetchManager, SmartPrefetchManager } from "./prefetchManager.js";
|
|
6
|
-
export { createQueryKeyFactory, createSimpleQueryKeyFactory, extractParamsFromKey, isQueryKeyEqual, type NormalizeConfig, normalizeQueryParams, type QueryKeyFactory, type QueryKeyFactoryConfig } from "./queryKey.js";
|
|
6
|
+
export { createQueryKeyFactory, createSimpleQueryKeyFactory, extractParamsFromKey, isQueryKeyEqual, startsWithKeyPrefix, 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
9
|
export { applyDataGuard, addHashToData, hashObject, markRecentlyUpdated, clearRecentlyUpdated, updateFamilyMetadata } from "./dataGuard.js";
|
|
@@ -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,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,KAAK,eAAe,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,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,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/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export { getNetworkInfo, getNetworkSpeed, isFastNetwork, isSlowNetwork } from ".
|
|
|
3
3
|
export { batchRemoveItems, batchUpdateItems, conditionalUpdateItems, createAddItemConfig, createListOperationConfig, createRemoveItemConfig, createUpdateItemConfig, listUpdater, reorderItems } from "./optimisticUtils.js";
|
|
4
4
|
export { keepPreviousData, stableListPlaceholder } from "./placeholderData.js";
|
|
5
5
|
export { getPrefetchManager, resetPrefetchManager, SmartPrefetchManager } from "./prefetchManager.js";
|
|
6
|
-
export { createQueryKeyFactory, createSimpleQueryKeyFactory, extractParamsFromKey, isQueryKeyEqual, normalizeQueryParams } from "./queryKey.js";
|
|
6
|
+
export { createQueryKeyFactory, createSimpleQueryKeyFactory, extractParamsFromKey, isQueryKeyEqual, startsWithKeyPrefix, 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
9
|
export { applyDataGuard, addHashToData, hashObject, markRecentlyUpdated, clearRecentlyUpdated, updateFamilyMetadata } from "./dataGuard.js";
|
package/dist/utils/queryKey.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { QueryKey } from "@tanstack/react-query";
|
|
1
2
|
export interface NormalizeConfig<T = any> {
|
|
2
3
|
required?: (keyof T)[];
|
|
3
4
|
defaults?: Partial<T>;
|
|
@@ -21,4 +22,5 @@ export declare function createQueryKeyFactory<TParams = any>(config: QueryKeyFac
|
|
|
21
22
|
export declare function createSimpleQueryKeyFactory(namespace: string): QueryKeyFactory;
|
|
22
23
|
export declare function isQueryKeyEqual(key1: readonly any[], key2: readonly any[]): boolean;
|
|
23
24
|
export declare function extractParamsFromKey(queryKey: readonly any[]): Record<string, any> | undefined;
|
|
25
|
+
export declare function startsWithKeyPrefix(key: QueryKey, prefix: QueryKey): boolean;
|
|
24
26
|
//# sourceMappingURL=queryKey.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryKey.d.ts","sourceRoot":"","sources":["../../src/utils/queryKey.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,GAAG;IAAI,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE;AACtI,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAAE,MAAM,GAAE,eAAe,CAAC,CAAC,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAuB/I;AACD,MAAM,WAAW,qBAAqB,CAAC,OAAO,GAAG,GAAG;IAAI,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;CAAE;AACvH,MAAM,WAAW,eAAe,CAAC,OAAO,GAAG,GAAG;IAAI,GAAG,EAAE,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;CAAE;AAC/X,wBAAgB,qBAAqB,CAAC,OAAO,GAAG,GAAG,EAAE,MAAM,EAAE,qBAAqB,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,OAAO,CAAC,CAUrH;AACD,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAAiD;AAChI,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,EAAE,GAAG,OAAO,CAUnF;AACD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAI9F"}
|
|
1
|
+
{"version":3,"file":"queryKey.d.ts","sourceRoot":"","sources":["../../src/utils/queryKey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,GAAG;IAAI,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE;AACtI,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAAE,MAAM,GAAE,eAAe,CAAC,CAAC,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAuB/I;AACD,MAAM,WAAW,qBAAqB,CAAC,OAAO,GAAG,GAAG;IAAI,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;CAAE;AACvH,MAAM,WAAW,eAAe,CAAC,OAAO,GAAG,GAAG;IAAI,GAAG,EAAE,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;CAAE;AAC/X,wBAAgB,qBAAqB,CAAC,OAAO,GAAG,GAAG,EAAE,MAAM,EAAE,qBAAqB,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,OAAO,CAAC,CAUrH;AACD,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAAiD;AAChI,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,EAAE,GAAG,OAAO,CAUnF;AACD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAI9F;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAU5E"}
|
package/dist/utils/queryKey.js
CHANGED
|
@@ -75,3 +75,15 @@ export function extractParamsFromKey(queryKey) {
|
|
|
75
75
|
}
|
|
76
76
|
return undefined;
|
|
77
77
|
}
|
|
78
|
+
export function startsWithKeyPrefix(key, prefix) {
|
|
79
|
+
const k = Array.isArray(key) ? key : [key];
|
|
80
|
+
const p = Array.isArray(prefix) ? prefix : [prefix];
|
|
81
|
+
if (p.length > k.length)
|
|
82
|
+
return false;
|
|
83
|
+
for (let i = 0; i < p.length; i++) {
|
|
84
|
+
if (JSON.stringify(k[i]) !== JSON.stringify(p[i])) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
}
|
package/package.json
CHANGED