xxf_react 0.8.5 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +54 -0
- package/dist/http/interceptor/DefaultCacheInterceptor.d.ts.map +1 -0
- package/dist/http/interceptor/DefaultCacheInterceptor.js +111 -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,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 缓存条目
|
|
3
|
+
*
|
|
4
|
+
* 存储在内存缓存和磁盘缓存中的数据结构
|
|
5
|
+
*
|
|
6
|
+
* @template T 缓存数据类型
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const entry: CacheEntry<User> = {
|
|
11
|
+
* data: { id: '1', name: 'John' },
|
|
12
|
+
* timestamp: Date.now(),
|
|
13
|
+
* ttl: 5 * 60 * 1000, // 5 分钟
|
|
14
|
+
* key: 'GET:/users/1',
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export interface CacheEntry<T = unknown> {
|
|
19
|
+
/** 缓存数据 */
|
|
20
|
+
data: T;
|
|
21
|
+
/** 缓存时间戳 (ms) */
|
|
22
|
+
timestamp: number;
|
|
23
|
+
/** 过期时间 (ms),0 表示永不过期 */
|
|
24
|
+
ttl: number;
|
|
25
|
+
/** 缓存 key */
|
|
26
|
+
key: string;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=CacheEntry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CacheEntry.d.ts","sourceRoot":"","sources":["../../src/cache/CacheEntry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,OAAO;IACnC,WAAW;IACX,IAAI,EAAE,CAAC,CAAA;IACP,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,aAAa;IACb,GAAG,EAAE,MAAM,CAAA;CACd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 缓存存储配置
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* DiskLruCache 配置
|
|
6
|
+
*
|
|
7
|
+
* 用于配置基于 IndexedDB 的磁盘 LRU 缓存
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const diskCache = new DiskLruCache({
|
|
12
|
+
* dbName: 'my-app-cache',
|
|
13
|
+
* storeName: 'http-cache',
|
|
14
|
+
* maxSize: 500,
|
|
15
|
+
* cleanupThreshold: 0.1,
|
|
16
|
+
* })
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export interface DiskLruCacheConfig {
|
|
20
|
+
/** IndexedDB 数据库名 */
|
|
21
|
+
dbName: string;
|
|
22
|
+
/** 存储名(ObjectStore 名称) */
|
|
23
|
+
storeName: string;
|
|
24
|
+
/** 最大条目数 */
|
|
25
|
+
maxSize: number;
|
|
26
|
+
/**
|
|
27
|
+
* 清理阈值
|
|
28
|
+
*
|
|
29
|
+
* 超过 maxSize * (1 + cleanupThreshold) 后触发清理
|
|
30
|
+
* 默认 0.1,即超过 110% 时清理到 100%
|
|
31
|
+
*/
|
|
32
|
+
cleanupThreshold?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* HttpCache 配置
|
|
36
|
+
*
|
|
37
|
+
* 用于配置 HTTP 缓存(内存 + 磁盘双层)
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* const cache = new HttpCache({
|
|
42
|
+
* memoryMaxSize: 100,
|
|
43
|
+
* diskMaxSize: 500,
|
|
44
|
+
* dbName: 'my-app-cache',
|
|
45
|
+
* })
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export interface HttpCacheConfig {
|
|
49
|
+
/** 内存缓存最大条目数 */
|
|
50
|
+
memoryMaxSize: number;
|
|
51
|
+
/** 磁盘缓存最大条目数 */
|
|
52
|
+
diskMaxSize: number;
|
|
53
|
+
/** IndexedDB 数据库名 */
|
|
54
|
+
dbName: string;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=DiskCacheConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiskCacheConfig.d.ts","sourceRoot":"","sources":["../../src/cache/DiskCacheConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,kBAAkB;IAC/B,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY;IACZ,OAAO,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC5B,gBAAgB;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAA;CACjB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 基于 IndexedDB 的 LRU 磁盘缓存
|
|
3
|
+
*
|
|
4
|
+
* 特点:
|
|
5
|
+
* - 使用 idb-keyval 简化 IndexedDB 操作
|
|
6
|
+
* - 维护 LRU 元数据实现淘汰策略
|
|
7
|
+
* - 支持 TTL 过期
|
|
8
|
+
* - 批量清理优化性能
|
|
9
|
+
* - 防污染:返回数据的深拷贝
|
|
10
|
+
* - 使用快速选择算法优化淘汰性能 O(n)
|
|
11
|
+
*/
|
|
12
|
+
import type { CacheEntry } from './CacheEntry';
|
|
13
|
+
import type { DiskLruCacheConfig } from './DiskCacheConfig';
|
|
14
|
+
export declare class DiskLruCache {
|
|
15
|
+
private store;
|
|
16
|
+
private config;
|
|
17
|
+
private metadata;
|
|
18
|
+
private metadataDirty;
|
|
19
|
+
private flushTimer;
|
|
20
|
+
private evicting;
|
|
21
|
+
constructor(config: DiskLruCacheConfig);
|
|
22
|
+
/**
|
|
23
|
+
* 加载或初始化 LRU 元数据(失败返回空元数据)
|
|
24
|
+
*/
|
|
25
|
+
private loadMetadata;
|
|
26
|
+
/**
|
|
27
|
+
* 保存元数据到磁盘 (批量优化,延迟写入)
|
|
28
|
+
*/
|
|
29
|
+
private scheduleFlushMetadata;
|
|
30
|
+
/**
|
|
31
|
+
* 立即刷新元数据到磁盘(失败静默忽略)
|
|
32
|
+
*/
|
|
33
|
+
flush(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* 获取缓存(失败返回 null,不影响业务)
|
|
36
|
+
* @returns 缓存条目的深拷贝
|
|
37
|
+
*/
|
|
38
|
+
get<T>(key: string): Promise<CacheEntry<T> | null>;
|
|
39
|
+
/**
|
|
40
|
+
* 设置缓存(失败静默忽略,不影响业务)
|
|
41
|
+
*/
|
|
42
|
+
set<T>(key: string, data: T, ttl?: number): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* 删除缓存(失败静默忽略)
|
|
45
|
+
*/
|
|
46
|
+
delete(key: string): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* 检查缓存是否存在(不更新访问时间,失败返回 false)
|
|
49
|
+
*/
|
|
50
|
+
has(key: string): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* 淘汰最旧的缓存条目(失败静默忽略)
|
|
53
|
+
* 使用快速选择算法,平均时间复杂度 O(n)
|
|
54
|
+
*/
|
|
55
|
+
private evict;
|
|
56
|
+
/**
|
|
57
|
+
* 清空所有缓存(失败静默忽略)
|
|
58
|
+
*/
|
|
59
|
+
clear(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* 获取缓存数量(失败返回 0)
|
|
62
|
+
*/
|
|
63
|
+
size(): Promise<number>;
|
|
64
|
+
/**
|
|
65
|
+
* 获取所有缓存 key(失败返回空数组)
|
|
66
|
+
*/
|
|
67
|
+
keys(): Promise<string[]>;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=DiskLruCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiskLruCache.d.ts","sourceRoot":"","sources":["../../src/cache/DiskLruCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AA6D3D,qBAAa,YAAY;IACrB,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,MAAM,EAAE,kBAAkB;IAQtC;;OAEG;YACW,YAAY;IAiB1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkB7B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;;OAGG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAmCxD;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BlE;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAexC;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASxC;;;OAGG;YACW,KAAK;IAwCnB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAS7B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAQlC"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 基于 IndexedDB 的 LRU 磁盘缓存
|
|
3
|
+
*
|
|
4
|
+
* 特点:
|
|
5
|
+
* - 使用 idb-keyval 简化 IndexedDB 操作
|
|
6
|
+
* - 维护 LRU 元数据实现淘汰策略
|
|
7
|
+
* - 支持 TTL 过期
|
|
8
|
+
* - 批量清理优化性能
|
|
9
|
+
* - 防污染:返回数据的深拷贝
|
|
10
|
+
* - 使用快速选择算法优化淘汰性能 O(n)
|
|
11
|
+
*/
|
|
12
|
+
import { get, set, del, clear as clearStore, createStore } from 'idb-keyval';
|
|
13
|
+
const META_KEY = '__lru_metadata__';
|
|
14
|
+
/**
|
|
15
|
+
* 快速选择算法:找出数组中最小的 k 个元素
|
|
16
|
+
* 平均时间复杂度 O(n),比完整排序 O(n log n) 更高效
|
|
17
|
+
*/
|
|
18
|
+
function quickSelectSmallestK(items, k, getValue) {
|
|
19
|
+
if (k <= 0 || items.length === 0)
|
|
20
|
+
return [];
|
|
21
|
+
if (k >= items.length)
|
|
22
|
+
return items;
|
|
23
|
+
// 复制数组避免修改原数组
|
|
24
|
+
const arr = [...items];
|
|
25
|
+
const n = arr.length;
|
|
26
|
+
// 分区函数
|
|
27
|
+
const partition = (left, right, pivotIndex) => {
|
|
28
|
+
const pivotValue = getValue(arr[pivotIndex]);
|
|
29
|
+
[arr[pivotIndex], arr[right]] = [arr[right], arr[pivotIndex]];
|
|
30
|
+
let storeIndex = left;
|
|
31
|
+
for (let i = left; i < right; i++) {
|
|
32
|
+
if (getValue(arr[i]) < pivotValue) {
|
|
33
|
+
;
|
|
34
|
+
[arr[storeIndex], arr[i]] = [arr[i], arr[storeIndex]];
|
|
35
|
+
storeIndex++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// 将 pivot 移回正确位置
|
|
39
|
+
;
|
|
40
|
+
[arr[storeIndex], arr[right]] = [arr[right], arr[storeIndex]];
|
|
41
|
+
return storeIndex;
|
|
42
|
+
};
|
|
43
|
+
// 快速选择主逻辑
|
|
44
|
+
let left = 0;
|
|
45
|
+
let right = n - 1;
|
|
46
|
+
while (left < right) {
|
|
47
|
+
// 使用中间元素作为 pivot(比随机选择更稳定)
|
|
48
|
+
const pivotIndex = left + Math.floor((right - left) / 2);
|
|
49
|
+
const newPivotIndex = partition(left, right, pivotIndex);
|
|
50
|
+
if (newPivotIndex === k) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
else if (newPivotIndex < k) {
|
|
54
|
+
left = newPivotIndex + 1;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
right = newPivotIndex - 1;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 返回前 k 个元素
|
|
61
|
+
return arr.slice(0, k);
|
|
62
|
+
}
|
|
63
|
+
export class DiskLruCache {
|
|
64
|
+
constructor(config) {
|
|
65
|
+
this.metadata = null;
|
|
66
|
+
this.metadataDirty = false;
|
|
67
|
+
this.flushTimer = null;
|
|
68
|
+
this.evicting = false; // 防止并发淘汰
|
|
69
|
+
this.config = {
|
|
70
|
+
cleanupThreshold: 0.1,
|
|
71
|
+
...config,
|
|
72
|
+
};
|
|
73
|
+
this.store = createStore(config.dbName, config.storeName);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 加载或初始化 LRU 元数据(失败返回空元数据)
|
|
77
|
+
*/
|
|
78
|
+
async loadMetadata() {
|
|
79
|
+
if (this.metadata)
|
|
80
|
+
return this.metadata;
|
|
81
|
+
try {
|
|
82
|
+
const stored = await get(META_KEY, this.store);
|
|
83
|
+
if (stored) {
|
|
84
|
+
this.metadata = stored;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
this.metadata = { entries: {}, count: 0 };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// 加载失败,使用空元数据
|
|
92
|
+
this.metadata = { entries: {}, count: 0 };
|
|
93
|
+
}
|
|
94
|
+
return this.metadata;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 保存元数据到磁盘 (批量优化,延迟写入)
|
|
98
|
+
*/
|
|
99
|
+
scheduleFlushMetadata() {
|
|
100
|
+
if (this.flushTimer)
|
|
101
|
+
return;
|
|
102
|
+
this.metadataDirty = true;
|
|
103
|
+
this.flushTimer = setTimeout(() => {
|
|
104
|
+
this.flushTimer = null;
|
|
105
|
+
if (this.metadataDirty && this.metadata) {
|
|
106
|
+
set(META_KEY, this.metadata, this.store)
|
|
107
|
+
.then(() => {
|
|
108
|
+
this.metadataDirty = false;
|
|
109
|
+
})
|
|
110
|
+
.catch(() => {
|
|
111
|
+
// 静默处理写入错误,下次会重试
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}, 1000); // 1 秒后批量写入
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* 立即刷新元数据到磁盘(失败静默忽略)
|
|
118
|
+
*/
|
|
119
|
+
async flush() {
|
|
120
|
+
if (this.flushTimer) {
|
|
121
|
+
clearTimeout(this.flushTimer);
|
|
122
|
+
this.flushTimer = null;
|
|
123
|
+
}
|
|
124
|
+
if (this.metadataDirty && this.metadata) {
|
|
125
|
+
try {
|
|
126
|
+
await set(META_KEY, this.metadata, this.store);
|
|
127
|
+
this.metadataDirty = false;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// 刷新失败静默忽略,下次会重试
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 获取缓存(失败返回 null,不影响业务)
|
|
136
|
+
* @returns 缓存条目的深拷贝
|
|
137
|
+
*/
|
|
138
|
+
async get(key) {
|
|
139
|
+
try {
|
|
140
|
+
const meta = await this.loadMetadata();
|
|
141
|
+
// 检查是否存在
|
|
142
|
+
if (!meta.entries[key]) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const entry = await get(key, this.store);
|
|
146
|
+
if (!entry) {
|
|
147
|
+
// 数据丢失,清理元数据
|
|
148
|
+
delete meta.entries[key];
|
|
149
|
+
meta.count = Math.max(0, meta.count - 1);
|
|
150
|
+
this.scheduleFlushMetadata();
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
// 检查是否过期
|
|
154
|
+
if (entry.ttl > 0 && Date.now() - entry.timestamp > entry.ttl) {
|
|
155
|
+
await this.delete(key);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
// 更新访问时间
|
|
159
|
+
meta.entries[key] = { accessTime: Date.now() };
|
|
160
|
+
this.scheduleFlushMetadata();
|
|
161
|
+
return entry;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// IndexedDB 操作失败,返回 null 不影响业务
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* 设置缓存(失败静默忽略,不影响业务)
|
|
170
|
+
*/
|
|
171
|
+
async set(key, data, ttl = 0) {
|
|
172
|
+
try {
|
|
173
|
+
const meta = await this.loadMetadata();
|
|
174
|
+
const entry = {
|
|
175
|
+
data,
|
|
176
|
+
timestamp: Date.now(),
|
|
177
|
+
ttl,
|
|
178
|
+
key,
|
|
179
|
+
};
|
|
180
|
+
// 检查是否需要淘汰
|
|
181
|
+
if (!meta.entries[key] && meta.count >= this.config.maxSize) {
|
|
182
|
+
await this.evict();
|
|
183
|
+
}
|
|
184
|
+
await set(key, entry, this.store);
|
|
185
|
+
// 更新元数据
|
|
186
|
+
if (!meta.entries[key]) {
|
|
187
|
+
meta.count++;
|
|
188
|
+
}
|
|
189
|
+
meta.entries[key] = { accessTime: Date.now() };
|
|
190
|
+
this.scheduleFlushMetadata();
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// IndexedDB 操作失败,静默忽略不影响业务
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* 删除缓存(失败静默忽略)
|
|
198
|
+
*/
|
|
199
|
+
async delete(key) {
|
|
200
|
+
try {
|
|
201
|
+
const meta = await this.loadMetadata();
|
|
202
|
+
if (meta.entries[key]) {
|
|
203
|
+
await del(key, this.store);
|
|
204
|
+
delete meta.entries[key];
|
|
205
|
+
meta.count = Math.max(0, meta.count - 1);
|
|
206
|
+
this.scheduleFlushMetadata();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// 删除失败静默忽略
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 检查缓存是否存在(不更新访问时间,失败返回 false)
|
|
215
|
+
*/
|
|
216
|
+
async has(key) {
|
|
217
|
+
try {
|
|
218
|
+
const meta = await this.loadMetadata();
|
|
219
|
+
return !!meta.entries[key];
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* 淘汰最旧的缓存条目(失败静默忽略)
|
|
227
|
+
* 使用快速选择算法,平均时间复杂度 O(n)
|
|
228
|
+
*/
|
|
229
|
+
async evict() {
|
|
230
|
+
// 防止并发淘汰
|
|
231
|
+
if (this.evicting)
|
|
232
|
+
return;
|
|
233
|
+
this.evicting = true;
|
|
234
|
+
try {
|
|
235
|
+
const meta = await this.loadMetadata();
|
|
236
|
+
// 计算需要淘汰的数量
|
|
237
|
+
const evictCount = Math.ceil(this.config.maxSize * this.config.cleanupThreshold);
|
|
238
|
+
// 使用快速选择算法找出访问时间最早的 k 个条目 O(n)
|
|
239
|
+
const entries = Object.entries(meta.entries);
|
|
240
|
+
const toEvict = quickSelectSmallestK(entries, evictCount, ([, entry]) => entry.accessTime);
|
|
241
|
+
// 淘汰选中的条目
|
|
242
|
+
for (const [key] of toEvict) {
|
|
243
|
+
try {
|
|
244
|
+
await del(key, this.store);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// 单个删除失败继续处理其他
|
|
248
|
+
}
|
|
249
|
+
delete meta.entries[key];
|
|
250
|
+
meta.count = Math.max(0, meta.count - 1);
|
|
251
|
+
}
|
|
252
|
+
this.scheduleFlushMetadata();
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// 淘汰失败静默忽略
|
|
256
|
+
}
|
|
257
|
+
finally {
|
|
258
|
+
this.evicting = false;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* 清空所有缓存(失败静默忽略)
|
|
263
|
+
*/
|
|
264
|
+
async clear() {
|
|
265
|
+
// 取消待处理的元数据写入
|
|
266
|
+
if (this.flushTimer) {
|
|
267
|
+
clearTimeout(this.flushTimer);
|
|
268
|
+
this.flushTimer = null;
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
// 使用 idb-keyval 的 clear 方法一次性清空整个 store
|
|
272
|
+
await clearStore(this.store);
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// 清空失败静默忽略
|
|
276
|
+
}
|
|
277
|
+
// 重置内存中的元数据
|
|
278
|
+
this.metadata = { entries: {}, count: 0 };
|
|
279
|
+
this.metadataDirty = false;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* 获取缓存数量(失败返回 0)
|
|
283
|
+
*/
|
|
284
|
+
async size() {
|
|
285
|
+
try {
|
|
286
|
+
const meta = await this.loadMetadata();
|
|
287
|
+
return meta.count;
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return 0;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* 获取所有缓存 key(失败返回空数组)
|
|
295
|
+
*/
|
|
296
|
+
async keys() {
|
|
297
|
+
try {
|
|
298
|
+
const meta = await this.loadMetadata();
|
|
299
|
+
return Object.keys(meta.entries);
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return [];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LRU 缓存元数据
|
|
3
|
+
*
|
|
4
|
+
* 用于 DiskLruCache 内部管理缓存条目的访问顺序
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* LRU 元数据条目
|
|
8
|
+
*
|
|
9
|
+
* 单个缓存条目的元数据信息
|
|
10
|
+
*/
|
|
11
|
+
export interface LruMetadataEntry {
|
|
12
|
+
/** 最后访问时间 (ms) */
|
|
13
|
+
accessTime: number;
|
|
14
|
+
/** 数据大小估算 (可选,用于未来扩展) */
|
|
15
|
+
size?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* LRU 元数据
|
|
19
|
+
*
|
|
20
|
+
* 存储在 IndexedDB 中的元数据,用于 LRU 淘汰算法
|
|
21
|
+
*/
|
|
22
|
+
export interface LruMetadata {
|
|
23
|
+
/** 所有缓存 key 及其元数据 */
|
|
24
|
+
entries: Record<string, LruMetadataEntry>;
|
|
25
|
+
/** 总条目数 */
|
|
26
|
+
count: number;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=LruMetadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LruMetadata.d.ts","sourceRoot":"","sources":["../../src/cache/LruMetadata.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC7B,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACzC,WAAW;IACX,KAAK,EAAE,MAAM,CAAA;CAChB"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { CacheEntry } from './CacheEntry';
|
|
2
|
+
export type { DiskLruCacheConfig, HttpCacheConfig } from './DiskCacheConfig';
|
|
3
|
+
export type { LruMetadataEntry, LruMetadata } from './LruMetadata';
|
|
4
|
+
export { DiskLruCache } from './DiskLruCache';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAG5E,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA"}
|