xxf_react 0.8.5 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/CacheEntry.d.ts +28 -0
- package/dist/cache/CacheEntry.d.ts.map +1 -0
- package/dist/cache/CacheEntry.js +1 -0
- package/dist/cache/DiskCacheConfig.d.ts +56 -0
- package/dist/cache/DiskCacheConfig.d.ts.map +1 -0
- package/dist/cache/DiskCacheConfig.js +4 -0
- package/dist/cache/DiskLruCache.d.ts +69 -0
- package/dist/cache/DiskLruCache.d.ts.map +1 -0
- package/dist/cache/DiskLruCache.js +305 -0
- package/dist/cache/LruMetadata.d.ts +28 -0
- package/dist/cache/LruMetadata.d.ts.map +1 -0
- package/dist/cache/LruMetadata.js +6 -0
- package/dist/cache/index.d.ts +5 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +2 -0
- package/dist/event-bus/EventBus.d.ts +176 -0
- package/dist/event-bus/EventBus.d.ts.map +1 -0
- package/dist/event-bus/EventBus.js +278 -0
- package/dist/event-bus/EventDemo.d.ts +71 -0
- package/dist/event-bus/EventDemo.d.ts.map +1 -0
- package/dist/event-bus/EventDemo.js +76 -0
- package/dist/event-bus/EventHooks.d.ts +48 -0
- package/dist/event-bus/EventHooks.d.ts.map +1 -0
- package/dist/event-bus/EventHooks.js +73 -0
- package/dist/event-bus/index.d.ts +3 -0
- package/dist/event-bus/index.d.ts.map +1 -0
- package/dist/event-bus/index.js +2 -0
- package/dist/fetch/Fetch.d.ts +9 -0
- package/dist/fetch/Fetch.d.ts.map +1 -0
- package/dist/fetch/Fetch.js +54 -0
- package/dist/fetch/TimeoutError.d.ts +7 -0
- package/dist/fetch/TimeoutError.d.ts.map +1 -0
- package/dist/fetch/TimeoutError.js +23 -0
- package/dist/fetch/index.d.ts +3 -0
- package/dist/fetch/index.d.ts.map +1 -0
- package/dist/fetch/index.js +2 -0
- package/dist/flow/PromiseExt.d.ts +8 -0
- package/dist/flow/PromiseExt.d.ts.map +1 -0
- package/dist/flow/PromiseExt.js +50 -0
- package/dist/flow/PromiseLifecycle.d.ts +33 -0
- package/dist/flow/PromiseLifecycle.d.ts.map +1 -0
- package/dist/flow/PromiseLifecycle.js +37 -0
- package/dist/flow/PromiseLoading.d.ts +25 -0
- package/dist/flow/PromiseLoading.d.ts.map +1 -0
- package/dist/flow/PromiseLoading.js +30 -0
- package/dist/flow/index.d.ts +4 -0
- package/dist/flow/index.d.ts.map +1 -0
- package/dist/flow/index.js +3 -0
- package/dist/foundation/Copy.d.ts +8 -0
- package/dist/foundation/Copy.d.ts.map +1 -0
- package/dist/foundation/Copy.js +21 -0
- package/dist/foundation/Debug.d.ts +7 -0
- package/dist/foundation/Debug.d.ts.map +1 -0
- package/dist/foundation/Debug.js +12 -0
- package/dist/foundation/LayoutSize.d.ts +5 -0
- package/dist/foundation/LayoutSize.d.ts.map +1 -0
- package/dist/foundation/LayoutSize.js +1 -0
- package/dist/foundation/PerformanceMonitor.d.ts +13 -0
- package/dist/foundation/PerformanceMonitor.d.ts.map +1 -0
- package/dist/foundation/PerformanceMonitor.js +26 -0
- package/dist/foundation/index.d.ts +5 -0
- package/dist/foundation/index.d.ts.map +1 -0
- package/dist/foundation/index.js +4 -0
- package/dist/http/api/ApiBuilder.d.ts +251 -0
- package/dist/http/api/ApiBuilder.d.ts.map +1 -0
- package/dist/http/api/ApiBuilder.js +189 -0
- package/dist/http/api/index.d.ts +2 -0
- package/dist/http/api/index.d.ts.map +1 -0
- package/dist/http/api/index.js +1 -0
- package/dist/http/cache/HttpCache.d.ts +59 -0
- package/dist/http/cache/HttpCache.d.ts.map +1 -0
- package/dist/http/cache/HttpCache.js +215 -0
- package/dist/http/cache/index.d.ts +3 -0
- package/dist/http/cache/index.d.ts.map +1 -0
- package/dist/http/cache/index.js +2 -0
- package/dist/http/client/ApiStream.d.ts +80 -0
- package/dist/http/client/ApiStream.d.ts.map +1 -0
- package/dist/http/client/ApiStream.js +190 -0
- package/dist/http/client/HttpClient.d.ts +88 -0
- package/dist/http/client/HttpClient.d.ts.map +1 -0
- package/dist/http/client/HttpClient.js +381 -0
- package/dist/http/client/index.d.ts +3 -0
- package/dist/http/client/index.d.ts.map +1 -0
- package/dist/http/client/index.js +2 -0
- package/dist/http/demo/api-builder.demo.d.ts +102 -0
- package/dist/http/demo/api-builder.demo.d.ts.map +1 -0
- package/dist/http/demo/api-builder.demo.js +343 -0
- package/dist/http/index.d.ts +52 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +61 -0
- package/dist/http/interceptor/CacheInterceptor.d.ts +112 -0
- package/dist/http/interceptor/CacheInterceptor.d.ts.map +1 -0
- package/dist/http/interceptor/CacheInterceptor.js +6 -0
- package/dist/http/interceptor/DefaultCacheInterceptor.d.ts +53 -0
- package/dist/http/interceptor/DefaultCacheInterceptor.d.ts.map +1 -0
- package/dist/http/interceptor/DefaultCacheInterceptor.js +106 -0
- package/dist/http/interceptor/index.d.ts +3 -0
- package/dist/http/interceptor/index.d.ts.map +1 -0
- package/dist/http/interceptor/index.js +2 -0
- package/dist/http/models/ApiTypes.d.ts +54 -0
- package/dist/http/models/ApiTypes.d.ts.map +1 -0
- package/dist/http/models/ApiTypes.js +4 -0
- package/dist/http/models/CacheConfig.d.ts +58 -0
- package/dist/http/models/CacheConfig.d.ts.map +1 -0
- package/dist/http/models/CacheConfig.js +4 -0
- package/dist/http/models/CacheMode.d.ts +45 -0
- package/dist/http/models/CacheMode.d.ts.map +1 -0
- package/dist/http/models/CacheMode.js +45 -0
- package/dist/http/models/HttpClientConfig.d.ts +90 -0
- package/dist/http/models/HttpClientConfig.d.ts.map +1 -0
- package/dist/http/models/HttpClientConfig.js +4 -0
- package/dist/http/models/RequestConfig.d.ts +67 -0
- package/dist/http/models/RequestConfig.d.ts.map +1 -0
- package/dist/http/models/RequestConfig.js +4 -0
- package/dist/http/models/index.d.ts +24 -0
- package/dist/http/models/index.d.ts.map +1 -0
- package/dist/http/models/index.js +16 -0
- package/dist/http/types.d.ts +13 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/http/types.js +14 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/layout/button/XButton.d.ts +99 -0
- package/dist/layout/button/XButton.d.ts.map +1 -0
- package/dist/layout/button/XButton.js +131 -0
- package/dist/layout/hover/XHover.d.ts +147 -0
- package/dist/layout/hover/XHover.d.ts.map +1 -0
- package/dist/layout/hover/XHover.js +128 -0
- package/dist/layout/image/XImage.d.ts +35 -0
- package/dist/layout/image/XImage.d.ts.map +1 -0
- package/dist/layout/image/XImage.effects.d.ts +16 -0
- package/dist/layout/image/XImage.effects.d.ts.map +1 -0
- package/dist/layout/image/XImage.effects.js +77 -0
- package/dist/layout/image/XImage.js +261 -0
- package/dist/layout/image/XImage.types.d.ts +130 -0
- package/dist/layout/image/XImage.types.d.ts.map +1 -0
- package/dist/layout/image/XImage.types.js +2 -0
- package/dist/layout/image/XImageGallery.d.ts +76 -0
- package/dist/layout/image/XImageGallery.d.ts.map +1 -0
- package/dist/layout/image/XImageGallery.js +94 -0
- package/dist/layout/image/index.d.ts +12 -0
- package/dist/layout/image/index.d.ts.map +1 -0
- package/dist/layout/image/index.js +4 -0
- package/dist/layout/index.d.ts +12 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +11 -0
- package/dist/layout/resize/core/ResizeObserverHook.d.ts +41 -0
- package/dist/layout/resize/core/ResizeObserverHook.d.ts.map +1 -0
- package/dist/layout/resize/core/ResizeObserverHook.js +57 -0
- package/dist/layout/resize/core/SizedLayoutContext.d.ts +23 -0
- package/dist/layout/resize/core/SizedLayoutContext.d.ts.map +1 -0
- package/dist/layout/resize/core/SizedLayoutContext.js +23 -0
- package/dist/layout/resize/core/SizedLayoutProps.d.ts +19 -0
- package/dist/layout/resize/core/SizedLayoutProps.d.ts.map +1 -0
- package/dist/layout/resize/core/SizedLayoutProps.js +1 -0
- package/dist/layout/resize/impl/SizedContainer.d.ts +45 -0
- package/dist/layout/resize/impl/SizedContainer.d.ts.map +1 -0
- package/dist/layout/resize/impl/SizedContainer.js +65 -0
- package/dist/layout/resize/impl/SizedLayout.d.ts +45 -0
- package/dist/layout/resize/impl/SizedLayout.d.ts.map +1 -0
- package/dist/layout/resize/impl/SizedLayout.js +65 -0
- package/dist/layout/spinner/XSpinner.d.ts +43 -0
- package/dist/layout/spinner/XSpinner.d.ts.map +1 -0
- package/dist/layout/spinner/XSpinner.js +47 -0
- package/dist/layout/virtualized/VirtualizedConfig.d.ts +16 -0
- package/dist/layout/virtualized/VirtualizedConfig.d.ts.map +1 -0
- package/dist/layout/virtualized/VirtualizedConfig.js +15 -0
- package/dist/layout/visibility/ElementVisibilityHooks.d.ts +13 -0
- package/dist/layout/visibility/ElementVisibilityHooks.d.ts.map +1 -0
- package/dist/layout/visibility/ElementVisibilityHooks.js +119 -0
- package/dist/media/components/XVideo.d.ts +205 -0
- package/dist/media/components/XVideo.d.ts.map +1 -0
- package/dist/media/components/XVideo.js +297 -0
- package/dist/media/components/XVideoBufferingIndicator.d.ts +13 -0
- package/dist/media/components/XVideoBufferingIndicator.d.ts.map +1 -0
- package/dist/media/components/XVideoBufferingIndicator.js +13 -0
- package/dist/media/components/XVideoErrorIndicator.d.ts +15 -0
- package/dist/media/components/XVideoErrorIndicator.d.ts.map +1 -0
- package/dist/media/components/XVideoErrorIndicator.js +19 -0
- package/dist/media/index.d.ts +7 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +7 -0
- package/dist/media/playback-queue-store.d.ts +746 -0
- package/dist/media/playback-queue-store.d.ts.map +1 -0
- package/dist/media/playback-queue-store.js +670 -0
- package/dist/media/video-play-safe.d.ts +26 -0
- package/dist/media/video-play-safe.d.ts.map +1 -0
- package/dist/media/video-play-safe.js +56 -0
- package/dist/media/video-state.d.ts +38 -0
- package/dist/media/video-state.d.ts.map +1 -0
- package/dist/media/video-state.js +125 -0
- package/dist/models/ApiPageDataFieldDTO.d.ts +9 -0
- package/dist/models/ApiPageDataFieldDTO.d.ts.map +1 -0
- package/dist/models/ApiPageDataFieldDTO.js +1 -0
- package/dist/models/ApiResponse.d.ts +29 -0
- package/dist/models/ApiResponse.d.ts.map +1 -0
- package/dist/models/ApiResponse.js +32 -0
- package/dist/models/PaginationDTO.d.ts +8 -0
- package/dist/models/PaginationDTO.d.ts.map +1 -0
- package/dist/models/PaginationDTO.js +6 -0
- package/dist/models/index.d.ts +4 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +3 -0
- package/dist/refresh/LoadMoreAsync.d.ts +36 -0
- package/dist/refresh/LoadMoreAsync.d.ts.map +1 -0
- package/dist/refresh/LoadMoreAsync.js +55 -0
- package/dist/refresh/index.d.ts +2 -0
- package/dist/refresh/index.d.ts.map +1 -0
- package/dist/refresh/index.js +2 -0
- package/dist/responsive/BrowserAdapter.d.ts +26 -0
- package/dist/responsive/BrowserAdapter.d.ts.map +1 -0
- package/dist/responsive/BrowserAdapter.js +79 -0
- package/dist/responsive/ScreenAdapter.d.ts +2 -0
- package/dist/responsive/ScreenAdapter.d.ts.map +1 -0
- package/dist/responsive/ScreenAdapter.js +5 -0
- package/dist/responsive/index.d.ts +3 -0
- package/dist/responsive/index.d.ts.map +1 -0
- package/dist/responsive/index.js +3 -0
- package/dist/sse/SSEManager.d.ts +21 -0
- package/dist/sse/SSEManager.d.ts.map +1 -0
- package/dist/sse/SSEManager.js +73 -0
- package/dist/sse/SSERegistry.d.ts +20 -0
- package/dist/sse/SSERegistry.d.ts.map +1 -0
- package/dist/sse/SSERegistry.js +36 -0
- package/dist/sse/SSEStatus.d.ts +7 -0
- package/dist/sse/SSEStatus.d.ts.map +1 -0
- package/dist/sse/SSEStatus.js +7 -0
- package/dist/sse/UseSSE.d.ts +13 -0
- package/dist/sse/UseSSE.d.ts.map +1 -0
- package/dist/sse/UseSSE.js +39 -0
- package/dist/sse/index.d.ts +5 -0
- package/dist/sse/index.d.ts.map +1 -0
- package/dist/sse/index.js +5 -0
- package/dist/utils/MIME.d.ts +137 -0
- package/dist/utils/MIME.d.ts.map +1 -0
- package/dist/utils/MIME.js +192 -0
- package/dist/utils/Reload.d.ts +62 -0
- package/dist/utils/Reload.d.ts.map +1 -0
- package/dist/utils/Reload.js +66 -0
- package/dist/utils/ScrollToCenter.d.ts +72 -0
- package/dist/utils/ScrollToCenter.d.ts.map +1 -0
- package/dist/utils/ScrollToCenter.js +145 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/url-placholder.d.ts +14 -0
- package/dist/utils/url-placholder.d.ts.map +1 -0
- package/dist/utils/url-placholder.js +17 -0
- package/package.json +1 -1
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApiBuilder 使用示例
|
|
3
|
+
*
|
|
4
|
+
* 此文件演示 ApiBuilder 的核心特性:
|
|
5
|
+
* 1. 泛型累积 - 链式调用自动累积端点类型
|
|
6
|
+
* 2. Body 类型约束 - POST/PUT/PATCH 请求体类型检查
|
|
7
|
+
* 3. 端点名称字面量 - 调用不存在的端点会编译报错
|
|
8
|
+
* 4. 缓存策略 - CacheMode 控制缓存行为
|
|
9
|
+
* 5. 多次响应 - 支持缓存优先场景下的两次数据返回
|
|
10
|
+
*/
|
|
11
|
+
import { ApiBuilder } from '../api/ApiBuilder';
|
|
12
|
+
import { CacheMode } from '../models/CacheMode';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// 创建 API 服务
|
|
15
|
+
// ============================================================================
|
|
16
|
+
export const userApi = ApiBuilder.create({
|
|
17
|
+
baseUrl: 'https://api.example.com',
|
|
18
|
+
timeout: 10000,
|
|
19
|
+
defaultCache: {
|
|
20
|
+
mode: CacheMode.FirstRemote,
|
|
21
|
+
ttl: 5 * 60 * 1000,
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
// GET 请求 - 无路径参数
|
|
25
|
+
.get('getUsers', {
|
|
26
|
+
path: '/users',
|
|
27
|
+
cache: { mode: CacheMode.FirstCache },
|
|
28
|
+
})
|
|
29
|
+
// GET 请求 - 有路径参数
|
|
30
|
+
.get('getUser', {
|
|
31
|
+
path: '/users/{id}',
|
|
32
|
+
cache: { mode: CacheMode.IfCache, ttl: 60000 },
|
|
33
|
+
})
|
|
34
|
+
// GET 请求 - 分页
|
|
35
|
+
.get('getUsersPaginated', {
|
|
36
|
+
path: '/users/paginated',
|
|
37
|
+
})
|
|
38
|
+
// POST 请求 - 有 body 类型
|
|
39
|
+
.post('createUser', {
|
|
40
|
+
path: '/users',
|
|
41
|
+
})
|
|
42
|
+
// POST 请求 - 无 body 类型(触发器)
|
|
43
|
+
.post('activateUser', {
|
|
44
|
+
path: '/users/{id}/activate',
|
|
45
|
+
})
|
|
46
|
+
// PUT 请求 - 完整更新
|
|
47
|
+
.put('updateUser', {
|
|
48
|
+
path: '/users/{id}',
|
|
49
|
+
})
|
|
50
|
+
// PATCH 请求 - 部分更新
|
|
51
|
+
.patch('patchUser', {
|
|
52
|
+
path: '/users/{id}',
|
|
53
|
+
})
|
|
54
|
+
// DELETE 请求
|
|
55
|
+
.delete('deleteUser', {
|
|
56
|
+
path: '/users/{id}',
|
|
57
|
+
})
|
|
58
|
+
// 扩展 ky 实例(添加拦截器)
|
|
59
|
+
.extend({
|
|
60
|
+
hooks: {
|
|
61
|
+
beforeRequest: [
|
|
62
|
+
(request) => {
|
|
63
|
+
const token = 'mock-token';
|
|
64
|
+
request.headers.set('Authorization', `Bearer ${token}`);
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
.build();
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// 使用示例 - 类型安全调用
|
|
72
|
+
// ============================================================================
|
|
73
|
+
async function demo() {
|
|
74
|
+
// ✅ GET 无路径参数
|
|
75
|
+
const users = await userApi.getUsers();
|
|
76
|
+
console.log('Users:', users);
|
|
77
|
+
// ✅ GET 有路径参数
|
|
78
|
+
const user = await userApi.getUser({
|
|
79
|
+
pathParams: { id: '123' },
|
|
80
|
+
});
|
|
81
|
+
console.log('User:', user);
|
|
82
|
+
// ✅ GET 带 query 参数
|
|
83
|
+
const paginatedUsers = await userApi.getUsersPaginated({
|
|
84
|
+
query: { page: 1, pageSize: 10 },
|
|
85
|
+
});
|
|
86
|
+
console.log('Paginated:', paginatedUsers);
|
|
87
|
+
// ✅ POST 有 body 类型约束
|
|
88
|
+
const newUser = await userApi.createUser({
|
|
89
|
+
body: { name: 'John', email: 'john@example.com' },
|
|
90
|
+
});
|
|
91
|
+
console.log('Created:', newUser);
|
|
92
|
+
// ✅ POST 无 body(触发器)
|
|
93
|
+
await userApi.activateUser({
|
|
94
|
+
pathParams: { id: '123' },
|
|
95
|
+
});
|
|
96
|
+
// ✅ PUT 完整更新
|
|
97
|
+
const updatedUser = await userApi.updateUser({
|
|
98
|
+
pathParams: { id: '123' },
|
|
99
|
+
body: { name: 'John Updated', email: 'john.updated@example.com' },
|
|
100
|
+
});
|
|
101
|
+
console.log('Updated:', updatedUser);
|
|
102
|
+
// ✅ PATCH 部分更新
|
|
103
|
+
const patchedUser = await userApi.patchUser({
|
|
104
|
+
pathParams: { id: '123' },
|
|
105
|
+
body: { name: 'John Patched' },
|
|
106
|
+
});
|
|
107
|
+
console.log('Patched:', patchedUser);
|
|
108
|
+
// ✅ DELETE
|
|
109
|
+
await userApi.deleteUser({
|
|
110
|
+
pathParams: { id: '123' },
|
|
111
|
+
});
|
|
112
|
+
// ✅ 覆盖缓存配置
|
|
113
|
+
const freshUser = await userApi.getUser({
|
|
114
|
+
pathParams: { id: '123' },
|
|
115
|
+
cache: { mode: CacheMode.OnlyRemote },
|
|
116
|
+
});
|
|
117
|
+
console.log('Fresh:', freshUser);
|
|
118
|
+
}
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// CacheMode 缓存模式详解
|
|
121
|
+
// ============================================================================
|
|
122
|
+
/**
|
|
123
|
+
* CacheMode 枚举值说明:
|
|
124
|
+
*
|
|
125
|
+
* - OnlyRemote: 只请求网络,不使用缓存(适用于实时性要求高的数据)
|
|
126
|
+
* - OnlyCache: 只读取缓存,不请求网络(适用于离线场景)
|
|
127
|
+
* - FirstCache: 先返回缓存,再请求网络更新(可能返回两次数据)
|
|
128
|
+
* - FirstRemote: 先请求网络,失败时回退到缓存(网络优先)
|
|
129
|
+
* - IfCache: 有缓存则用缓存,无缓存则请求网络(只返回一次)
|
|
130
|
+
*/
|
|
131
|
+
/**
|
|
132
|
+
* 缓存模式使用示例
|
|
133
|
+
*/
|
|
134
|
+
async function cacheModeDemo() {
|
|
135
|
+
// 1. OnlyRemote - 始终请求网络,忽略缓存
|
|
136
|
+
// 适用场景:提交表单、实时数据
|
|
137
|
+
const realTimeData = await userApi.getUser({
|
|
138
|
+
pathParams: { id: '123' },
|
|
139
|
+
cache: { mode: CacheMode.OnlyRemote },
|
|
140
|
+
});
|
|
141
|
+
console.log('实时数据:', realTimeData);
|
|
142
|
+
// 2. OnlyCache - 只读缓存,不请求网络
|
|
143
|
+
// 适用场景:离线模式、快速展示历史数据
|
|
144
|
+
try {
|
|
145
|
+
const cachedData = await userApi.getUser({
|
|
146
|
+
pathParams: { id: '123' },
|
|
147
|
+
cache: { mode: CacheMode.OnlyCache },
|
|
148
|
+
});
|
|
149
|
+
console.log('缓存数据:', cachedData);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
console.log('无缓存数据');
|
|
153
|
+
}
|
|
154
|
+
// 3. IfCache - 有缓存用缓存,无缓存请求网络(只返回一次)
|
|
155
|
+
// 适用场景:静态资源、不常变化的配置
|
|
156
|
+
const configData = await userApi.getUsers({
|
|
157
|
+
cache: { mode: CacheMode.IfCache, ttl: 60 * 60 * 1000 }, // 1小时
|
|
158
|
+
});
|
|
159
|
+
console.log('配置数据:', configData);
|
|
160
|
+
// 4. FirstRemote - 优先网络,失败回退缓存(只返回一次)
|
|
161
|
+
// 适用场景:希望获取最新数据,但网络不稳定时有兜底
|
|
162
|
+
const freshData = await userApi.getUser({
|
|
163
|
+
pathParams: { id: '123' },
|
|
164
|
+
cache: { mode: CacheMode.FirstRemote },
|
|
165
|
+
});
|
|
166
|
+
console.log('最新数据:', freshData);
|
|
167
|
+
}
|
|
168
|
+
// ============================================================================
|
|
169
|
+
// 多次响应处理 - FirstCache 模式的核心特性
|
|
170
|
+
// ============================================================================
|
|
171
|
+
/**
|
|
172
|
+
* FirstCache 模式会返回两次数据:
|
|
173
|
+
* 1. 第一次:从缓存返回(如果有缓存),fromCache = true
|
|
174
|
+
* 2. 第二次:从网络返回最新数据,fromCache = false
|
|
175
|
+
*
|
|
176
|
+
* 这种模式非常适合:
|
|
177
|
+
* - 列表页快速展示 + 后台刷新
|
|
178
|
+
* - 详情页先显示旧数据,再更新为最新数据
|
|
179
|
+
* - 提升用户体验,减少白屏时间
|
|
180
|
+
*/
|
|
181
|
+
/**
|
|
182
|
+
* 方式一:使用 for await 处理多次响应
|
|
183
|
+
* 推荐用于需要处理每次响应的场景
|
|
184
|
+
*/
|
|
185
|
+
async function multiResponseWithForAwait() {
|
|
186
|
+
console.log('=== for await 方式 ===');
|
|
187
|
+
for await (const { data, fromCache } of userApi.getUser({
|
|
188
|
+
pathParams: { id: '123' },
|
|
189
|
+
cache: { mode: CacheMode.FirstCache },
|
|
190
|
+
})) {
|
|
191
|
+
if (fromCache) {
|
|
192
|
+
console.log('📦 缓存数据(快速展示):', data);
|
|
193
|
+
// 可以先用缓存数据渲染 UI
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
console.log('🌐 网络数据(最新):', data);
|
|
197
|
+
// 用最新数据更新 UI
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
console.log('✅ 请求完成');
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* 方式二:使用 subscribe 处理多次响应
|
|
204
|
+
* 推荐用于 React/Vue 等框架中的响应式更新
|
|
205
|
+
*/
|
|
206
|
+
async function multiResponseWithSubscribe() {
|
|
207
|
+
console.log('=== subscribe 方式 ===');
|
|
208
|
+
await userApi
|
|
209
|
+
.getUser({
|
|
210
|
+
pathParams: { id: '123' },
|
|
211
|
+
cache: { mode: CacheMode.FirstCache },
|
|
212
|
+
})
|
|
213
|
+
.subscribe({
|
|
214
|
+
onData: (data, fromCache) => {
|
|
215
|
+
if (fromCache) {
|
|
216
|
+
console.log('📦 缓存数据:', data);
|
|
217
|
+
// setState({ user: data, loading: false })
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
console.log('🌐 网络数据:', data);
|
|
221
|
+
// setState({ user: data, loading: false, isStale: false })
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
onError: (error) => {
|
|
225
|
+
console.error('❌ 请求失败:', error);
|
|
226
|
+
// setState({ error, loading: false })
|
|
227
|
+
},
|
|
228
|
+
onComplete: () => {
|
|
229
|
+
console.log('✅ 请求完成');
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* 方式三:只需要最终结果时使用 await
|
|
235
|
+
* 注意:await 只返回最后一次响应(网络数据)
|
|
236
|
+
*/
|
|
237
|
+
async function singleResponseWithAwait() {
|
|
238
|
+
console.log('=== await 方式(只获取最终结果)===');
|
|
239
|
+
// 直接 await 只会返回最终的网络数据
|
|
240
|
+
const user = await userApi.getUser({
|
|
241
|
+
pathParams: { id: '123' },
|
|
242
|
+
cache: { mode: CacheMode.FirstCache },
|
|
243
|
+
});
|
|
244
|
+
console.log('最终数据:', user);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* React 组件中的典型用法示例(伪代码)
|
|
248
|
+
*/
|
|
249
|
+
function reactUsageExample() {
|
|
250
|
+
/*
|
|
251
|
+
// React 组件示例
|
|
252
|
+
function UserProfile({ userId }: { userId: string }) {
|
|
253
|
+
const [user, setUser] = useState<User | null>(null)
|
|
254
|
+
const [isStale, setIsStale] = useState(false)
|
|
255
|
+
const [loading, setLoading] = useState(true)
|
|
256
|
+
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
let cancelled = false
|
|
259
|
+
|
|
260
|
+
// 使用 subscribe 处理多次响应
|
|
261
|
+
userApi.getUser({
|
|
262
|
+
pathParams: { id: userId },
|
|
263
|
+
cache: { mode: CacheMode.FirstCache }
|
|
264
|
+
}).subscribe({
|
|
265
|
+
onData: (data, fromCache) => {
|
|
266
|
+
if (cancelled) return
|
|
267
|
+
setUser(data)
|
|
268
|
+
setIsStale(fromCache) // 标记是否为陈旧数据
|
|
269
|
+
setLoading(false)
|
|
270
|
+
},
|
|
271
|
+
onError: (error) => {
|
|
272
|
+
if (cancelled) return
|
|
273
|
+
console.error(error)
|
|
274
|
+
setLoading(false)
|
|
275
|
+
}
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
return () => { cancelled = true }
|
|
279
|
+
}, [userId])
|
|
280
|
+
|
|
281
|
+
if (loading) return <div>加载中...</div>
|
|
282
|
+
if (!user) return <div>用户不存在</div>
|
|
283
|
+
|
|
284
|
+
return (
|
|
285
|
+
<div>
|
|
286
|
+
{isStale && <span className="badge">数据更新中...</span>}
|
|
287
|
+
<h1>{user.name}</h1>
|
|
288
|
+
<p>{user.email}</p>
|
|
289
|
+
</div>
|
|
290
|
+
)
|
|
291
|
+
}
|
|
292
|
+
*/
|
|
293
|
+
}
|
|
294
|
+
// ============================================================================
|
|
295
|
+
// 类型错误示例
|
|
296
|
+
// ============================================================================
|
|
297
|
+
/**
|
|
298
|
+
* 类型安全验证
|
|
299
|
+
*
|
|
300
|
+
* 注意:由于 TypeScript 对深层交叉类型的处理限制,
|
|
301
|
+
* 当链式调用超过 4 个端点时,类型推断可能不够精确。
|
|
302
|
+
* 建议:保持单个 builder 的端点数量在 4 个以内,或分批构建。
|
|
303
|
+
*
|
|
304
|
+
* 以下是简化版本的类型安全验证(2-3 个端点)
|
|
305
|
+
*/
|
|
306
|
+
const simpleApi = ApiBuilder.create({ baseUrl: 'http://test' })
|
|
307
|
+
.get('getUser', { path: '/users/{id}' })
|
|
308
|
+
.post('createUser', { path: '/users' })
|
|
309
|
+
.build();
|
|
310
|
+
function typeErrors() {
|
|
311
|
+
// ❌ body 类型不匹配(缺少 email)
|
|
312
|
+
// @ts-expect-error email is required
|
|
313
|
+
simpleApi.createUser({ body: { name: 'John' } });
|
|
314
|
+
// ❌ body 类型不匹配(错误的属性)
|
|
315
|
+
// @ts-expect-error wrong property
|
|
316
|
+
simpleApi.createUser({ body: { wrong: 'x' } });
|
|
317
|
+
// ❌ GET 请求不应该有 body
|
|
318
|
+
// @ts-expect-error body not allowed for GET
|
|
319
|
+
simpleApi.getUser({ pathParams: { id: '1' }, body: {} });
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* 类型兼容性验证示例
|
|
323
|
+
*/
|
|
324
|
+
function verifyTypeCompatibility() {
|
|
325
|
+
const api = ApiBuilder.create({ baseUrl: 'http://test' })
|
|
326
|
+
.get('getUser', { path: '/users/{id}' })
|
|
327
|
+
.get('getUsers', { path: '/users' })
|
|
328
|
+
.post('createUser', { path: '/users' })
|
|
329
|
+
.put('updateUser', { path: '/users/{id}' })
|
|
330
|
+
.delete('deleteUser', { path: '/users/{id}' })
|
|
331
|
+
.build();
|
|
332
|
+
// ✅ 使用类型断言确保 API 符合定义
|
|
333
|
+
// 注意:由于 TypeScript 深层交叉类型限制,需要通过 unknown 进行断言
|
|
334
|
+
const typedApi = api;
|
|
335
|
+
// 现在可以获得精确的类型检查
|
|
336
|
+
typedApi.createUser({ body: { name: 'John', email: 'john@test.com' } });
|
|
337
|
+
typedApi.getUser({ pathParams: { id: '1' } });
|
|
338
|
+
console.log('Typed API:', typedApi);
|
|
339
|
+
}
|
|
340
|
+
// ============================================================================
|
|
341
|
+
// 导出
|
|
342
|
+
// ============================================================================
|
|
343
|
+
export { demo, typeErrors, verifyTypeCompatibility, cacheModeDemo, multiResponseWithForAwait, multiResponseWithSubscribe, singleResponseWithAwait, reactUsageExample, };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP 网络框架
|
|
3
|
+
*
|
|
4
|
+
* 基于 ky + idb-keyval,支持:
|
|
5
|
+
* - 内存 + 磁盘双层缓存
|
|
6
|
+
* - 6 种缓存模式
|
|
7
|
+
* - AsyncGenerator 流式响应
|
|
8
|
+
* - 类 Retrofit 的 API 定义方式
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { ApiBuilder, CacheMode } from 'xxf_react/http'
|
|
13
|
+
*
|
|
14
|
+
* const userApi = ApiBuilder.create({
|
|
15
|
+
* baseUrl: 'https://api.example.com',
|
|
16
|
+
* })
|
|
17
|
+
* .get<User>('getUser', {
|
|
18
|
+
* path: '/users/{id}',
|
|
19
|
+
* cache: { mode: CacheMode.IfCache, ttl: 60000 },
|
|
20
|
+
* })
|
|
21
|
+
* .build()
|
|
22
|
+
*
|
|
23
|
+
* // 方式1: 简单 await
|
|
24
|
+
* const user = await userApi.getUser({ pathParams: { id: '123' } })
|
|
25
|
+
*
|
|
26
|
+
* // 方式2: for await 多次响应
|
|
27
|
+
* for await (const { data, fromCache } of userApi.getUser({ pathParams: { id: '123' } })) {
|
|
28
|
+
* console.log(data, fromCache)
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // 方式3: subscribe 安全消费
|
|
32
|
+
* await userApi.getUser({ pathParams: { id: '123' } }).subscribe({
|
|
33
|
+
* onData: (data, fromCache) => console.log(data),
|
|
34
|
+
* onError: (e) => console.error(e),
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export { CacheMode } from './types';
|
|
39
|
+
export type { ApiResult, ApiCallback } from './types';
|
|
40
|
+
export type { CacheConfig, CacheKeyRequest, CacheEntry, DiskLruCacheConfig, HttpCacheConfig, LruMetadataEntry, LruMetadata, } from './types';
|
|
41
|
+
export type { CacheInterceptor, CacheInterceptorContext, CacheInterceptorResult, } from './types';
|
|
42
|
+
/** 默认缓存拦截器:检查 HTTP 200 + JSON + ApiResponse.code */
|
|
43
|
+
export { defaultCacheInterceptor, createCacheInterceptor } from './interceptor';
|
|
44
|
+
export type { HttpClientConfig, RequestConfig, ApiOptions } from './types';
|
|
45
|
+
export type { ApiEndpoint, ApiDefinition, ApiEndpointWithBody, ApiEndpointWithoutBody, ApiEndpointWithBodyRequired, ApiEndpointWithBodyOptional, Simplify, } from './api';
|
|
46
|
+
/** 磁盘 LRU 缓存(从 cache 模块重导出) */
|
|
47
|
+
export { DiskLruCache } from '../cache';
|
|
48
|
+
/** HTTP 缓存(内存 + 磁盘双层) */
|
|
49
|
+
export { HttpCache } from './cache';
|
|
50
|
+
export { HttpClient, ApiStream } from './client';
|
|
51
|
+
export { ApiBuilder } from './api';
|
|
52
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAKnC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAKrD,YAAY,EAER,WAAW,EACX,eAAe,EAEf,UAAU,EAEV,kBAAkB,EAClB,eAAe,EAEf,gBAAgB,EAChB,WAAW,GACd,MAAM,SAAS,CAAA;AAKhB,YAAY,EACR,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACzB,MAAM,SAAS,CAAA;AAKhB,oDAAoD;AACpD,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAK/E,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAK1E,YAAY,EACR,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC3B,QAAQ,GACX,MAAM,OAAO,CAAA;AAKd,+BAA+B;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,yBAAyB;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAKnC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAKhD,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP 网络框架
|
|
3
|
+
*
|
|
4
|
+
* 基于 ky + idb-keyval,支持:
|
|
5
|
+
* - 内存 + 磁盘双层缓存
|
|
6
|
+
* - 6 种缓存模式
|
|
7
|
+
* - AsyncGenerator 流式响应
|
|
8
|
+
* - 类 Retrofit 的 API 定义方式
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { ApiBuilder, CacheMode } from 'xxf_react/http'
|
|
13
|
+
*
|
|
14
|
+
* const userApi = ApiBuilder.create({
|
|
15
|
+
* baseUrl: 'https://api.example.com',
|
|
16
|
+
* })
|
|
17
|
+
* .get<User>('getUser', {
|
|
18
|
+
* path: '/users/{id}',
|
|
19
|
+
* cache: { mode: CacheMode.IfCache, ttl: 60000 },
|
|
20
|
+
* })
|
|
21
|
+
* .build()
|
|
22
|
+
*
|
|
23
|
+
* // 方式1: 简单 await
|
|
24
|
+
* const user = await userApi.getUser({ pathParams: { id: '123' } })
|
|
25
|
+
*
|
|
26
|
+
* // 方式2: for await 多次响应
|
|
27
|
+
* for await (const { data, fromCache } of userApi.getUser({ pathParams: { id: '123' } })) {
|
|
28
|
+
* console.log(data, fromCache)
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // 方式3: subscribe 安全消费
|
|
32
|
+
* await userApi.getUser({ pathParams: { id: '123' } }).subscribe({
|
|
33
|
+
* onData: (data, fromCache) => console.log(data),
|
|
34
|
+
* onError: (e) => console.error(e),
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// 枚举
|
|
40
|
+
// ============================================================================
|
|
41
|
+
export { CacheMode } from './types';
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// 缓存拦截器实现
|
|
44
|
+
// ============================================================================
|
|
45
|
+
/** 默认缓存拦截器:检查 HTTP 200 + JSON + ApiResponse.code */
|
|
46
|
+
export { defaultCacheInterceptor, createCacheInterceptor } from './interceptor';
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// 缓存实现
|
|
49
|
+
// ============================================================================
|
|
50
|
+
/** 磁盘 LRU 缓存(从 cache 模块重导出) */
|
|
51
|
+
export { DiskLruCache } from '../cache';
|
|
52
|
+
/** HTTP 缓存(内存 + 磁盘双层) */
|
|
53
|
+
export { HttpCache } from './cache';
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// 客户端
|
|
56
|
+
// ============================================================================
|
|
57
|
+
export { HttpClient, ApiStream } from './client';
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// API Builder
|
|
60
|
+
// ============================================================================
|
|
61
|
+
export { ApiBuilder } from './api';
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 缓存拦截器相关类型
|
|
3
|
+
*
|
|
4
|
+
* 用于根据响应内容动态决定是否缓存
|
|
5
|
+
*/
|
|
6
|
+
import type { CacheKeyRequest } from '../models/CacheConfig';
|
|
7
|
+
/**
|
|
8
|
+
* 缓存拦截器上下文
|
|
9
|
+
*
|
|
10
|
+
* 包含响应的完整信息,供拦截器判断是否应该缓存
|
|
11
|
+
*
|
|
12
|
+
* @template T 响应数据类型
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* cacheInterceptor: (ctx) => {
|
|
17
|
+
* // 可以访问响应数据、HTTP 状态码、响应头等
|
|
18
|
+
* console.log(ctx.data) // 响应数据
|
|
19
|
+
* console.log(ctx.status) // HTTP 状态码
|
|
20
|
+
* console.log(ctx.headers) // 响应头
|
|
21
|
+
* console.log(ctx.request) // 请求信息
|
|
22
|
+
* console.log(ctx.cacheKey) // 缓存 key
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export interface CacheInterceptorContext<T = unknown> {
|
|
27
|
+
/** 响应数据(已解析的 JSON) */
|
|
28
|
+
data: T;
|
|
29
|
+
/** HTTP 状态码 */
|
|
30
|
+
status: number;
|
|
31
|
+
/** 响应头 */
|
|
32
|
+
headers: Headers;
|
|
33
|
+
/** 请求信息(用于调试或高级判断) */
|
|
34
|
+
request: CacheKeyRequest;
|
|
35
|
+
/** 缓存 key(用于调试或高级判断) */
|
|
36
|
+
cacheKey: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 缓存拦截器返回结果
|
|
40
|
+
*
|
|
41
|
+
* 当需要更精细控制时使用对象形式返回
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* // 简单返回 boolean
|
|
46
|
+
* cacheInterceptor: (ctx) => ctx.status === 200
|
|
47
|
+
*
|
|
48
|
+
* // 返回对象,可以覆盖 TTL
|
|
49
|
+
* cacheInterceptor: (ctx) => ({
|
|
50
|
+
* shouldCache: true,
|
|
51
|
+
* ttl: 10 * 60 * 1000, // 覆盖为 10 分钟
|
|
52
|
+
* })
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export interface CacheInterceptorResult {
|
|
56
|
+
/** 是否允许缓存 */
|
|
57
|
+
shouldCache: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* 可选:覆盖缓存 TTL (ms)
|
|
60
|
+
* 如果不指定,使用请求配置中的 ttl
|
|
61
|
+
*/
|
|
62
|
+
ttl?: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 缓存拦截器
|
|
66
|
+
*
|
|
67
|
+
* 在响应返回后、写入缓存前调用,用于根据响应内容决定是否缓存。
|
|
68
|
+
*
|
|
69
|
+
* ## 常见场景
|
|
70
|
+
* - 只缓存 HTTP 200 响应
|
|
71
|
+
* - 只缓存业务 code 为成功的响应
|
|
72
|
+
* - 根据响应头决定是否缓存
|
|
73
|
+
* - 根据响应内容动态调整缓存时间
|
|
74
|
+
*
|
|
75
|
+
* ## 返回值
|
|
76
|
+
* - `true`:允许缓存
|
|
77
|
+
* - `false`:不缓存
|
|
78
|
+
* - `CacheInterceptorResult`:精细控制(是否缓存 + 可选覆盖 TTL)
|
|
79
|
+
* - `Promise<...>`:支持异步判断
|
|
80
|
+
*
|
|
81
|
+
* @template T 响应数据类型
|
|
82
|
+
* @param context 拦截器上下文,包含响应的完整信息
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* // 示例 1:只缓存 HTTP 200
|
|
87
|
+
* cacheInterceptor: (ctx) => ctx.status === 200
|
|
88
|
+
*
|
|
89
|
+
* // 示例 2:检查业务 code
|
|
90
|
+
* cacheInterceptor: (ctx) => {
|
|
91
|
+
* const res = ctx.data as { code?: number }
|
|
92
|
+
* return res.code === 200
|
|
93
|
+
* }
|
|
94
|
+
*
|
|
95
|
+
* // 示例 3:检查响应头
|
|
96
|
+
* cacheInterceptor: (ctx) => {
|
|
97
|
+
* return ctx.headers.get('X-Cacheable') !== 'false'
|
|
98
|
+
* }
|
|
99
|
+
*
|
|
100
|
+
* // 示例 4:动态 TTL
|
|
101
|
+
* cacheInterceptor: (ctx) => {
|
|
102
|
+
* const res = ctx.data as { code?: number; cacheTtl?: number }
|
|
103
|
+
* if (res.code !== 200) return false
|
|
104
|
+
* return {
|
|
105
|
+
* shouldCache: true,
|
|
106
|
+
* ttl: res.cacheTtl ?? 5 * 60 * 1000,
|
|
107
|
+
* }
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export type CacheInterceptor<T = unknown> = (context: CacheInterceptorContext<T>) => boolean | CacheInterceptorResult | Promise<boolean | CacheInterceptorResult>;
|
|
112
|
+
//# sourceMappingURL=CacheInterceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CacheInterceptor.d.ts","sourceRoot":"","sources":["../../../src/http/interceptor/CacheInterceptor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,OAAO;IAChD,sBAAsB;IACtB,IAAI,EAAE,CAAC,CAAA;IACP,eAAe;IACf,MAAM,EAAE,MAAM,CAAA;IACd,UAAU;IACV,OAAO,EAAE,OAAO,CAAA;IAChB,sBAAsB;IACtB,OAAO,EAAE,eAAe,CAAA;IACxB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,sBAAsB;IACnC,aAAa;IACb,WAAW,EAAE,OAAO,CAAA;IACpB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,GAAG,OAAO,IAAI,CACxC,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,KAClC,OAAO,GAAG,sBAAsB,GAAG,OAAO,CAAC,OAAO,GAAG,sBAAsB,CAAC,CAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局缓存拦截器
|
|
3
|
+
* 用于 xxf_react/http 的 ApiBuilder
|
|
4
|
+
*/
|
|
5
|
+
import { CacheInterceptor } from './CacheInterceptor';
|
|
6
|
+
/**
|
|
7
|
+
* 默认缓存拦截器
|
|
8
|
+
*
|
|
9
|
+
* 只有满足以下条件才缓存:
|
|
10
|
+
* - HTTP 状态码 = 200
|
|
11
|
+
* - Content-Type 包含 application/json(不区分大小写)
|
|
12
|
+
* - data 是有效对象或数组
|
|
13
|
+
* - ApiResponse.code 存在且为成功值(0 或 200)
|
|
14
|
+
*
|
|
15
|
+
* 特殊处理:
|
|
16
|
+
* - code 字段支持 number 或 string 类型
|
|
17
|
+
* - 所有检查都有异常保护,异常时默认不缓存
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* ApiBuilder.create({
|
|
22
|
+
* baseUrl: '...',
|
|
23
|
+
* cacheInterceptor: defaultCacheInterceptor,
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const defaultCacheInterceptor: CacheInterceptor;
|
|
28
|
+
/**
|
|
29
|
+
* 创建自定义缓存拦截器
|
|
30
|
+
*
|
|
31
|
+
* 在默认检查基础上添加自定义逻辑。
|
|
32
|
+
* 默认检查通过后才会执行自定义检查。
|
|
33
|
+
*
|
|
34
|
+
* @param customCheck 自定义检查函数,在默认检查通过后执行
|
|
35
|
+
* @returns 组合后的缓存拦截器
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* // 额外检查:只缓存有 data 字段的响应
|
|
40
|
+
* const myInterceptor = createCacheInterceptor((ctx) => {
|
|
41
|
+
* const res = ctx.data as { data?: unknown }
|
|
42
|
+
* return res.data !== undefined
|
|
43
|
+
* })
|
|
44
|
+
*
|
|
45
|
+
* // 额外检查:只缓存列表数据
|
|
46
|
+
* const listInterceptor = createCacheInterceptor((ctx) => {
|
|
47
|
+
* const res = ctx.data as { data?: unknown[] }
|
|
48
|
+
* return Array.isArray(res.data) && res.data.length > 0
|
|
49
|
+
* })
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function createCacheInterceptor(customCheck?: (ctx: Parameters<CacheInterceptor>[0]) => boolean): CacheInterceptor;
|
|
53
|
+
//# sourceMappingURL=DefaultCacheInterceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultCacheInterceptor.d.ts","sourceRoot":"","sources":["../../../src/http/interceptor/DefaultCacheInterceptor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAGrD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,EAAE,gBAuCrC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CAClC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,GAChE,gBAAgB,CAiBlB"}
|