xxf_react 0.7.4 → 0.7.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/README.md +15 -14
- package/dist/cache/CacheEntry.d.ts.map +1 -0
- package/dist/cache/DiskCacheConfig.d.ts.map +1 -0
- package/dist/{http/cache → cache}/DiskLruCache.d.ts +4 -1
- package/dist/cache/DiskLruCache.d.ts.map +1 -0
- package/dist/{http/cache → cache}/DiskLruCache.js +55 -4
- package/dist/cache/LruMetadata.d.ts.map +1 -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/http/api/ApiBuilder.d.ts +10 -1
- package/dist/http/api/ApiBuilder.d.ts.map +1 -1
- package/dist/http/api/ApiBuilder.js +3 -1
- package/dist/http/api/index.d.ts +1 -1
- package/dist/http/api/index.d.ts.map +1 -1
- package/dist/http/api/index.js +1 -1
- package/dist/http/cache/HttpCache.d.ts +1 -1
- package/dist/http/cache/HttpCache.d.ts.map +1 -1
- package/dist/http/cache/HttpCache.js +1 -1
- package/dist/http/cache/index.d.ts +1 -1
- package/dist/http/cache/index.d.ts.map +1 -1
- package/dist/http/cache/index.js +1 -1
- package/dist/http/client/HttpClient.js +1 -1
- package/dist/http/demo/api-builder.demo.d.ts +59 -10
- package/dist/http/demo/api-builder.demo.d.ts.map +1 -1
- package/dist/http/demo/api-builder.demo.js +190 -10
- package/dist/http/index.d.ts +13 -3
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +22 -6
- package/dist/http/{models → interceptor}/CacheInterceptor.d.ts +1 -1
- package/dist/http/interceptor/CacheInterceptor.d.ts.map +1 -0
- package/dist/http/interceptor/DefaultCacheInterceptor.d.ts +39 -0
- package/dist/http/interceptor/DefaultCacheInterceptor.d.ts.map +1 -0
- package/dist/http/interceptor/DefaultCacheInterceptor.js +63 -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/HttpClientConfig.d.ts +15 -2
- package/dist/http/models/HttpClientConfig.d.ts.map +1 -1
- package/dist/http/models/index.d.ts +4 -4
- package/dist/http/models/index.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +5 -1
- package/dist/http/cache/DiskLruCache.d.ts.map +0 -1
- package/dist/http/models/CacheEntry.d.ts.map +0 -1
- package/dist/http/models/CacheInterceptor.d.ts.map +0 -1
- package/dist/http/models/DiskCacheConfig.d.ts.map +0 -1
- package/dist/http/models/LruMetadata.d.ts.map +0 -1
- /package/dist/{http/models → cache}/CacheEntry.d.ts +0 -0
- /package/dist/{http/models → cache}/CacheEntry.js +0 -0
- /package/dist/{http/models → cache}/DiskCacheConfig.d.ts +0 -0
- /package/dist/{http/models → cache}/DiskCacheConfig.js +0 -0
- /package/dist/{http/models → cache}/LruMetadata.d.ts +0 -0
- /package/dist/{http/models → cache}/LruMetadata.js +0 -0
- /package/dist/http/{models → interceptor}/CacheInterceptor.js +0 -0
package/README.md
CHANGED
|
@@ -18,20 +18,21 @@ This project was created using `bun init` in bun v1.3.2. [Bun](https://bun.com)
|
|
|
18
18
|
|
|
19
19
|
## 模块文档
|
|
20
20
|
|
|
21
|
-
| 模块 | 说明
|
|
22
|
-
|
|
23
|
-
| [
|
|
24
|
-
| [
|
|
25
|
-
| [
|
|
26
|
-
| [flow](./src/flow/README.md) | Promise 扩展,全局错误处理
|
|
27
|
-
| [foundation](./src/foundation/README.md) | 基础工具,性能监控
|
|
28
|
-
| [
|
|
29
|
-
| [
|
|
30
|
-
| [
|
|
31
|
-
| [
|
|
32
|
-
| [
|
|
33
|
-
| [
|
|
34
|
-
| [
|
|
21
|
+
| 模块 | 说明 |
|
|
22
|
+
|------------------------------------------|---------------------------------------|
|
|
23
|
+
| [cache](./src/cache/README.md) | 通用 LRU 缓存,IndexedDB 持久化,快速选择算法优化 |
|
|
24
|
+
| [event-bus](./src/event-bus/README.md) | 事件总线,支持跨 Tab 通信 |
|
|
25
|
+
| [fetch](./src/fetch/README.md) | 带超时控制的 fetch 封装 |
|
|
26
|
+
| [flow](./src/flow/README.md) | Promise 扩展,全局错误处理 |
|
|
27
|
+
| [foundation](./src/foundation/README.md) | 基础工具,性能监控 |
|
|
28
|
+
| [http](./src/http/README.md) | HTTP 网络框架,双层缓存,6 种缓存模式,类 Retrofit API |
|
|
29
|
+
| [layout](./src/layout/README.md) | 布局组件,悬浮交互 |
|
|
30
|
+
| [media](./src/media/README.md) | 媒体组件,视频播放 |
|
|
31
|
+
| [models](./src/models/README.md) | 数据模型,API 响应类型 |
|
|
32
|
+
| [refresh](./src/refresh/README.md) | 刷新加载,分页加载更多 |
|
|
33
|
+
| [responsive](./src/responsive/README.md) | 响应式布局,设备检测 |
|
|
34
|
+
| [sse](./src/sse/README.md) | Server-Sent Events 连接管理 |
|
|
35
|
+
| [utils](./src/utils/README.md) | 工具函数,滚动定位、组件刷新 |
|
|
35
36
|
|
|
36
37
|
## 详细文档
|
|
37
38
|
|
|
@@ -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
|
+
{"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"}
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* - 支持 TTL 过期
|
|
8
8
|
* - 批量清理优化性能
|
|
9
9
|
* - 防污染:返回数据的深拷贝
|
|
10
|
+
* - 使用快速选择算法优化淘汰性能 O(n)
|
|
10
11
|
*/
|
|
11
|
-
import type { CacheEntry
|
|
12
|
+
import type { CacheEntry } from './CacheEntry';
|
|
13
|
+
import type { DiskLruCacheConfig } from './DiskCacheConfig';
|
|
12
14
|
export declare class DiskLruCache {
|
|
13
15
|
private store;
|
|
14
16
|
private config;
|
|
@@ -48,6 +50,7 @@ export declare class DiskLruCache {
|
|
|
48
50
|
has(key: string): Promise<boolean>;
|
|
49
51
|
/**
|
|
50
52
|
* 淘汰最旧的缓存条目(失败静默忽略)
|
|
53
|
+
* 使用快速选择算法,平均时间复杂度 O(n)
|
|
51
54
|
*/
|
|
52
55
|
private evict;
|
|
53
56
|
/**
|
|
@@ -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"}
|
|
@@ -7,9 +7,59 @@
|
|
|
7
7
|
* - 支持 TTL 过期
|
|
8
8
|
* - 批量清理优化性能
|
|
9
9
|
* - 防污染:返回数据的深拷贝
|
|
10
|
+
* - 使用快速选择算法优化淘汰性能 O(n)
|
|
10
11
|
*/
|
|
11
12
|
import { get, set, del, clear as clearStore, createStore } from 'idb-keyval';
|
|
12
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
|
+
}
|
|
13
63
|
export class DiskLruCache {
|
|
14
64
|
constructor(config) {
|
|
15
65
|
this.metadata = null;
|
|
@@ -174,6 +224,7 @@ export class DiskLruCache {
|
|
|
174
224
|
}
|
|
175
225
|
/**
|
|
176
226
|
* 淘汰最旧的缓存条目(失败静默忽略)
|
|
227
|
+
* 使用快速选择算法,平均时间复杂度 O(n)
|
|
177
228
|
*/
|
|
178
229
|
async evict() {
|
|
179
230
|
// 防止并发淘汰
|
|
@@ -184,10 +235,10 @@ export class DiskLruCache {
|
|
|
184
235
|
const meta = await this.loadMetadata();
|
|
185
236
|
// 计算需要淘汰的数量
|
|
186
237
|
const evictCount = Math.ceil(this.config.maxSize * this.config.cleanupThreshold);
|
|
187
|
-
//
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
238
|
+
// 使用快速选择算法找出访问时间最早的 k 个条目 O(n)
|
|
239
|
+
const entries = Object.entries(meta.entries);
|
|
240
|
+
const toEvict = quickSelectSmallestK(entries, evictCount, ([, entry]) => entry.accessTime);
|
|
241
|
+
// 淘汰选中的条目
|
|
191
242
|
for (const [key] of toEvict) {
|
|
192
243
|
try {
|
|
193
244
|
await del(key, this.store);
|
|
@@ -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"}
|
|
@@ -38,6 +38,13 @@ import type { RequestConfig, ApiOptions, CacheConfig, HttpClientConfig } from '.
|
|
|
38
38
|
* 基础 API 调用选项(不含 body)
|
|
39
39
|
*/
|
|
40
40
|
type BaseApiOptions = Omit<ApiOptions, 'body'>;
|
|
41
|
+
/**
|
|
42
|
+
* 强制 TypeScript 展开交叉类型为单一对象类型
|
|
43
|
+
* 用于用户自定义接口类型时使用
|
|
44
|
+
*/
|
|
45
|
+
export type Simplify<T> = {
|
|
46
|
+
[K in keyof T]: T[K];
|
|
47
|
+
} & {};
|
|
41
48
|
/**
|
|
42
49
|
* 带 body 的 API 调用选项(body 必需)
|
|
43
50
|
*/
|
|
@@ -133,8 +140,10 @@ type EmptyApi = {};
|
|
|
133
140
|
* 当单个 builder 链式调用超过 4 个端点时,类型推断可能不够精确。
|
|
134
141
|
*
|
|
135
142
|
* 建议:
|
|
136
|
-
* - 保持单个 builder 的端点数量在 4
|
|
143
|
+
* - 保持单个 builder 的端点数量在 4 个以内以获得最佳类型推断
|
|
137
144
|
* - 如需更多端点,功能仍然正常,但部分类型检查可能被放宽
|
|
145
|
+
* - 可以使用导出的 `ApiEndpointWithBody`、`ApiEndpointWithoutBody` 等类型
|
|
146
|
+
* 来定义自己的接口类型,获得更精确的类型检查
|
|
138
147
|
*
|
|
139
148
|
* @example
|
|
140
149
|
* ```ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiBuilder.d.ts","sourceRoot":"","sources":["../../../src/http/api/ApiBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,EAAE,EAAE,KAAK,OAAO,IAAI,SAAS,EAAE,MAAM,IAAI,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAMxF;;GAEG;AACH,KAAK,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"ApiBuilder.d.ts","sourceRoot":"","sources":["../../../src/http/api/ApiBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,8 +43,10 @@ import { HttpClient } from '../client/HttpClient';
|
|
|
43
43
|
* 当单个 builder 链式调用超过 4 个端点时,类型推断可能不够精确。
|
|
44
44
|
*
|
|
45
45
|
* 建议:
|
|
46
|
-
* - 保持单个 builder 的端点数量在 4
|
|
46
|
+
* - 保持单个 builder 的端点数量在 4 个以内以获得最佳类型推断
|
|
47
47
|
* - 如需更多端点,功能仍然正常,但部分类型检查可能被放宽
|
|
48
|
+
* - 可以使用导出的 `ApiEndpointWithBody`、`ApiEndpointWithoutBody` 等类型
|
|
49
|
+
* 来定义自己的接口类型,获得更精确的类型检查
|
|
48
50
|
*
|
|
49
51
|
* @example
|
|
50
52
|
* ```ts
|
package/dist/http/api/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ApiBuilder, type ApiEndpoint, type ApiDefinition } from './ApiBuilder';
|
|
1
|
+
export { ApiBuilder, type ApiEndpoint, type ApiDefinition, type ApiEndpointWithBody, type ApiEndpointWithoutBody, type ApiEndpointWithBodyRequired, type ApiEndpointWithBodyOptional, type Simplify, } from './ApiBuilder';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,QAAQ,GAChB,MAAM,cAAc,CAAA"}
|
package/dist/http/api/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ApiBuilder } from './ApiBuilder';
|
|
1
|
+
export { ApiBuilder, } from './ApiBuilder';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - 容错:缓存操作失败不影响正常业务
|
|
8
8
|
* - 防污染:返回数据的深拷贝,防止上层修改影响缓存
|
|
9
9
|
*/
|
|
10
|
-
import { DiskLruCache } from '
|
|
10
|
+
import { DiskLruCache } from '../../cache';
|
|
11
11
|
import type { CacheEntry, HttpCacheConfig } from '../types';
|
|
12
12
|
export declare class HttpCache {
|
|
13
13
|
private memoryCache;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpCache.d.ts","sourceRoot":"","sources":["../../../src/http/cache/HttpCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"HttpCache.d.ts","sourceRoot":"","sources":["../../../src/http/cache/HttpCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAG3D,qBAAa,SAAS;IAClB,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,SAAS,CAAc;gBAEnB,MAAM,EAAE,eAAe;IAcnC;;;;OAIG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAwCxD;;;;;OAKG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBlE;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAc5B;;;OAGG;IACH,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI;IAgBnD;;OAEG;IACH,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,GAAE,MAAU,GAAG,IAAI;IAc3D;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyBxC;;OAEG;IACH,YAAY,IAAI,YAAY;IAI5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/http/cache/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { DiskLruCache } from '
|
|
1
|
+
export { DiskLruCache } from '../../cache/DiskLruCache';
|
|
2
2
|
export { HttpCache } from './HttpCache';
|
|
@@ -85,7 +85,7 @@ export class HttpClient {
|
|
|
85
85
|
memoryCacheMaxSize: 100,
|
|
86
86
|
diskCacheMaxSize: 500,
|
|
87
87
|
dbName: 'xxf-http-cache',
|
|
88
|
-
defaultKeyHeaders: [
|
|
88
|
+
defaultKeyHeaders: [], // 默认不包含任何 header,避免 token 变化导致缓存失效
|
|
89
89
|
defaultCache: undefined, // 默认不缓存 (OnlyRemote)
|
|
90
90
|
cacheInterceptor: undefined, // 默认无拦截器
|
|
91
91
|
...config,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ApiBuilder 使用示例
|
|
3
3
|
*
|
|
4
|
-
* 此文件演示 ApiBuilder
|
|
4
|
+
* 此文件演示 ApiBuilder 的核心特性:
|
|
5
5
|
* 1. 泛型累积 - 链式调用自动累积端点类型
|
|
6
6
|
* 2. Body 类型约束 - POST/PUT/PATCH 请求体类型检查
|
|
7
7
|
* 3. 端点名称字面量 - 调用不存在的端点会编译报错
|
|
8
|
+
* 4. 缓存策略 - CacheMode 控制缓存行为
|
|
9
|
+
* 5. 多次响应 - 支持缓存优先场景下的两次数据返回
|
|
8
10
|
*/
|
|
9
11
|
/** 用户实体 */
|
|
10
12
|
interface User {
|
|
@@ -31,23 +33,70 @@ interface PaginatedResponse<T> {
|
|
|
31
33
|
pageSize: number;
|
|
32
34
|
}
|
|
33
35
|
export declare const userApi: object & {
|
|
34
|
-
[x: string]:
|
|
36
|
+
[x: string]: ApiEndpointWithoutBody<User[]>;
|
|
35
37
|
} & {
|
|
36
|
-
[x: string]:
|
|
38
|
+
[x: string]: ApiEndpointWithoutBody<User>;
|
|
37
39
|
} & {
|
|
38
|
-
[x: string]:
|
|
40
|
+
[x: string]: ApiEndpointWithoutBody<PaginatedResponse<User>>;
|
|
39
41
|
} & {
|
|
40
|
-
[x: string]: import("
|
|
42
|
+
[x: string]: import("..").ApiEndpointWithBodyRequired<User, CreateUserDTO>;
|
|
41
43
|
} & {
|
|
42
|
-
[x: string]: import("
|
|
44
|
+
[x: string]: import("..").ApiEndpointWithBodyOptional<void>;
|
|
43
45
|
} & {
|
|
44
|
-
[x: string]: import("
|
|
46
|
+
[x: string]: import("..").ApiEndpointWithBodyRequired<User, UpdateUserDTO>;
|
|
45
47
|
} & {
|
|
46
|
-
[x: string]: import("
|
|
48
|
+
[x: string]: import("..").ApiEndpointWithBodyRequired<User, Partial<UpdateUserDTO>>;
|
|
47
49
|
} & {
|
|
48
|
-
[x: string]:
|
|
50
|
+
[x: string]: ApiEndpointWithoutBody<void>;
|
|
49
51
|
};
|
|
50
52
|
declare function demo(): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* CacheMode 枚举值说明:
|
|
55
|
+
*
|
|
56
|
+
* - OnlyRemote: 只请求网络,不使用缓存(适用于实时性要求高的数据)
|
|
57
|
+
* - OnlyCache: 只读取缓存,不请求网络(适用于离线场景)
|
|
58
|
+
* - FirstCache: 先返回缓存,再请求网络更新(可能返回两次数据)
|
|
59
|
+
* - FirstRemote: 先请求网络,失败时回退到缓存(网络优先)
|
|
60
|
+
* - IfCache: 有缓存则用缓存,无缓存则请求网络(只返回一次)
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* 缓存模式使用示例
|
|
64
|
+
*/
|
|
65
|
+
declare function cacheModeDemo(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* FirstCache 模式会返回两次数据:
|
|
68
|
+
* 1. 第一次:从缓存返回(如果有缓存),fromCache = true
|
|
69
|
+
* 2. 第二次:从网络返回最新数据,fromCache = false
|
|
70
|
+
*
|
|
71
|
+
* 这种模式非常适合:
|
|
72
|
+
* - 列表页快速展示 + 后台刷新
|
|
73
|
+
* - 详情页先显示旧数据,再更新为最新数据
|
|
74
|
+
* - 提升用户体验,减少白屏时间
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* 方式一:使用 for await 处理多次响应
|
|
78
|
+
* 推荐用于需要处理每次响应的场景
|
|
79
|
+
*/
|
|
80
|
+
declare function multiResponseWithForAwait(): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* 方式二:使用 subscribe 处理多次响应
|
|
83
|
+
* 推荐用于 React/Vue 等框架中的响应式更新
|
|
84
|
+
*/
|
|
85
|
+
declare function multiResponseWithSubscribe(): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* 方式三:只需要最终结果时使用 await
|
|
88
|
+
* 注意:await 只返回最后一次响应(网络数据)
|
|
89
|
+
*/
|
|
90
|
+
declare function singleResponseWithAwait(): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* React 组件中的典型用法示例(伪代码)
|
|
93
|
+
*/
|
|
94
|
+
declare function reactUsageExample(): void;
|
|
51
95
|
declare function typeErrors(): void;
|
|
52
|
-
|
|
96
|
+
import type { ApiEndpointWithoutBody } from '../api/ApiBuilder';
|
|
97
|
+
/**
|
|
98
|
+
* 类型兼容性验证示例
|
|
99
|
+
*/
|
|
100
|
+
declare function verifyTypeCompatibility(): void;
|
|
101
|
+
export { demo, typeErrors, verifyTypeCompatibility, cacheModeDemo, multiResponseWithForAwait, multiResponseWithSubscribe, singleResponseWithAwait, reactUsageExample, };
|
|
53
102
|
//# sourceMappingURL=api-builder.demo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-builder.demo.d.ts","sourceRoot":"","sources":["../../../src/http/demo/api-builder.demo.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"api-builder.demo.d.ts","sourceRoot":"","sources":["../../../src/http/demo/api-builder.demo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,WAAW;AACX,UAAU,IAAI;IACV,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CACpB;AAED,eAAe;AACf,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,eAAe;AACf,UAAU,aAAa;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,WAAW;AACX,UAAU,iBAAiB,CAAC,CAAC;IACzB,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;CACnB;AAMD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;CA8DR,CAAA;AAMZ,iBAAe,IAAI,kBAqDlB;AAMD;;;;;;;;GAQG;AAEH;;GAEG;AACH,iBAAe,aAAa,kBAmC3B;AAMD;;;;;;;;;GASG;AAEH;;;GAGG;AACH,iBAAe,yBAAyB,kBAiBvC;AAED;;;GAGG;AACH,iBAAe,0BAA0B,kBA0BxC;AAED;;;GAGG;AACH,iBAAe,uBAAuB,kBAUrC;AAED;;GAEG;AACH,iBAAS,iBAAiB,SA4CzB;AAoBD,iBAAS,UAAU,SAYlB;AAMD,OAAO,KAAK,EAAuB,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAcpF;;GAEG;AACH,iBAAS,uBAAuB,SAkB/B;AAMD,OAAO,EACH,IAAI,EACJ,UAAU,EACV,uBAAuB,EACvB,aAAa,EACb,yBAAyB,EACzB,0BAA0B,EAC1B,uBAAuB,EACvB,iBAAiB,GACpB,CAAA"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ApiBuilder 使用示例
|
|
3
3
|
*
|
|
4
|
-
* 此文件演示 ApiBuilder
|
|
4
|
+
* 此文件演示 ApiBuilder 的核心特性:
|
|
5
5
|
* 1. 泛型累积 - 链式调用自动累积端点类型
|
|
6
6
|
* 2. Body 类型约束 - POST/PUT/PATCH 请求体类型检查
|
|
7
7
|
* 3. 端点名称字面量 - 调用不存在的端点会编译报错
|
|
8
|
+
* 4. 缓存策略 - CacheMode 控制缓存行为
|
|
9
|
+
* 5. 多次响应 - 支持缓存优先场景下的两次数据返回
|
|
8
10
|
*/
|
|
9
11
|
import { ApiBuilder } from '../api/ApiBuilder';
|
|
10
12
|
import { CacheMode } from '../models/CacheMode';
|
|
@@ -113,23 +115,182 @@ async function demo() {
|
|
|
113
115
|
cache: { mode: CacheMode.OnlyRemote },
|
|
114
116
|
});
|
|
115
117
|
console.log('Fresh:', freshUser);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
+
}
|
|
119
199
|
}
|
|
120
|
-
|
|
121
|
-
|
|
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({
|
|
122
214
|
onData: (data, fromCache) => {
|
|
123
|
-
|
|
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
|
+
}
|
|
124
223
|
},
|
|
125
224
|
onError: (error) => {
|
|
126
|
-
console.error('
|
|
225
|
+
console.error('❌ 请求失败:', error);
|
|
226
|
+
// setState({ error, loading: false })
|
|
127
227
|
},
|
|
128
228
|
onComplete: () => {
|
|
129
|
-
console.log('
|
|
229
|
+
console.log('✅ 请求完成');
|
|
130
230
|
},
|
|
131
231
|
});
|
|
132
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
|
+
}
|
|
133
294
|
// ============================================================================
|
|
134
295
|
// 类型错误示例
|
|
135
296
|
// ============================================================================
|
|
@@ -157,7 +318,26 @@ function typeErrors() {
|
|
|
157
318
|
// @ts-expect-error body not allowed for GET
|
|
158
319
|
simpleApi.getUser({ pathParams: { id: '1' }, body: {} });
|
|
159
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
|
+
}
|
|
160
340
|
// ============================================================================
|
|
161
341
|
// 导出
|
|
162
342
|
// ============================================================================
|
|
163
|
-
export { demo, typeErrors };
|
|
343
|
+
export { demo, typeErrors, verifyTypeCompatibility, cacheModeDemo, multiResponseWithForAwait, multiResponseWithSubscribe, singleResponseWithAwait, reactUsageExample, };
|
package/dist/http/index.d.ts
CHANGED
|
@@ -35,8 +35,18 @@
|
|
|
35
35
|
* })
|
|
36
36
|
* ```
|
|
37
37
|
*/
|
|
38
|
-
export { CacheMode
|
|
39
|
-
export {
|
|
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';
|
|
40
50
|
export { HttpClient, ApiStream } from './client';
|
|
41
|
-
export { ApiBuilder
|
|
51
|
+
export { ApiBuilder } from './api';
|
|
42
52
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/http/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;
|
|
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"}
|
package/dist/http/index.js
CHANGED
|
@@ -35,11 +35,27 @@
|
|
|
35
35
|
* })
|
|
36
36
|
* ```
|
|
37
37
|
*/
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
export {
|
|
42
|
-
//
|
|
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
|
+
// ============================================================================
|
|
43
57
|
export { HttpClient, ApiStream } from './client';
|
|
44
|
-
//
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// API Builder
|
|
60
|
+
// ============================================================================
|
|
45
61
|
export { ApiBuilder } from './api';
|
|
@@ -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,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局缓存拦截器
|
|
3
|
+
* 用于 xxf_react/http 的 ApiBuilder
|
|
4
|
+
*/
|
|
5
|
+
import { CacheInterceptor } from "./CacheInterceptor";
|
|
6
|
+
/**
|
|
7
|
+
* 默认缓存拦截器
|
|
8
|
+
* 只有满足以下条件才缓存:
|
|
9
|
+
* - HTTP 状态码 = 200
|
|
10
|
+
* - Content-Type 包含 application/json
|
|
11
|
+
* - data 是有效对象
|
|
12
|
+
* - ApiResponse.code = 0 或 200
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* ApiBuilder.create({
|
|
17
|
+
* baseUrl: '...',
|
|
18
|
+
* cacheInterceptor: defaultCacheInterceptor,
|
|
19
|
+
* })
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const defaultCacheInterceptor: CacheInterceptor;
|
|
23
|
+
/**
|
|
24
|
+
* 创建自定义缓存拦截器
|
|
25
|
+
* 在默认检查基础上添加自定义逻辑
|
|
26
|
+
*
|
|
27
|
+
* @param customCheck 自定义检查函数,在默认检查通过后执行
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const myInterceptor = createCacheInterceptor((ctx) => {
|
|
32
|
+
* // 额外检查:只缓存有 data 字段的响应
|
|
33
|
+
* const res = ctx.data as { data?: unknown }
|
|
34
|
+
* return res.data !== undefined
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function createCacheInterceptor(customCheck?: (ctx: Parameters<CacheInterceptor>[0]) => boolean): CacheInterceptor;
|
|
39
|
+
//# 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,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEpD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,uBAAuB,EAAE,gBAkBrC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAClC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,GAChE,gBAAgB,CASlB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局缓存拦截器
|
|
3
|
+
* 用于 xxf_react/http 的 ApiBuilder
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 默认缓存拦截器
|
|
7
|
+
* 只有满足以下条件才缓存:
|
|
8
|
+
* - HTTP 状态码 = 200
|
|
9
|
+
* - Content-Type 包含 application/json
|
|
10
|
+
* - data 是有效对象
|
|
11
|
+
* - ApiResponse.code = 0 或 200
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* ApiBuilder.create({
|
|
16
|
+
* baseUrl: '...',
|
|
17
|
+
* cacheInterceptor: defaultCacheInterceptor,
|
|
18
|
+
* })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const defaultCacheInterceptor = (ctx) => {
|
|
22
|
+
// 检查 HTTP 状态码
|
|
23
|
+
if (ctx.status !== 200) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
// 检查 Content-Type 是否为 JSON
|
|
27
|
+
const contentType = ctx.headers.get('Content-Type') || '';
|
|
28
|
+
if (!contentType.includes('application/json')) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
// 检查 data 是否为有效对象
|
|
32
|
+
if (!ctx.data || typeof ctx.data !== 'object') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
// 检查业务码:code 必须是 0 或 200
|
|
36
|
+
const res = ctx.data;
|
|
37
|
+
return !(res.code !== 0 && res.code !== 200);
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* 创建自定义缓存拦截器
|
|
41
|
+
* 在默认检查基础上添加自定义逻辑
|
|
42
|
+
*
|
|
43
|
+
* @param customCheck 自定义检查函数,在默认检查通过后执行
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const myInterceptor = createCacheInterceptor((ctx) => {
|
|
48
|
+
* // 额外检查:只缓存有 data 字段的响应
|
|
49
|
+
* const res = ctx.data as { data?: unknown }
|
|
50
|
+
* return res.data !== undefined
|
|
51
|
+
* })
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function createCacheInterceptor(customCheck) {
|
|
55
|
+
return (ctx) => {
|
|
56
|
+
// 先执行默认检查
|
|
57
|
+
if (!defaultCacheInterceptor(ctx)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// 执行自定义检查
|
|
61
|
+
return !(customCheck && !customCheck(ctx));
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/interceptor/index.ts"],"names":[],"mappings":"AACA,YAAY,EACR,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACzB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* HTTP 客户端配置
|
|
3
3
|
*/
|
|
4
4
|
import type { CacheConfig } from './CacheConfig';
|
|
5
|
-
import type { CacheInterceptor } from '
|
|
5
|
+
import type { CacheInterceptor } from '../interceptor/CacheInterceptor';
|
|
6
6
|
/**
|
|
7
7
|
* HTTP 客户端配置
|
|
8
8
|
*
|
|
@@ -37,7 +37,20 @@ export interface HttpClientConfig {
|
|
|
37
37
|
diskCacheMaxSize?: number;
|
|
38
38
|
/** IndexedDB 数据库名,默认 'xxf-http-cache' */
|
|
39
39
|
dbName?: string;
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* 默认参与缓存 key 计算的 header 列表
|
|
42
|
+
*
|
|
43
|
+
* 默认为空数组 `[]`,不包含任何 header。
|
|
44
|
+
*
|
|
45
|
+
* **为什么默认不包含 Authorization?**
|
|
46
|
+
* - Authorization header 通常包含会变化的 token(如 JWT 刷新、时间戳签名)
|
|
47
|
+
* - 如果 token 变化,缓存 key 也会变化,导致缓存失效
|
|
48
|
+
* - 同一用户在同一浏览器中不会共享缓存,无需通过 header 区分用户
|
|
49
|
+
*
|
|
50
|
+
* 如需根据 header 区分缓存,可以:
|
|
51
|
+
* 1. 设置 `defaultKeyHeaders: ['Accept-Language']` 等稳定的 header
|
|
52
|
+
* 2. 使用 `cacheKey` 函数提取 token 中不变的部分(如 userId)
|
|
53
|
+
*/
|
|
41
54
|
defaultKeyHeaders?: string[];
|
|
42
55
|
/**
|
|
43
56
|
* 全局默认缓存配置
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpClientConfig.d.ts","sourceRoot":"","sources":["../../../src/http/models/HttpClientConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"HttpClientConfig.d.ts","sourceRoot":"","sources":["../../../src/http/models/HttpClientConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAEvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,gBAAgB;IAC7B,aAAa;IACb,OAAO,EAAE,MAAM,CAAA;IAEf,YAAY;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,uBAAuB;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B,uBAAuB;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAEzB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAE5B;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAEnC;;;;;;;;;;;;;;;;;OAiBG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CACtC"}
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
* - LruMetadata: LRU 元数据
|
|
14
14
|
*/
|
|
15
15
|
export { CacheMode } from './CacheMode';
|
|
16
|
-
export type { CacheEntry } from '
|
|
16
|
+
export type { CacheEntry } from '../../cache/CacheEntry';
|
|
17
17
|
export type { ApiResult, ApiCallback } from './ApiTypes';
|
|
18
18
|
export type { CacheConfig, CacheKeyRequest } from './CacheConfig';
|
|
19
|
-
export type { CacheInterceptor, CacheInterceptorContext, CacheInterceptorResult, } from '
|
|
19
|
+
export type { CacheInterceptor, CacheInterceptorContext, CacheInterceptorResult, } from '../interceptor/CacheInterceptor';
|
|
20
20
|
export type { HttpClientConfig } from './HttpClientConfig';
|
|
21
21
|
export type { RequestConfig, ApiOptions } from './RequestConfig';
|
|
22
|
-
export type { DiskLruCacheConfig, HttpCacheConfig } from '
|
|
23
|
-
export type { LruMetadataEntry, LruMetadata } from '
|
|
22
|
+
export type { DiskLruCacheConfig, HttpCacheConfig } from '../../cache/DiskCacheConfig';
|
|
23
|
+
export type { LruMetadataEntry, LruMetadata } from '../../cache/LruMetadata';
|
|
24
24
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/models/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGvC,YAAY,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/models/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGvC,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAGxD,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGxD,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGjE,YAAY,EACR,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACzB,MAAM,iCAAiC,CAAA;AAGxC,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAG1D,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAGhE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAGtF,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AAGvB,wBAAgB,OAAO,SAGtB"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AAGvB,wBAAgB,OAAO,SAGtB"}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xxf_react",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
"./http": {
|
|
58
58
|
"types": "./dist/http/index.d.ts",
|
|
59
59
|
"import": "./dist/http/index.js"
|
|
60
|
+
},
|
|
61
|
+
"./cache": {
|
|
62
|
+
"types": "./dist/cache/index.d.ts",
|
|
63
|
+
"import": "./dist/cache/index.js"
|
|
60
64
|
}
|
|
61
65
|
},
|
|
62
66
|
"files": [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DiskLruCache.d.ts","sourceRoot":"","sources":["../../../src/http/cache/DiskLruCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAe,MAAM,UAAU,CAAA;AAK3E,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;;OAEG;YACW,KAAK;IAsCnB;;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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CacheEntry.d.ts","sourceRoot":"","sources":["../../../src/http/models/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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CacheInterceptor.d.ts","sourceRoot":"","sources":["../../../src/http/models/CacheInterceptor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD;;;;;;;;;;;;;;;;;;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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DiskCacheConfig.d.ts","sourceRoot":"","sources":["../../../src/http/models/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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LruMetadata.d.ts","sourceRoot":"","sources":["../../../src/http/models/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"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|