@net-vert/core 1.2.1 → 1.3.0
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 +51 -263
- package/dist/index.d.ts +22 -52
- package/dist/index.js +94 -171
- package/dist/index.umd.cjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,11 +11,11 @@ GitHub 开源仓库 👉 [https://github.com/yvygyyth/net-vert](https://github.c
|
|
|
11
11
|
|
|
12
12
|
## ✨ 核心特性
|
|
13
13
|
|
|
14
|
-
✅ **依赖倒置设计** - 解耦网络层,按需注入 axios、fetch 或自定义请求器
|
|
15
|
-
✅ **中间件扩展** -
|
|
16
|
-
✅ **类型安全** - TypeScript 全类型提示,开发体验丝滑
|
|
17
|
-
✅ **零配置上手** - API 极简,开箱即用
|
|
18
|
-
✅ **灵活组合** - 多种中间件自由组合,满足复杂业务场景
|
|
14
|
+
✅ **依赖倒置设计** - 解耦网络层,按需注入 axios、fetch 或自定义请求器
|
|
15
|
+
✅ **中间件扩展** - 内置缓存、幂等、重试、并发控制等强大中间件
|
|
16
|
+
✅ **类型安全** - TypeScript 全类型提示,开发体验丝滑
|
|
17
|
+
✅ **零配置上手** - API 极简,开箱即用
|
|
18
|
+
✅ **灵活组合** - 多种中间件自由组合,满足复杂业务场景
|
|
19
19
|
✅ **Tree-Shaking** - 支持按需引入,打包体积更小
|
|
20
20
|
|
|
21
21
|
---
|
|
@@ -129,7 +129,7 @@ import { createRequestor, cache } from '@net-vert/core'
|
|
|
129
129
|
|
|
130
130
|
const requestor = createRequestor({
|
|
131
131
|
extensions: [
|
|
132
|
-
cache({
|
|
132
|
+
cache({
|
|
133
133
|
duration: 5000 // 缓存 5 秒
|
|
134
134
|
})
|
|
135
135
|
]
|
|
@@ -157,10 +157,10 @@ interface CacheOptions<D = any, R = any> {
|
|
|
157
157
|
* - number: 固定时长
|
|
158
158
|
* - function: 动态计算(可根据响应内容决定缓存时长)
|
|
159
159
|
*/
|
|
160
|
-
duration?: number | ((ctx: {
|
|
160
|
+
duration?: number | ((ctx: {
|
|
161
161
|
key: string
|
|
162
162
|
config: RequestConfig<D>
|
|
163
|
-
response: R
|
|
163
|
+
response: R
|
|
164
164
|
}) => number)
|
|
165
165
|
|
|
166
166
|
/**
|
|
@@ -354,7 +354,7 @@ import { createRequestor, retry } from '@net-vert/core'
|
|
|
354
354
|
|
|
355
355
|
const requestor = createRequestor({
|
|
356
356
|
extensions: [
|
|
357
|
-
retry({
|
|
357
|
+
retry({
|
|
358
358
|
retries: 3, // 最多重试 3 次
|
|
359
359
|
delay: 1000 // 每次重试延迟 1 秒
|
|
360
360
|
})
|
|
@@ -447,7 +447,7 @@ import { createRequestor, concurrent } from '@net-vert/core'
|
|
|
447
447
|
|
|
448
448
|
const requestor = createRequestor({
|
|
449
449
|
extensions: [
|
|
450
|
-
concurrent({
|
|
450
|
+
concurrent({
|
|
451
451
|
parallelCount: 3 // 最多同时 3 个请求
|
|
452
452
|
})
|
|
453
453
|
]
|
|
@@ -511,140 +511,6 @@ const results = await Promise.all(
|
|
|
511
511
|
|
|
512
512
|
---
|
|
513
513
|
|
|
514
|
-
### 5. 同步模式中间件 (`sync`)
|
|
515
|
-
|
|
516
|
-
让异步请求支持"Suspense 风格"的同步调用,适用于 React Suspense 等场景。
|
|
517
|
-
|
|
518
|
-
> **⚠️ 重要**:`sync` 中间件**必须放在中间件数组的第一位**,否则会导致功能异常。详见 [中间件顺序规则](#️-重要中间件顺序规则)。
|
|
519
|
-
|
|
520
|
-
#### 基础用法(Suspense 模式)
|
|
521
|
-
|
|
522
|
-
```typescript
|
|
523
|
-
import { createRequestor, sync } from '@net-vert/core'
|
|
524
|
-
|
|
525
|
-
const requestor = createRequestor({
|
|
526
|
-
extensions: [sync()]
|
|
527
|
-
})
|
|
528
|
-
|
|
529
|
-
// 首次调用会抛出 Promise(触发 Suspense)
|
|
530
|
-
try {
|
|
531
|
-
const data = requestor.get('/api/users')
|
|
532
|
-
} catch (promise) {
|
|
533
|
-
await promise // 等待数据加载
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// 再次调用会同步返回缓存数据
|
|
537
|
-
const data = requestor.get('/api/users') // 同步返回,不再抛出
|
|
538
|
-
console.log(data) // 直接获取数据
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
#### React Suspense 集成
|
|
542
|
-
|
|
543
|
-
```tsx
|
|
544
|
-
import { createRequestor, sync } from '@net-vert/core'
|
|
545
|
-
|
|
546
|
-
const requestor = createRequestor({
|
|
547
|
-
extensions: [sync()]
|
|
548
|
-
})
|
|
549
|
-
|
|
550
|
-
function UserProfile({ userId }) {
|
|
551
|
-
// 首次渲染会抛出 Promise,触发 Suspense
|
|
552
|
-
// 数据加载完成后重新渲染,此时同步返回数据
|
|
553
|
-
const user = requestor.get(`/api/users/${userId}`)
|
|
554
|
-
|
|
555
|
-
return <div>{user.name}</div>
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
function App() {
|
|
559
|
-
return (
|
|
560
|
-
<Suspense fallback={<div>Loading...</div>}>
|
|
561
|
-
<UserProfile userId={1} />
|
|
562
|
-
</Suspense>
|
|
563
|
-
)
|
|
564
|
-
}
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
#### 配置选项
|
|
568
|
-
|
|
569
|
-
```typescript
|
|
570
|
-
interface SyncOptions<D = any, R = any> {
|
|
571
|
-
/**
|
|
572
|
-
* 缓存 key 生成函数
|
|
573
|
-
* 默认:基于 method + url + params 生成
|
|
574
|
-
*/
|
|
575
|
-
key?: (ctx: { config: RequestConfig<D> }) => string
|
|
576
|
-
|
|
577
|
-
/**
|
|
578
|
-
* 是否启用 Suspense 模式(抛出 Promise)
|
|
579
|
-
* - true: 首次调用抛出 Promise(默认)
|
|
580
|
-
* - false: 首次调用返回 Promise
|
|
581
|
-
*/
|
|
582
|
-
suspense?: boolean
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* 自定义 Promise 包装函数
|
|
586
|
-
* 可用于添加元数据或修改返回结构
|
|
587
|
-
*/
|
|
588
|
-
wrapSuspense?: (params: {
|
|
589
|
-
key: string
|
|
590
|
-
config: RequestConfig<D>
|
|
591
|
-
p: Promise<R>
|
|
592
|
-
}) => Promise<R>
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* 缓存有效期(毫秒)
|
|
596
|
-
* 默认:永久缓存
|
|
597
|
-
*/
|
|
598
|
-
duration?: number
|
|
599
|
-
|
|
600
|
-
/**
|
|
601
|
-
* 是否持久化
|
|
602
|
-
* 默认:false
|
|
603
|
-
*/
|
|
604
|
-
persist?: boolean
|
|
605
|
-
}
|
|
606
|
-
```
|
|
607
|
-
|
|
608
|
-
#### 高级示例
|
|
609
|
-
|
|
610
|
-
**非 Suspense 模式**
|
|
611
|
-
|
|
612
|
-
```typescript
|
|
613
|
-
const requestor = createRequestor({
|
|
614
|
-
extensions: [
|
|
615
|
-
sync({ suspense: false }) // 关闭 Suspense 模式
|
|
616
|
-
]
|
|
617
|
-
})
|
|
618
|
-
|
|
619
|
-
// 首次调用返回 Promise
|
|
620
|
-
const promise = requestor.get('/api/users')
|
|
621
|
-
await promise
|
|
622
|
-
|
|
623
|
-
// 再次调用同步返回缓存
|
|
624
|
-
const data = requestor.get('/api/users') // 同步返回
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
**自定义 Promise 包装**
|
|
628
|
-
|
|
629
|
-
```typescript
|
|
630
|
-
const requestor = createRequestor({
|
|
631
|
-
extensions: [
|
|
632
|
-
sync({
|
|
633
|
-
wrapSuspense: ({ p, key }) => {
|
|
634
|
-
// 给 Promise 添加元数据
|
|
635
|
-
return p.then(data => ({
|
|
636
|
-
...data,
|
|
637
|
-
__cacheKey: key,
|
|
638
|
-
__timestamp: Date.now()
|
|
639
|
-
}))
|
|
640
|
-
}
|
|
641
|
-
})
|
|
642
|
-
]
|
|
643
|
-
})
|
|
644
|
-
```
|
|
645
|
-
|
|
646
|
-
---
|
|
647
|
-
|
|
648
514
|
## 🔗 中间件组合
|
|
649
515
|
|
|
650
516
|
多个中间件可以自由组合,执行顺序遵循数组顺序:
|
|
@@ -660,68 +526,15 @@ const requestor = createRequestor({
|
|
|
660
526
|
})
|
|
661
527
|
```
|
|
662
528
|
|
|
663
|
-
###
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
1.
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
sync(), // 必须第一个
|
|
673
|
-
idempotent(),
|
|
674
|
-
cache({ duration: 5000 })
|
|
675
|
-
]
|
|
676
|
-
})
|
|
677
|
-
|
|
678
|
-
// ❌ 错误 - 某些情况下 sync 不在第一位会导致同步调用失败,幂等缓存的promise会被sync模块直接改变,导致幂等缓存失效.重试也会因为同步模块抛错误耗尽失败次数,同步模块的同步能力也可能因为部分中间件的异步特性而失效
|
|
679
|
-
const requestor = createRequestor({
|
|
680
|
-
extensions: [
|
|
681
|
-
retry() | idempotent(),
|
|
682
|
-
sync() // 错误位置!
|
|
683
|
-
]
|
|
684
|
-
})
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
2. **自定义中间件如果需要拦截所有请求,必须前置**
|
|
688
|
-
|
|
689
|
-
自定义中间件的位置决定了它在中间件链中的执行时机:
|
|
690
|
-
- **前置**:可以拦截和修改所有请求(包括被其他中间件处理的请求)
|
|
691
|
-
- **后置**:只能处理未被前面中间件拦截的请求(如缓存命中的请求不会到达后置中间件)
|
|
692
|
-
|
|
693
|
-
```typescript
|
|
694
|
-
const loggerMiddleware: Middleware = async ({ config, next }) => {
|
|
695
|
-
console.log('Request:', config.url)
|
|
696
|
-
return await next()
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
// ✅ 正确 - logger 在最前面,可以记录所有请求
|
|
700
|
-
const requestor = createRequestor({
|
|
701
|
-
extensions: [
|
|
702
|
-
loggerMiddleware, // 第一个执行
|
|
703
|
-
cache({ duration: 5000 }),
|
|
704
|
-
retry({ retries: 3 })
|
|
705
|
-
]
|
|
706
|
-
})
|
|
707
|
-
|
|
708
|
-
// ⚠️ 注意 - logger 在 cache 之后,缓存命中的请求不会被记录
|
|
709
|
-
const requestor = createRequestor({
|
|
710
|
-
extensions: [
|
|
711
|
-
cache({ duration: 5000 }),
|
|
712
|
-
loggerMiddleware, // 缓存命中时不会执行
|
|
713
|
-
retry({ retries: 3 })
|
|
714
|
-
]
|
|
715
|
-
})
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
3. **推荐的中间件顺序**(从前到后):
|
|
719
|
-
- `sync()` - 同步模式(如果使用)
|
|
720
|
-
- 自定义拦截中间件(日志、鉴权等)
|
|
721
|
-
- `idempotent()` - 幂等处理
|
|
722
|
-
- `cache()` - 缓存
|
|
723
|
-
- `retry()` - 重试
|
|
724
|
-
- `concurrent()` - 并发控制
|
|
529
|
+
### 推荐的中间件顺序
|
|
530
|
+
|
|
531
|
+
在组合中间件时,建议遵循以下顺序(从前到后):
|
|
532
|
+
|
|
533
|
+
1. 自定义拦截中间件(日志、鉴权等)
|
|
534
|
+
2. `idempotent()` - 幂等处理
|
|
535
|
+
3. `cache()` - 缓存
|
|
536
|
+
4. `retry()` - 重试
|
|
537
|
+
5. `concurrent()` - 并发控制
|
|
725
538
|
|
|
726
539
|
### 常见组合模式
|
|
727
540
|
|
|
@@ -747,25 +560,6 @@ const requestor = createRequestor({
|
|
|
747
560
|
})
|
|
748
561
|
```
|
|
749
562
|
|
|
750
|
-
#### 3. 全能组合(适用于复杂场景)
|
|
751
|
-
|
|
752
|
-
```typescript
|
|
753
|
-
const requestor = createRequestor({
|
|
754
|
-
extensions: [
|
|
755
|
-
idempotent(), // 1. 防止并发重复
|
|
756
|
-
cache({
|
|
757
|
-
duration: 10000,
|
|
758
|
-
persist: true // 2. 持久化缓存 10 秒
|
|
759
|
-
}),
|
|
760
|
-
retry({
|
|
761
|
-
retries: 3,
|
|
762
|
-
delay: ({ attempt }) => Math.pow(2, attempt) * 100 // 3. 指数退避重试
|
|
763
|
-
}),
|
|
764
|
-
concurrent({ parallelCount: 3 }) // 4. 限制并发数
|
|
765
|
-
]
|
|
766
|
-
})
|
|
767
|
-
```
|
|
768
|
-
|
|
769
563
|
---
|
|
770
564
|
|
|
771
565
|
## 🎯 便捷组合方法
|
|
@@ -899,7 +693,7 @@ inject(config => instance.request(config))
|
|
|
899
693
|
export const queryRequestor = createRequestor({
|
|
900
694
|
extensions: [
|
|
901
695
|
idempotent(),
|
|
902
|
-
cache({
|
|
696
|
+
cache({
|
|
903
697
|
duration: 30000, // 缓存 30 秒
|
|
904
698
|
persist: true // 持久化
|
|
905
699
|
})
|
|
@@ -909,8 +703,8 @@ export const queryRequestor = createRequestor({
|
|
|
909
703
|
// 3. 创建数据变更请求器(带重试)
|
|
910
704
|
export const mutationRequestor = createRequestor({
|
|
911
705
|
extensions: [
|
|
912
|
-
retry({
|
|
913
|
-
retries: 3,
|
|
706
|
+
retry({
|
|
707
|
+
retries: 3,
|
|
914
708
|
delay: ({ attempt }) => Math.pow(2, attempt) * 200,
|
|
915
709
|
retryCondition: ({ lastResponse }) => {
|
|
916
710
|
// 只在网络错误或 5xx 时重试
|
|
@@ -949,44 +743,38 @@ async function uploadFiles(files: File[]) {
|
|
|
949
743
|
formData.append('file', file)
|
|
950
744
|
return uploadRequestor.post('/upload', formData)
|
|
951
745
|
})
|
|
952
|
-
|
|
746
|
+
|
|
953
747
|
return Promise.all(tasks)
|
|
954
748
|
}
|
|
955
749
|
```
|
|
956
750
|
|
|
957
|
-
### 示例 3
|
|
751
|
+
### 示例 3:自定义中间件
|
|
958
752
|
|
|
959
|
-
```
|
|
960
|
-
import {
|
|
961
|
-
import { Suspense } from 'react'
|
|
962
|
-
|
|
963
|
-
// 注入请求器
|
|
964
|
-
inject(config => fetch(config.url).then(res => res.json()))
|
|
965
|
-
|
|
966
|
-
// 创建 Suspense 风格的请求器
|
|
967
|
-
const suspenseRequestor = createRequestor({
|
|
968
|
-
extensions: [sync()]
|
|
969
|
-
})
|
|
753
|
+
```typescript
|
|
754
|
+
import { createRequestor, type Middleware } from '@net-vert/core'
|
|
970
755
|
|
|
971
|
-
//
|
|
972
|
-
const
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
}
|
|
756
|
+
// 自定义日志中间件
|
|
757
|
+
const loggerMiddleware: Middleware = async ({ config, next }) => {
|
|
758
|
+
console.log('Request:', config.method, config.url)
|
|
759
|
+
const startTime = Date.now()
|
|
976
760
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
761
|
+
try {
|
|
762
|
+
const result = await next()
|
|
763
|
+
console.log('Success:', Date.now() - startTime, 'ms')
|
|
764
|
+
return result
|
|
765
|
+
} catch (error) {
|
|
766
|
+
console.error('Error:', error)
|
|
767
|
+
throw error
|
|
768
|
+
}
|
|
981
769
|
}
|
|
982
770
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
}
|
|
771
|
+
// 使用自定义中间件
|
|
772
|
+
const requestor = createRequestor({
|
|
773
|
+
extensions: [
|
|
774
|
+
loggerMiddleware,
|
|
775
|
+
cache({ duration: 5000 })
|
|
776
|
+
]
|
|
777
|
+
})
|
|
990
778
|
```
|
|
991
779
|
|
|
992
780
|
---
|
|
@@ -1004,7 +792,7 @@ import { createRequestor, type Middleware } from '@net-vert/core'
|
|
|
1004
792
|
const loggerMiddleware: Middleware = async ({ config, next }) => {
|
|
1005
793
|
console.log('Request:', config.method, config.url)
|
|
1006
794
|
const startTime = Date.now()
|
|
1007
|
-
|
|
795
|
+
|
|
1008
796
|
try {
|
|
1009
797
|
const result = await next()
|
|
1010
798
|
console.log('Success:', Date.now() - startTime, 'ms')
|
|
@@ -1021,7 +809,7 @@ const requestor = createRequestor({
|
|
|
1021
809
|
})
|
|
1022
810
|
```
|
|
1023
811
|
|
|
1024
|
-
>
|
|
812
|
+
> **💡 提示**:如果你的自定义中间件需要拦截所有请求(如日志记录、鉴权检查等),建议将其放在中间件数组的最前面。否则,被前置中间件(如 `cache`)拦截的请求不会经过你的自定义中间件。
|
|
1025
813
|
|
|
1026
814
|
### 动态切换请求器
|
|
1027
815
|
|
|
@@ -1059,17 +847,17 @@ describe('API Tests', () => {
|
|
|
1059
847
|
code: 200,
|
|
1060
848
|
data: { url: config.url }
|
|
1061
849
|
}))
|
|
1062
|
-
|
|
850
|
+
|
|
1063
851
|
inject(mockRequestor)
|
|
1064
|
-
|
|
852
|
+
|
|
1065
853
|
const requestor = createRequestor({
|
|
1066
854
|
extensions: [cache({ duration: 5000 })]
|
|
1067
855
|
})
|
|
1068
|
-
|
|
856
|
+
|
|
1069
857
|
// 发起两次相同请求
|
|
1070
858
|
await requestor.get('/api/test')
|
|
1071
859
|
await requestor.get('/api/test')
|
|
1072
|
-
|
|
860
|
+
|
|
1073
861
|
// 验证只调用了一次
|
|
1074
862
|
expect(mockRequestor).toHaveBeenCalledTimes(1)
|
|
1075
863
|
})
|
package/dist/index.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ declare interface CacheKeyContext<D = any> {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/** 缓存中间件类型(带 storage 实例)*/
|
|
45
|
-
declare type CacheMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.CACHE,
|
|
45
|
+
declare type CacheMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.CACHE, D, R> & {
|
|
46
46
|
storage: CacheStorageInstance<R>;
|
|
47
47
|
};
|
|
48
48
|
|
|
@@ -87,7 +87,7 @@ declare type ConcurrentContext<D = any> = {
|
|
|
87
87
|
config: RequestConfig<D>;
|
|
88
88
|
};
|
|
89
89
|
|
|
90
|
-
declare type ConcurrentMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.CONCURRENT,
|
|
90
|
+
declare type ConcurrentMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.CONCURRENT, D, R> & {
|
|
91
91
|
pool: ConcurrentPool;
|
|
92
92
|
};
|
|
93
93
|
|
|
@@ -120,14 +120,14 @@ RetryOptions<D>
|
|
|
120
120
|
* 适用场景:数据查询接口,既需要缓存提升性能,又要避免重复请求
|
|
121
121
|
* @param config 组合配置对象
|
|
122
122
|
*/
|
|
123
|
-
export declare function createCachedIdempotentRequestor<D = any, R = any>(config: CachedIdempotentConfig<D, R>): Requestor
|
|
123
|
+
export declare function createCachedIdempotentRequestor<D = any, R = any>(config: CachedIdempotentConfig<D, R>): Requestor;
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* 创建带并发控制和重试的请求器
|
|
127
127
|
* 适用场景:批量请求场景,需要控制并发数量,失败后自动重试
|
|
128
128
|
* @param config 组合配置对象
|
|
129
129
|
*/
|
|
130
|
-
export declare function createConcurrentRetryRequestor<D = any>(config: ConcurrentRetryConfig<D>): Requestor
|
|
130
|
+
export declare function createConcurrentRetryRequestor<D = any>(config: ConcurrentRetryConfig<D>): Requestor;
|
|
131
131
|
|
|
132
132
|
declare const createPromiseCache: () => {
|
|
133
133
|
getPromise: <T = unknown>(key: SafeKey) => Promise<T> | undefined;
|
|
@@ -136,11 +136,12 @@ declare const createPromiseCache: () => {
|
|
|
136
136
|
clearCache: () => void;
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
/**
|
|
140
|
+
* 创建请求器
|
|
141
|
+
* @param config 配置对象(可选)
|
|
142
|
+
* @returns 返回 Requestor 实例(所有方法都返回 Promise)
|
|
143
|
+
*/
|
|
144
|
+
export declare function createRequestor<const Extensions extends readonly Middleware[] = []>(config?: CreateRequestorConfig<Extensions>): Requestor;
|
|
144
145
|
|
|
145
146
|
export declare interface CreateRequestorConfig<Extensions extends readonly Middleware[] = readonly Middleware[]> {
|
|
146
147
|
extensions?: Extensions;
|
|
@@ -212,8 +213,6 @@ export declare type FlattenWithInstanceKey<Types extends readonly any[]> = WithI
|
|
|
212
213
|
|
|
213
214
|
export declare type HandlerParams<T extends keyof Requestor> = Parameters<Requestor[T]>;
|
|
214
215
|
|
|
215
|
-
export declare type HasSyncMiddleware<T extends readonly any[]> = T extends readonly [infer First, ...infer Rest] ? First extends TypedMiddleware<MIDDLEWARE_TYPE.SYNC, true, any, any> ? true : HasSyncMiddleware<Rest> : false;
|
|
216
|
-
|
|
217
216
|
declare type Id = string | number;
|
|
218
217
|
|
|
219
218
|
declare type IdempotencyContext<D = any> = {
|
|
@@ -226,7 +225,7 @@ declare type IdempotencyOptions<D = any> = {
|
|
|
226
225
|
|
|
227
226
|
export declare const idempotent: <D = any, R = any>(options?: Partial<IdempotencyOptions<D>>) => IdempotentMiddleware<D, R>;
|
|
228
227
|
|
|
229
|
-
declare type IdempotentMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.IDEMPOTENT,
|
|
228
|
+
declare type IdempotentMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.IDEMPOTENT, D, R> & {
|
|
230
229
|
promiseCache: PromiseCache;
|
|
231
230
|
};
|
|
232
231
|
|
|
@@ -234,13 +233,11 @@ export declare const inject: (requestor: BaseRequestor, instanceKey?: string) =>
|
|
|
234
233
|
|
|
235
234
|
export declare type Key = string | symbol | number;
|
|
236
235
|
|
|
237
|
-
export declare type
|
|
238
|
-
|
|
239
|
-
export declare type Middleware<IsSync extends boolean = false, D = any, R = any> = (context: {
|
|
236
|
+
export declare type Middleware<D = any, R = any> = (context: {
|
|
240
237
|
config: RequestConfig<D>;
|
|
241
|
-
next: () =>
|
|
238
|
+
next: () => Promise<R>;
|
|
242
239
|
ctx: MiddlewareContext;
|
|
243
|
-
}) =>
|
|
240
|
+
}) => Promise<R>;
|
|
244
241
|
|
|
245
242
|
declare enum MIDDLEWARE_TYPE {
|
|
246
243
|
CACHE = "cache",
|
|
@@ -272,15 +269,15 @@ export declare interface RequestConfig<D = any> extends Record<string, any> {
|
|
|
272
269
|
|
|
273
270
|
declare type RequestMethod = REQUEST_METHOD;
|
|
274
271
|
|
|
275
|
-
export declare interface Requestor
|
|
276
|
-
request: <R = any, D = any>(config: RequestConfig<D>) =>
|
|
277
|
-
get: <R = any, D = any>(url: string, config?: WithoutMethod<D>) =>
|
|
278
|
-
post: <R = any, D = any>(url: string, data?: D, config?: WithoutMethod<D>) =>
|
|
279
|
-
put: <R = any, D = any>(url: string, data?: D, config?: WithoutMethod<D>) =>
|
|
280
|
-
delete: <R = any, D = any>(url: string, config?: WithoutMethod<D>) =>
|
|
272
|
+
export declare interface Requestor {
|
|
273
|
+
request: <R = any, D = any>(config: RequestConfig<D>) => Promise<R>;
|
|
274
|
+
get: <R = any, D = any>(url: string, config?: WithoutMethod<D>) => Promise<R>;
|
|
275
|
+
post: <R = any, D = any>(url: string, data?: D, config?: WithoutMethod<D>) => Promise<R>;
|
|
276
|
+
put: <R = any, D = any>(url: string, data?: D, config?: WithoutMethod<D>) => Promise<R>;
|
|
277
|
+
delete: <R = any, D = any>(url: string, config?: WithoutMethod<D>) => Promise<R>;
|
|
281
278
|
}
|
|
282
279
|
|
|
283
|
-
export declare const retry: <D = any, R = any>(options?: Partial<RetryOptions<D>>) => TypedMiddleware<MIDDLEWARE_TYPE.RETRY,
|
|
280
|
+
export declare const retry: <D = any, R = any>(options?: Partial<RetryOptions<D>>) => TypedMiddleware<MIDDLEWARE_TYPE.RETRY, D, R>;
|
|
284
281
|
|
|
285
282
|
declare type RetryContext<D = any> = {
|
|
286
283
|
config: RequestConfig<D>;
|
|
@@ -301,27 +298,6 @@ export declare type StoreDescriptor = StoreKey | {
|
|
|
301
298
|
factory: StoreFactory<Store<AnyRecord>, any[]>;
|
|
302
299
|
};
|
|
303
300
|
|
|
304
|
-
/**
|
|
305
|
-
* 缓存中有数据则直接返回。
|
|
306
|
-
* suspense 为 true 时,会抛出一个 Promise(而不是普通错误),Promise resolve 后得到数据。
|
|
307
|
-
* suspense 为 false 时,会返回一个 Promise,Promise resolve 后得到数据,调用者需要用 await 或 .then 捕获。
|
|
308
|
-
*/
|
|
309
|
-
export declare function sync<D = any, R = any>(options: Partial<SyncOptions<D>> & {
|
|
310
|
-
suspense: true;
|
|
311
|
-
}): TypedMiddleware<MIDDLEWARE_TYPE.SYNC, true, D, R>;
|
|
312
|
-
|
|
313
|
-
export declare function sync<D = any, R = any>(options: Partial<SyncOptions<D>> & {
|
|
314
|
-
suspense: false;
|
|
315
|
-
}): TypedMiddleware<MIDDLEWARE_TYPE.SYNC, any, D, R>;
|
|
316
|
-
|
|
317
|
-
export declare function sync<D = any, R = any>(options?: Partial<SyncOptions<D>>): TypedMiddleware<MIDDLEWARE_TYPE.SYNC, true, D, R>;
|
|
318
|
-
|
|
319
|
-
declare interface SyncOptions<D = any, R = any> extends CacheOptions<D, R> {
|
|
320
|
-
isValid: (ctx: CacheCheckContext<D, R>) => boolean;
|
|
321
|
-
suspense: boolean;
|
|
322
|
-
wrapSuspense?: (params: WrapSuspense<D, R>) => any;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
301
|
declare type Task<T> = () => Promise<T>;
|
|
326
302
|
|
|
327
303
|
declare type TaskItem<T> = {
|
|
@@ -332,7 +308,7 @@ declare type TaskItem<T> = {
|
|
|
332
308
|
|
|
333
309
|
declare type TaskItemList<T> = TaskQueue<TaskItem<T>>;
|
|
334
310
|
|
|
335
|
-
export declare type TypedMiddleware<Type extends MiddlewareType,
|
|
311
|
+
export declare type TypedMiddleware<Type extends MiddlewareType, D = any, R = any> = Middleware<D, R> & {
|
|
336
312
|
__middlewareType: Type;
|
|
337
313
|
};
|
|
338
314
|
|
|
@@ -357,10 +333,4 @@ export declare type WithInstanceKey<T> = T & {
|
|
|
357
333
|
|
|
358
334
|
export declare type WithoutMethod<D = any> = Omit<RequestConfig<D>, 'method' | 'url'>;
|
|
359
335
|
|
|
360
|
-
declare type WrapSuspense<D = any, R = any> = {
|
|
361
|
-
key: CacheKey;
|
|
362
|
-
config: RequestConfig<D>;
|
|
363
|
-
p: Promise<R>;
|
|
364
|
-
};
|
|
365
|
-
|
|
366
336
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { TaskQueue as
|
|
2
|
-
var
|
|
3
|
-
const
|
|
1
|
+
import { TaskQueue as F } from "id-queue";
|
|
2
|
+
var h = /* @__PURE__ */ ((r) => (r.GET = "get", r.POST = "post", r.PUT = "put", r.DELETE = "delete", r))(h || {}), m = /* @__PURE__ */ ((r) => (r.CACHE = "cache", r.RETRY = "retry", r.IDEMPOTENT = "idempotent", r.CONCURRENT = "concurrent", r.SYNC = "sync", r))(m || {});
|
|
3
|
+
const p = "default", j = {
|
|
4
4
|
retries: 3,
|
|
5
5
|
delay: 0,
|
|
6
6
|
retryCondition: () => !0
|
|
7
|
-
},
|
|
8
|
-
const e = { ...
|
|
7
|
+
}, D = (r) => {
|
|
8
|
+
const e = { ...j, ...r };
|
|
9
9
|
return Object.assign(async ({ config: n, next: s }) => {
|
|
10
10
|
let o = 0, i;
|
|
11
11
|
for (; o <= e.retries; )
|
|
@@ -23,22 +23,22 @@ const S = "default", D = {
|
|
|
23
23
|
throw a;
|
|
24
24
|
o++;
|
|
25
25
|
const u = typeof e.delay == "function" ? e.delay(c) : e.delay;
|
|
26
|
-
u > 0 && await new Promise((
|
|
26
|
+
u > 0 && await new Promise((w) => setTimeout(w, u));
|
|
27
27
|
}
|
|
28
28
|
throw i;
|
|
29
29
|
}, { __middlewareType: m.RETRY });
|
|
30
|
-
},
|
|
30
|
+
}, T = () => {
|
|
31
31
|
const r = /* @__PURE__ */ new Map();
|
|
32
32
|
return { getPromise: (o) => r.get(o), setPromise: (o, i) => {
|
|
33
33
|
r.set(o, i), i.finally(() => r.delete(o));
|
|
34
34
|
}, delPromise: (o) => r.delete(o), clearCache: () => r.clear() };
|
|
35
|
-
},
|
|
35
|
+
}, V = (r) => {
|
|
36
36
|
const { config: e } = r, { method: t, url: n, data: s } = e;
|
|
37
37
|
return [t, n, JSON.stringify(s)].join("|");
|
|
38
|
-
},
|
|
39
|
-
key:
|
|
40
|
-
},
|
|
41
|
-
const e = { ...
|
|
38
|
+
}, q = {
|
|
39
|
+
key: V
|
|
40
|
+
}, E = (r) => {
|
|
41
|
+
const e = { ...q, ...r }, t = T();
|
|
42
42
|
return Object.assign(({ config: s, next: o }) => {
|
|
43
43
|
const i = e.key({ config: s }), a = t.getPromise(i);
|
|
44
44
|
if (a)
|
|
@@ -55,7 +55,7 @@ class R {
|
|
|
55
55
|
tasks;
|
|
56
56
|
runningCount;
|
|
57
57
|
constructor(e = 4) {
|
|
58
|
-
this.parallelCount = e, this.tasks = new
|
|
58
|
+
this.parallelCount = e, this.tasks = new F(), this.runningCount = 0;
|
|
59
59
|
}
|
|
60
60
|
// 加入
|
|
61
61
|
add(e, t) {
|
|
@@ -84,26 +84,26 @@ class R {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
let
|
|
88
|
-
const
|
|
87
|
+
let $ = 0;
|
|
88
|
+
const B = {
|
|
89
89
|
parallelCount: 4,
|
|
90
|
-
createId: () =>
|
|
90
|
+
createId: () => $++
|
|
91
91
|
}, K = (r) => {
|
|
92
|
-
const { parallelCount: e, createId: t } = { ...
|
|
92
|
+
const { parallelCount: e, createId: t } = { ...B, ...r }, n = new R(e);
|
|
93
93
|
return Object.assign(({ config: o, next: i }) => {
|
|
94
94
|
const a = t({ config: o });
|
|
95
95
|
return n.add(a, () => i());
|
|
96
96
|
}, { __middlewareType: m.CONCURRENT, pool: n });
|
|
97
|
-
},
|
|
98
|
-
|
|
97
|
+
}, I = /* @__PURE__ */ new Map(), y = (r, e) => {
|
|
98
|
+
I.set(e, r);
|
|
99
99
|
};
|
|
100
|
-
function
|
|
101
|
-
const e =
|
|
100
|
+
function _(r) {
|
|
101
|
+
const e = I.get(r);
|
|
102
102
|
if (!e)
|
|
103
103
|
throw new Error(`Store实例 ${String(r)} 未注册`);
|
|
104
104
|
return e;
|
|
105
105
|
}
|
|
106
|
-
class
|
|
106
|
+
class A {
|
|
107
107
|
store = /* @__PURE__ */ new Map();
|
|
108
108
|
getItem(e) {
|
|
109
109
|
return this.store.get(e);
|
|
@@ -132,7 +132,7 @@ class J {
|
|
|
132
132
|
e(s, n, t), t++;
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
-
const
|
|
135
|
+
const J = (r) => !!r && (typeof r == "object" || typeof r == "function") && typeof r.then == "function", C = (r) => typeof window < "u" ? r() : {
|
|
136
136
|
getItem() {
|
|
137
137
|
return null;
|
|
138
138
|
},
|
|
@@ -148,12 +148,12 @@ const z = (r) => !!r && (typeof r == "object" || typeof r == "function") && type
|
|
|
148
148
|
get length() {
|
|
149
149
|
return 0;
|
|
150
150
|
}
|
|
151
|
-
},
|
|
152
|
-
class
|
|
151
|
+
}, l = C(() => window.localStorage);
|
|
152
|
+
class z {
|
|
153
153
|
constructor() {
|
|
154
154
|
}
|
|
155
155
|
getItem(e) {
|
|
156
|
-
const t = String(e), n =
|
|
156
|
+
const t = String(e), n = l.getItem(t);
|
|
157
157
|
if (n !== null)
|
|
158
158
|
try {
|
|
159
159
|
return JSON.parse(n);
|
|
@@ -165,7 +165,7 @@ class G {
|
|
|
165
165
|
setItem(e, t) {
|
|
166
166
|
const n = String(e);
|
|
167
167
|
try {
|
|
168
|
-
|
|
168
|
+
l.setItem(n, JSON.stringify(t));
|
|
169
169
|
} catch (s) {
|
|
170
170
|
throw console.error(`Failed to set value for key: ${n}`, s), s;
|
|
171
171
|
}
|
|
@@ -173,21 +173,21 @@ class G {
|
|
|
173
173
|
}
|
|
174
174
|
removeItem(e) {
|
|
175
175
|
const t = String(e);
|
|
176
|
-
|
|
176
|
+
l.removeItem(t);
|
|
177
177
|
}
|
|
178
178
|
clear() {
|
|
179
|
-
|
|
179
|
+
l.clear();
|
|
180
180
|
}
|
|
181
181
|
length() {
|
|
182
|
-
return
|
|
182
|
+
return l.length;
|
|
183
183
|
}
|
|
184
184
|
key(e) {
|
|
185
|
-
return
|
|
185
|
+
return l.key(e);
|
|
186
186
|
}
|
|
187
187
|
keys() {
|
|
188
188
|
const e = [];
|
|
189
|
-
for (let t = 0; t <
|
|
190
|
-
const n =
|
|
189
|
+
for (let t = 0; t < l.length; t++) {
|
|
190
|
+
const n = l.key(t);
|
|
191
191
|
n && e.push(n);
|
|
192
192
|
}
|
|
193
193
|
return e;
|
|
@@ -199,8 +199,8 @@ class G {
|
|
|
199
199
|
});
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
-
const d =
|
|
203
|
-
class
|
|
202
|
+
const d = C(() => window.sessionStorage);
|
|
203
|
+
class G {
|
|
204
204
|
constructor() {
|
|
205
205
|
}
|
|
206
206
|
getItem(e) {
|
|
@@ -250,7 +250,7 @@ class U {
|
|
|
250
250
|
});
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
|
-
class
|
|
253
|
+
class U {
|
|
254
254
|
dbName;
|
|
255
255
|
storeName;
|
|
256
256
|
dbPromise = null;
|
|
@@ -379,11 +379,11 @@ const g = {
|
|
|
379
379
|
session: "session",
|
|
380
380
|
indexeddb: "indexeddb"
|
|
381
381
|
};
|
|
382
|
-
function
|
|
382
|
+
function k(r, e) {
|
|
383
383
|
Object.assign(r, e);
|
|
384
384
|
}
|
|
385
385
|
function M(r) {
|
|
386
|
-
return
|
|
386
|
+
return k(r, {
|
|
387
387
|
async getItemOrDefault(e, t) {
|
|
388
388
|
const n = await this.getItem(e);
|
|
389
389
|
return n !== null ? n : t;
|
|
@@ -400,7 +400,7 @@ function M(r) {
|
|
|
400
400
|
}), r;
|
|
401
401
|
}
|
|
402
402
|
function X(r) {
|
|
403
|
-
return
|
|
403
|
+
return k(r, {
|
|
404
404
|
getItemOrDefault(e, t) {
|
|
405
405
|
const n = this.getItem(e);
|
|
406
406
|
return n !== null ? n : t;
|
|
@@ -416,50 +416,50 @@ function X(r) {
|
|
|
416
416
|
}
|
|
417
417
|
}), r;
|
|
418
418
|
}
|
|
419
|
-
function
|
|
419
|
+
function Y(r) {
|
|
420
420
|
const e = r.getItem("");
|
|
421
|
-
return
|
|
421
|
+
return J(e) ? M(r) : X(r);
|
|
422
422
|
}
|
|
423
|
-
function
|
|
424
|
-
const t =
|
|
423
|
+
function f(r, ...e) {
|
|
424
|
+
const t = _(r);
|
|
425
425
|
let n;
|
|
426
426
|
try {
|
|
427
427
|
n = new t(...e);
|
|
428
428
|
} catch {
|
|
429
429
|
n = t(...e);
|
|
430
430
|
}
|
|
431
|
-
return
|
|
431
|
+
return Y(n);
|
|
432
432
|
}
|
|
433
|
-
y(
|
|
434
|
-
y(
|
|
435
|
-
y(
|
|
436
|
-
y(
|
|
437
|
-
function
|
|
433
|
+
y(A, g.memory);
|
|
434
|
+
y(z, g.local);
|
|
435
|
+
y(G, g.session);
|
|
436
|
+
y(U, g.indexeddb);
|
|
437
|
+
function S(r, e) {
|
|
438
438
|
return {
|
|
439
439
|
value: r,
|
|
440
440
|
expireAt: Date.now() + e
|
|
441
441
|
};
|
|
442
442
|
}
|
|
443
|
-
function
|
|
443
|
+
function v(r, e = Date.now()) {
|
|
444
444
|
return r.expireAt <= e;
|
|
445
445
|
}
|
|
446
|
-
function
|
|
447
|
-
return
|
|
446
|
+
function Z(r, e = Date.now()) {
|
|
447
|
+
return v(r, e) ? void 0 : r.value;
|
|
448
448
|
}
|
|
449
449
|
const H = (r) => {
|
|
450
450
|
const { config: e } = r, { method: t, url: n, data: s } = e;
|
|
451
451
|
return [t, n, JSON.stringify(s)].join("|");
|
|
452
|
-
}, L = () => !0,
|
|
452
|
+
}, L = () => !0, b = 24 * 60 * 60 * 1e3, Q = {
|
|
453
453
|
key: H,
|
|
454
|
-
duration:
|
|
454
|
+
duration: b,
|
|
455
455
|
isValid: L,
|
|
456
456
|
store: g.memory
|
|
457
457
|
// 默认不持久化,使用内存存储
|
|
458
458
|
};
|
|
459
|
-
|
|
459
|
+
class W {
|
|
460
460
|
store;
|
|
461
461
|
constructor(e) {
|
|
462
|
-
return typeof e == "string" ? this.store =
|
|
462
|
+
return typeof e == "string" ? this.store = f(e) : (y(e.factory, e.key), this.store = f(e.key)), new Proxy(this, {
|
|
463
463
|
get(t, n) {
|
|
464
464
|
if (n in t)
|
|
465
465
|
return t[n];
|
|
@@ -474,8 +474,8 @@ let W = class {
|
|
|
474
474
|
* @param value 要缓存的值
|
|
475
475
|
* @param duration 过期时长(毫秒),默认 24 小时
|
|
476
476
|
*/
|
|
477
|
-
setCache(e, t, n =
|
|
478
|
-
const s =
|
|
477
|
+
setCache(e, t, n = b) {
|
|
478
|
+
const s = S(t, n);
|
|
479
479
|
this.store.setItem(e, s);
|
|
480
480
|
}
|
|
481
481
|
/**
|
|
@@ -486,7 +486,7 @@ let W = class {
|
|
|
486
486
|
async getCache(e) {
|
|
487
487
|
const t = await this.store.getItem(e);
|
|
488
488
|
if (t)
|
|
489
|
-
return
|
|
489
|
+
return Z(t);
|
|
490
490
|
}
|
|
491
491
|
/**
|
|
492
492
|
* 检查是否有有效的缓存(未过期)
|
|
@@ -495,9 +495,9 @@ let W = class {
|
|
|
495
495
|
*/
|
|
496
496
|
async hasValidCache(e) {
|
|
497
497
|
const t = await this.store.getItem(e);
|
|
498
|
-
return t ? !
|
|
498
|
+
return t ? !v(t) : !1;
|
|
499
499
|
}
|
|
500
|
-
}
|
|
500
|
+
}
|
|
501
501
|
const ee = W, te = (r) => {
|
|
502
502
|
const e = { ...Q, ...r }, t = new ee(e.store), n = (o) => typeof e.duration == "function" ? e.duration(o) : e.duration;
|
|
503
503
|
return Object.assign(async ({ config: o, next: i }) => {
|
|
@@ -510,121 +510,45 @@ const ee = W, te = (r) => {
|
|
|
510
510
|
})) return c;
|
|
511
511
|
t.removeItem(a);
|
|
512
512
|
}
|
|
513
|
-
const u = await i(),
|
|
514
|
-
return t.setItem(a,
|
|
513
|
+
const u = await i(), w = n({ key: a, config: o, cachedData: c, response: u }), O = S(u, w);
|
|
514
|
+
return t.setItem(a, O), u;
|
|
515
515
|
}, {
|
|
516
516
|
__middlewareType: m.CACHE,
|
|
517
517
|
storage: t
|
|
518
518
|
});
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
return typeof e == "string" ? this.store = w(e) : (y(e.factory, e.key), this.store = w(e.key)), new Proxy(this, {
|
|
524
|
-
get(t, n) {
|
|
525
|
-
if (n in t)
|
|
526
|
-
return t[n];
|
|
527
|
-
const s = t.store[n];
|
|
528
|
-
return typeof s == "function" ? s.bind(t.store) : s;
|
|
529
|
-
}
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
/**
|
|
533
|
-
* 设置缓存(自动包装成 ExpirableValue)
|
|
534
|
-
* @param key 缓存 key
|
|
535
|
-
* @param value 要缓存的值
|
|
536
|
-
* @param duration 过期时长(毫秒),默认 24 小时
|
|
537
|
-
*/
|
|
538
|
-
setCache(e, t, n = k) {
|
|
539
|
-
const s = C(t, n);
|
|
540
|
-
this.store.setItem(e, s);
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* 获取缓存值(检查过期,如果过期返回 undefined)
|
|
544
|
-
* @param key 缓存 key
|
|
545
|
-
* @returns 未过期返回值,已过期返回 undefined
|
|
546
|
-
*/
|
|
547
|
-
getCache(e) {
|
|
548
|
-
const t = this.store.getItem(e);
|
|
549
|
-
if (t)
|
|
550
|
-
return x(t);
|
|
551
|
-
}
|
|
552
|
-
/**
|
|
553
|
-
* 检查是否有有效的缓存(未过期)
|
|
554
|
-
* @param key 缓存 key
|
|
555
|
-
* @returns true 表示有有效缓存,false 表示无缓存或已过期
|
|
556
|
-
*/
|
|
557
|
-
hasValidCache(e) {
|
|
558
|
-
const t = this.store.getItem(e);
|
|
559
|
-
return t ? !I(t) : !1;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
const ne = re, se = (r) => {
|
|
563
|
-
const { config: e } = r, { method: t, url: n } = e;
|
|
564
|
-
return [t, n].join("|");
|
|
565
|
-
}, oe = {
|
|
566
|
-
suspense: !0,
|
|
567
|
-
key: se,
|
|
568
|
-
duration: 24 * 60 * 60 * 1e3,
|
|
569
|
-
isValid: () => !0,
|
|
570
|
-
store: g.memory
|
|
571
|
-
};
|
|
572
|
-
function me(r) {
|
|
573
|
-
const e = { ...oe, ...r }, t = new ne(e.store), n = (o) => typeof e.duration == "function" ? e.duration(o) : e.duration;
|
|
574
|
-
return Object.assign(({ config: o, next: i }) => {
|
|
575
|
-
const a = e.key({ config: o }), c = t.getCache(a);
|
|
576
|
-
if (c) {
|
|
577
|
-
if (e.isValid({
|
|
578
|
-
key: a,
|
|
579
|
-
config: o,
|
|
580
|
-
cachedData: c
|
|
581
|
-
})) return c;
|
|
582
|
-
t.removeItem(a);
|
|
583
|
-
}
|
|
584
|
-
if (e.suspense)
|
|
585
|
-
throw (e.wrapSuspense ? e.wrapSuspense({ key: a, config: o, p: i() }) : i()).then((l) => {
|
|
586
|
-
const p = n({ key: a, config: o, cachedData: c, response: l });
|
|
587
|
-
return t.setCache(a, l, p), l;
|
|
588
|
-
});
|
|
589
|
-
return i().then((u) => {
|
|
590
|
-
const l = n({ key: a, config: o, cachedData: c, response: u });
|
|
591
|
-
return t.setCache(a, u, l), u;
|
|
592
|
-
});
|
|
593
|
-
}, { __middlewareType: m.SYNC });
|
|
594
|
-
}
|
|
595
|
-
const P = /* @__PURE__ */ new Map(), ye = (r, e = S) => {
|
|
596
|
-
P.set(e, r);
|
|
597
|
-
}, ae = (r = S) => {
|
|
598
|
-
const e = P.get(r);
|
|
519
|
+
}, N = /* @__PURE__ */ new Map(), ce = (r, e = p) => {
|
|
520
|
+
N.set(e, r);
|
|
521
|
+
}, re = (r = p) => {
|
|
522
|
+
const e = N.get(r);
|
|
599
523
|
if (!e) throw new Error(`Requestor实例 ${String(r)} 未注册`);
|
|
600
524
|
return e;
|
|
601
|
-
},
|
|
525
|
+
}, P = {
|
|
602
526
|
get: (r, e) => ({
|
|
603
527
|
url: r,
|
|
604
|
-
method:
|
|
528
|
+
method: h.GET,
|
|
605
529
|
...e,
|
|
606
530
|
params: e?.params
|
|
607
531
|
}),
|
|
608
532
|
post: (r, e, t) => ({
|
|
609
533
|
url: r,
|
|
610
|
-
method:
|
|
534
|
+
method: h.POST,
|
|
611
535
|
data: e,
|
|
612
536
|
...t
|
|
613
537
|
}),
|
|
614
538
|
delete: (r, e) => ({
|
|
615
539
|
url: r,
|
|
616
|
-
method:
|
|
540
|
+
method: h.DELETE,
|
|
617
541
|
...e
|
|
618
542
|
}),
|
|
619
543
|
put: (r, e, t) => ({
|
|
620
544
|
url: r,
|
|
621
|
-
method:
|
|
545
|
+
method: h.PUT,
|
|
622
546
|
data: e,
|
|
623
547
|
...t
|
|
624
548
|
}),
|
|
625
549
|
request: (r) => r
|
|
626
|
-
},
|
|
627
|
-
function
|
|
550
|
+
}, ne = Object.keys(P);
|
|
551
|
+
function se(r, e, t) {
|
|
628
552
|
const n = {}, s = (o) => {
|
|
629
553
|
if (o === e.length)
|
|
630
554
|
return t(r);
|
|
@@ -637,13 +561,13 @@ function ce(r, e, t) {
|
|
|
637
561
|
};
|
|
638
562
|
return s(0);
|
|
639
563
|
}
|
|
640
|
-
function
|
|
564
|
+
function oe(r, e) {
|
|
641
565
|
const t = {}, n = e ?? [];
|
|
642
|
-
return
|
|
566
|
+
return ne.forEach(
|
|
643
567
|
(s) => {
|
|
644
568
|
t[s] = (...o) => {
|
|
645
|
-
const i =
|
|
646
|
-
return
|
|
569
|
+
const i = P[s](...o);
|
|
570
|
+
return se(
|
|
647
571
|
i,
|
|
648
572
|
n,
|
|
649
573
|
r
|
|
@@ -652,42 +576,41 @@ function ue(r, e) {
|
|
|
652
576
|
}
|
|
653
577
|
), t;
|
|
654
578
|
}
|
|
655
|
-
function
|
|
656
|
-
const { extensions: e, instanceKey: t } = r ?? {}, n =
|
|
657
|
-
return
|
|
579
|
+
function x(r) {
|
|
580
|
+
const { extensions: e, instanceKey: t } = r ?? {}, n = re(t);
|
|
581
|
+
return oe(
|
|
658
582
|
n,
|
|
659
583
|
e
|
|
660
584
|
);
|
|
661
585
|
}
|
|
662
|
-
function
|
|
586
|
+
function ue(r) {
|
|
663
587
|
const { instanceKey: e, key: t, duration: n, isValid: s, store: o, ...i } = r;
|
|
664
|
-
return
|
|
588
|
+
return x({
|
|
665
589
|
instanceKey: e,
|
|
666
590
|
extensions: [
|
|
667
|
-
|
|
591
|
+
E(i),
|
|
668
592
|
te({ key: t, duration: n, isValid: s, store: o })
|
|
669
593
|
]
|
|
670
594
|
});
|
|
671
595
|
}
|
|
672
|
-
function
|
|
596
|
+
function le(r) {
|
|
673
597
|
const { instanceKey: e, parallelCount: t, createId: n, retries: s, delay: o, retryCondition: i } = r;
|
|
674
|
-
return
|
|
598
|
+
return x({
|
|
675
599
|
instanceKey: e,
|
|
676
600
|
extensions: [
|
|
677
601
|
K({ parallelCount: t, createId: n }),
|
|
678
|
-
|
|
602
|
+
D({ retries: s, delay: o, retryCondition: i })
|
|
679
603
|
]
|
|
680
604
|
});
|
|
681
605
|
}
|
|
682
606
|
export {
|
|
683
607
|
te as cache,
|
|
684
608
|
K as concurrent,
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
ae as useRequestor
|
|
609
|
+
ue as createCachedIdempotentRequestor,
|
|
610
|
+
le as createConcurrentRetryRequestor,
|
|
611
|
+
x as createRequestor,
|
|
612
|
+
E as idempotent,
|
|
613
|
+
ce as inject,
|
|
614
|
+
D as retry,
|
|
615
|
+
re as useRequestor
|
|
693
616
|
};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(u,w){typeof exports=="object"&&typeof module<"u"?w(exports,require("id-queue")):typeof define=="function"&&define.amd?define(["exports","id-queue"],w):(u=typeof globalThis<"u"?globalThis:u||self,w(u.netVertCore={},u.idQueue))})(this,function(u,w){"use strict";var p=(r=>(r.GET="get",r.POST="post",r.PUT="put",r.DELETE="delete",r))(p||{}),y=(r=>(r.CACHE="cache",r.RETRY="retry",r.IDEMPOTENT="idempotent",r.CONCURRENT="concurrent",r.SYNC="sync",r))(y||{});const N="default",E={retries:3,delay:0,retryCondition:()=>!0},P=r=>{const e={...E,...r};return Object.assign(async({config:n,next:s})=>{let o=0,a;for(;o<=e.retries;)try{return await s()}catch(i){if(a=i,o===e.retries)throw i;const c={config:n,lastResponse:i,attempt:o};if(!e.retryCondition(c))throw i;o++;const l=typeof e.delay=="function"?e.delay(c):e.delay;l>0&&await new Promise(d=>setTimeout(d,l))}throw a},{__middlewareType:y.RETRY})},B=()=>{const r=new Map;return{getPromise:o=>r.get(o),setPromise:(o,a)=>{r.set(o,a),a.finally(()=>r.delete(o))},delPromise:o=>r.delete(o),clearCache:()=>r.clear()}},K={key:r=>{const{config:e}=r,{method:t,url:n,data:s}=e;return[t,n,JSON.stringify(s)].join("|")}},V=r=>{const e={...K,...r},t=B();return Object.assign(({config:s,next:o})=>{const a=e.key({config:s}),i=t.getPromise(a);if(i)return i;const c=o();return t.setPromise(a,c),c},{__middlewareType:y.IDEMPOTENT,promiseCache:t})};class _{parallelCount;tasks;runningCount;constructor(e=4){this.parallelCount=e,this.tasks=new w.TaskQueue,this.runningCount=0}add(e,t){return new Promise((n,s)=>{this.tasks.enqueue(e,{task:t,resolve:n,reject:s}),this._run()})}remove(e){this.tasks.remove(e)}execute(e){const{task:t,resolve:n,reject:s}=e;return t().then(n).catch(s).finally(()=>{this.runningCount--,this._run()})}_run(){for(;this.runningCount<this.parallelCount&&this.tasks.size>0;){const e=this.tasks.dequeue();this.runningCount++,this.execute(e)}}}let A=0;const J={parallelCount:4,createId:()=>A++},x=r=>{const{parallelCount:e,createId:t}={...J,...r},n=new _(e);return Object.assign(({config:o,next:a})=>{const i=t({config:o});return n.add(i,()=>a())},{__middlewareType:y.CONCURRENT,pool:n})},O=new Map,f=(r,e)=>{O.set(e,r)};function z(r){const e=O.get(r);if(!e)throw new Error(`Store实例 ${String(r)} 未注册`);return e}class G{store=new Map;getItem(e){return this.store.get(e)}setItem(e,t){return this.store.set(e,t),t}removeItem(e){this.store.delete(e)}clear(){this.store.clear()}length(){return this.store.size}key(e){return Array.from(this.store.keys())[e]}keys(){return Array.from(this.store.keys())}iterate(e){let t=0;for(const[n,s]of this.store.entries())e(s,n,t),t++}}const U=r=>!!r&&(typeof r=="object"||typeof r=="function")&&typeof r.then=="function",q=r=>typeof window<"u"?r():{getItem(){return null},setItem(){},removeItem(){},clear(){},key(){return null},get length(){return 0}},h=q(()=>window.localStorage);class M{constructor(){}getItem(e){const t=String(e),n=h.getItem(t);if(n!==null)try{return JSON.parse(n)}catch(s){console.error(`Failed to parse value for key: ${t}`,s);return}}setItem(e,t){const n=String(e);try{h.setItem(n,JSON.stringify(t))}catch(s){throw console.error(`Failed to set value for key: ${n}`,s),s}return t}removeItem(e){const t=String(e);h.removeItem(t)}clear(){h.clear()}length(){return h.length}key(e){return h.key(e)}keys(){const e=[];for(let t=0;t<h.length;t++){const n=h.key(t);n&&e.push(n)}return e}iterate(e){this.keys().forEach((t,n)=>{const s=this.getItem(t);s!==void 0&&e(s,t,n)})}}const m=q(()=>window.sessionStorage);class Y{constructor(){}getItem(e){const t=String(e),n=m.getItem(t);if(n!==null)try{return JSON.parse(n)}catch(s){console.error(`Failed to parse value for key: ${t}`,s);return}}setItem(e,t){const n=String(e);try{m.setItem(n,JSON.stringify(t))}catch(s){throw console.error(`Failed to set value for key: ${n}`,s),s}return t}removeItem(e){const t=String(e);m.removeItem(t)}clear(){m.clear()}length(){return m.length}key(e){return m.key(e)}keys(){const e=[];for(let t=0;t<m.length;t++){const n=m.key(t);n&&e.push(n)}return e}iterate(e){this.keys().forEach((t,n)=>{const s=this.getItem(t);s!==void 0&&e(s,t,n)})}}class X{dbName;storeName;dbPromise=null;DB_VERSION=1;constructor(e,t){this.dbName=e,this.storeName=t,this.initDB()}initDB(){if(typeof window>"u"||!window.indexedDB){console.warn("IndexedDB is not available");return}this.dbPromise=new Promise((e,t)=>{const n=indexedDB.open(this.dbName,this.DB_VERSION);n.onerror=()=>{t(new Error(`Failed to open database: ${this.dbName}`))},n.onsuccess=()=>{e(n.result)},n.onupgradeneeded=s=>{const o=s.target.result;o.objectStoreNames.contains(this.storeName)||o.createObjectStore(this.storeName)}})}async getDB(){if(!this.dbPromise)throw new Error("IndexedDB is not initialized");return this.dbPromise}async withStore(e,t){const n=await this.getDB();return new Promise((s,o)=>{const a=n.transaction([this.storeName],e).objectStore(this.storeName),i=t(a);i.onsuccess=()=>{s(i.result)},i.onerror=()=>{o(i.error)}})}async getItem(e){try{const t=await this.withStore("readonly",n=>n.get(String(e)));return t===void 0?void 0:t}catch(t){console.error(`Failed to get value for key: ${String(e)}`,t);return}}async setItem(e,t){try{return await this.withStore("readwrite",n=>n.put(t,String(e))),t}catch(n){throw console.error(`Failed to set value for key: ${String(e)}`,n),n}}async removeItem(e){try{await this.withStore("readwrite",t=>t.delete(String(e)))}catch(t){throw console.error(`Failed to remove value for key: ${String(e)}`,t),t}}async clear(){try{await this.withStore("readwrite",e=>e.clear())}catch(e){throw console.error("Failed to clear storage",e),e}}async length(){try{return await this.withStore("readonly",e=>e.count())}catch(e){return console.error("Failed to get storage length",e),0}}async key(e){try{return(await this.withStore("readonly",t=>t.getAllKeys()))[e]}catch(t){console.error("Failed to get key",t);return}}async keys(){try{return await this.withStore("readonly",e=>e.getAllKeys())}catch(e){return console.error("Failed to get all keys",e),[]}}async iterate(e){try{const t=(await this.getDB()).transaction([this.storeName],"readonly").objectStore(this.storeName).openCursor();return new Promise((n,s)=>{let o=0;t.onsuccess=a=>{const i=a.target.result;if(i){const c=i.key,l=i.value;e(l,c,o),o++,i.continue()}else n()},t.onerror=()=>{s(t.error)}})}catch(t){console.error("Failed to iterate storage",t)}}}const g={memory:"memory",local:"local",session:"session",indexeddb:"indexeddb"};function j(r,e){Object.assign(r,e)}function Z(r){return j(r,{async getItemOrDefault(e,t){const n=await this.getItem(e);return n!==null?n:t},async hasItem(e){return await this.getItem(e)!==null},async removeItems(e){await Promise.all(e.map(t=>this.removeItem(t)))},async getItems(e){return await Promise.all(e.map(t=>this.getItem(t)))}}),r}function H(r){return j(r,{getItemOrDefault(e,t){const n=this.getItem(e);return n!==null?n:t},hasItem(e){return this.getItem(e)!==null},removeItems(e){e.forEach(t=>this.removeItem(t))},getItems(e){return e.map(t=>this.getItem(t))}}),r}function L(r){const e=r.getItem("");return U(e)?Z(r):H(r)}function C(r,...e){const t=z(r);let n;try{n=new t(...e)}catch{n=t(...e)}return L(n)}f(G,g.memory),f(M,g.local),f(Y,g.session),f(X,g.indexeddb);function I(r,e){return{value:r,expireAt:Date.now()+e}}function k(r,e=Date.now()){return r.expireAt<=e}function R(r,e=Date.now()){return k(r,e)?void 0:r.value}const Q=r=>{const{config:e}=r,{method:t,url:n,data:s}=e;return[t,n,JSON.stringify(s)].join("|")},W=()=>!0,S=24*60*60*1e3,ee={key:Q,duration:S,isValid:W,store:g.memory},te=class{store;constructor(e){return typeof e=="string"?this.store=C(e):(f(e.factory,e.key),this.store=C(e.key)),new Proxy(this,{get(t,n){if(n in t)return t[n];const s=t.store[n];return typeof s=="function"?s.bind(t.store):s}})}setCache(e,t,n=S){const s=I(t,n);this.store.setItem(e,s)}async getCache(e){const t=await this.store.getItem(e);if(t)return R(t)}async hasValidCache(e){const t=await this.store.getItem(e);return t?!k(t):!1}},T=r=>{const e={...ee,...r},t=new te(e.store),n=o=>typeof e.duration=="function"?e.duration(o):e.duration;return Object.assign(async({config:o,next:a})=>{const i=e.key({config:o}),c=await t.getCache(i);if(c){if(await e.isValid({key:i,config:o,cachedData:c}))return c;t.removeItem(i)}const l=await a(),d=n({key:i,config:o,cachedData:c,response:l}),v=I(l,d);return t.setItem(i,v),l},{__middlewareType:y.CACHE,storage:t})};class re{store;constructor(e){return typeof e=="string"?this.store=C(e):(f(e.factory,e.key),this.store=C(e.key)),new Proxy(this,{get(t,n){if(n in t)return t[n];const s=t.store[n];return typeof s=="function"?s.bind(t.store):s}})}setCache(e,t,n=S){const s=I(t,n);this.store.setItem(e,s)}getCache(e){const t=this.store.getItem(e);if(t)return R(t)}hasValidCache(e){const t=this.store.getItem(e);return t?!k(t):!1}}const ne=re,se={suspense:!0,key:r=>{const{config:e}=r,{method:t,url:n}=e;return[t,n].join("|")},duration:24*60*60*1e3,isValid:()=>!0,store:g.memory};function oe(r){const e={...se,...r},t=new ne(e.store),n=o=>typeof e.duration=="function"?e.duration(o):e.duration;return Object.assign(({config:o,next:a})=>{const i=e.key({config:o}),c=t.getCache(i);if(c){if(e.isValid({key:i,config:o,cachedData:c}))return c;t.removeItem(i)}if(e.suspense)throw(e.wrapSuspense?e.wrapSuspense({key:i,config:o,p:a()}):a()).then(d=>{const v=n({key:i,config:o,cachedData:c,response:d});return t.setCache(i,d,v),d});return a().then(l=>{const d=n({key:i,config:o,cachedData:c,response:l});return t.setCache(i,l,d),l})},{__middlewareType:y.SYNC})}const D=new Map,ie=(r,e=N)=>{D.set(e,r)},F=(r=N)=>{const e=D.get(r);if(!e)throw new Error(`Requestor实例 ${String(r)} 未注册`);return e},$={get:(r,e)=>({url:r,method:p.GET,...e,params:e?.params}),post:(r,e,t)=>({url:r,method:p.POST,data:e,...t}),delete:(r,e)=>({url:r,method:p.DELETE,...e}),put:(r,e,t)=>({url:r,method:p.PUT,data:e,...t}),request:r=>r},ae=Object.keys($);function ce(r,e,t){const n={},s=o=>{if(o===e.length)return t(r);const a=e[o];return a({config:r,ctx:n,next:()=>s(o+1)})};return s(0)}function ue(r,e){const t={},n=e??[];return ae.forEach(s=>{t[s]=(...o)=>{const a=$[s](...o);return ce(a,n,r)}}),t}function b(r){const{extensions:e,instanceKey:t}=r??{},n=F(t);return ue(n,e)}function le(r){const{instanceKey:e,key:t,duration:n,isValid:s,store:o,...a}=r;return b({instanceKey:e,extensions:[V(a),T({key:t,duration:n,isValid:s,store:o})]})}function de(r){const{instanceKey:e,parallelCount:t,createId:n,retries:s,delay:o,retryCondition:a}=r;return b({instanceKey:e,extensions:[x({parallelCount:t,createId:n}),P({retries:s,delay:o,retryCondition:a})]})}u.cache=T,u.concurrent=x,u.createCachedIdempotentRequestor=le,u.createConcurrentRetryRequestor=de,u.createRequestor=b,u.idempotent=V,u.inject=ie,u.retry=P,u.sync=oe,u.useRequestor=F,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(c,m){typeof exports=="object"&&typeof module<"u"?m(exports,require("id-queue")):typeof define=="function"&&define.amd?define(["exports","id-queue"],m):(c=typeof globalThis<"u"?globalThis:c||self,m(c.netVertCore={},c.idQueue))})(this,function(c,m){"use strict";var y=(r=>(r.GET="get",r.POST="post",r.PUT="put",r.DELETE="delete",r))(y||{}),g=(r=>(r.CACHE="cache",r.RETRY="retry",r.IDEMPOTENT="idempotent",r.CONCURRENT="concurrent",r.SYNC="sync",r))(g||{});const C="default",V={retries:3,delay:0,retryCondition:()=>!0},k=r=>{const e={...V,...r};return Object.assign(async({config:n,next:o})=>{let s=0,a;for(;s<=e.retries;)try{return await o()}catch(i){if(a=i,s===e.retries)throw i;const u={config:n,lastResponse:i,attempt:s};if(!e.retryCondition(u))throw i;s++;const h=typeof e.delay=="function"?e.delay(u):e.delay;h>0&&await new Promise(I=>setTimeout(I,h))}throw a},{__middlewareType:g.RETRY})},E=()=>{const r=new Map;return{getPromise:s=>r.get(s),setPromise:(s,a)=>{r.set(s,a),a.finally(()=>r.delete(s))},delPromise:s=>r.delete(s),clearCache:()=>r.clear()}},$={key:r=>{const{config:e}=r,{method:t,url:n,data:o}=e;return[t,n,JSON.stringify(o)].join("|")}},S=r=>{const e={...$,...r},t=E();return Object.assign(({config:o,next:s})=>{const a=e.key({config:o}),i=t.getPromise(a);if(i)return i;const u=s();return t.setPromise(a,u),u},{__middlewareType:g.IDEMPOTENT,promiseCache:t})};class B{parallelCount;tasks;runningCount;constructor(e=4){this.parallelCount=e,this.tasks=new m.TaskQueue,this.runningCount=0}add(e,t){return new Promise((n,o)=>{this.tasks.enqueue(e,{task:t,resolve:n,reject:o}),this._run()})}remove(e){this.tasks.remove(e)}execute(e){const{task:t,resolve:n,reject:o}=e;return t().then(n).catch(o).finally(()=>{this.runningCount--,this._run()})}_run(){for(;this.runningCount<this.parallelCount&&this.tasks.size>0;){const e=this.tasks.dequeue();this.runningCount++,this.execute(e)}}}let K=0;const _={parallelCount:4,createId:()=>K++},v=r=>{const{parallelCount:e,createId:t}={..._,...r},n=new B(e);return Object.assign(({config:s,next:a})=>{const i=t({config:s});return n.add(i,()=>a())},{__middlewareType:g.CONCURRENT,pool:n})},b=new Map,f=(r,e)=>{b.set(e,r)};function A(r){const e=b.get(r);if(!e)throw new Error(`Store实例 ${String(r)} 未注册`);return e}class J{store=new Map;getItem(e){return this.store.get(e)}setItem(e,t){return this.store.set(e,t),t}removeItem(e){this.store.delete(e)}clear(){this.store.clear()}length(){return this.store.size}key(e){return Array.from(this.store.keys())[e]}keys(){return Array.from(this.store.keys())}iterate(e){let t=0;for(const[n,o]of this.store.entries())e(o,n,t),t++}}const z=r=>!!r&&(typeof r=="object"||typeof r=="function")&&typeof r.then=="function",N=r=>typeof window<"u"?r():{getItem(){return null},setItem(){},removeItem(){},clear(){},key(){return null},get length(){return 0}},l=N(()=>window.localStorage);class G{constructor(){}getItem(e){const t=String(e),n=l.getItem(t);if(n!==null)try{return JSON.parse(n)}catch(o){console.error(`Failed to parse value for key: ${t}`,o);return}}setItem(e,t){const n=String(e);try{l.setItem(n,JSON.stringify(t))}catch(o){throw console.error(`Failed to set value for key: ${n}`,o),o}return t}removeItem(e){const t=String(e);l.removeItem(t)}clear(){l.clear()}length(){return l.length}key(e){return l.key(e)}keys(){const e=[];for(let t=0;t<l.length;t++){const n=l.key(t);n&&e.push(n)}return e}iterate(e){this.keys().forEach((t,n)=>{const o=this.getItem(t);o!==void 0&&e(o,t,n)})}}const d=N(()=>window.sessionStorage);class U{constructor(){}getItem(e){const t=String(e),n=d.getItem(t);if(n!==null)try{return JSON.parse(n)}catch(o){console.error(`Failed to parse value for key: ${t}`,o);return}}setItem(e,t){const n=String(e);try{d.setItem(n,JSON.stringify(t))}catch(o){throw console.error(`Failed to set value for key: ${n}`,o),o}return t}removeItem(e){const t=String(e);d.removeItem(t)}clear(){d.clear()}length(){return d.length}key(e){return d.key(e)}keys(){const e=[];for(let t=0;t<d.length;t++){const n=d.key(t);n&&e.push(n)}return e}iterate(e){this.keys().forEach((t,n)=>{const o=this.getItem(t);o!==void 0&&e(o,t,n)})}}class M{dbName;storeName;dbPromise=null;DB_VERSION=1;constructor(e,t){this.dbName=e,this.storeName=t,this.initDB()}initDB(){if(typeof window>"u"||!window.indexedDB){console.warn("IndexedDB is not available");return}this.dbPromise=new Promise((e,t)=>{const n=indexedDB.open(this.dbName,this.DB_VERSION);n.onerror=()=>{t(new Error(`Failed to open database: ${this.dbName}`))},n.onsuccess=()=>{e(n.result)},n.onupgradeneeded=o=>{const s=o.target.result;s.objectStoreNames.contains(this.storeName)||s.createObjectStore(this.storeName)}})}async getDB(){if(!this.dbPromise)throw new Error("IndexedDB is not initialized");return this.dbPromise}async withStore(e,t){const n=await this.getDB();return new Promise((o,s)=>{const a=n.transaction([this.storeName],e).objectStore(this.storeName),i=t(a);i.onsuccess=()=>{o(i.result)},i.onerror=()=>{s(i.error)}})}async getItem(e){try{const t=await this.withStore("readonly",n=>n.get(String(e)));return t===void 0?void 0:t}catch(t){console.error(`Failed to get value for key: ${String(e)}`,t);return}}async setItem(e,t){try{return await this.withStore("readwrite",n=>n.put(t,String(e))),t}catch(n){throw console.error(`Failed to set value for key: ${String(e)}`,n),n}}async removeItem(e){try{await this.withStore("readwrite",t=>t.delete(String(e)))}catch(t){throw console.error(`Failed to remove value for key: ${String(e)}`,t),t}}async clear(){try{await this.withStore("readwrite",e=>e.clear())}catch(e){throw console.error("Failed to clear storage",e),e}}async length(){try{return await this.withStore("readonly",e=>e.count())}catch(e){return console.error("Failed to get storage length",e),0}}async key(e){try{return(await this.withStore("readonly",t=>t.getAllKeys()))[e]}catch(t){console.error("Failed to get key",t);return}}async keys(){try{return await this.withStore("readonly",e=>e.getAllKeys())}catch(e){return console.error("Failed to get all keys",e),[]}}async iterate(e){try{const t=(await this.getDB()).transaction([this.storeName],"readonly").objectStore(this.storeName).openCursor();return new Promise((n,o)=>{let s=0;t.onsuccess=a=>{const i=a.target.result;if(i){const u=i.key,h=i.value;e(h,u,s),s++,i.continue()}else n()},t.onerror=()=>{o(t.error)}})}catch(t){console.error("Failed to iterate storage",t)}}}const w={memory:"memory",local:"local",session:"session",indexeddb:"indexeddb"};function P(r,e){Object.assign(r,e)}function X(r){return P(r,{async getItemOrDefault(e,t){const n=await this.getItem(e);return n!==null?n:t},async hasItem(e){return await this.getItem(e)!==null},async removeItems(e){await Promise.all(e.map(t=>this.removeItem(t)))},async getItems(e){return await Promise.all(e.map(t=>this.getItem(t)))}}),r}function Y(r){return P(r,{getItemOrDefault(e,t){const n=this.getItem(e);return n!==null?n:t},hasItem(e){return this.getItem(e)!==null},removeItems(e){e.forEach(t=>this.removeItem(t))},getItems(e){return e.map(t=>this.getItem(t))}}),r}function Z(r){const e=r.getItem("");return z(e)?X(r):Y(r)}function q(r,...e){const t=A(r);let n;try{n=new t(...e)}catch{n=t(...e)}return Z(n)}f(J,w.memory),f(G,w.local),f(U,w.session),f(M,w.indexeddb);function O(r,e){return{value:r,expireAt:Date.now()+e}}function R(r,e=Date.now()){return r.expireAt<=e}function H(r,e=Date.now()){return R(r,e)?void 0:r.value}const L=r=>{const{config:e}=r,{method:t,url:n,data:o}=e;return[t,n,JSON.stringify(o)].join("|")},Q=()=>!0,j=24*60*60*1e3,W={key:L,duration:j,isValid:Q,store:w.memory};class ee{store;constructor(e){return typeof e=="string"?this.store=q(e):(f(e.factory,e.key),this.store=q(e.key)),new Proxy(this,{get(t,n){if(n in t)return t[n];const o=t.store[n];return typeof o=="function"?o.bind(t.store):o}})}setCache(e,t,n=j){const o=O(t,n);this.store.setItem(e,o)}async getCache(e){const t=await this.store.getItem(e);if(t)return H(t)}async hasValidCache(e){const t=await this.store.getItem(e);return t?!R(t):!1}}const te=ee,x=r=>{const e={...W,...r},t=new te(e.store),n=s=>typeof e.duration=="function"?e.duration(s):e.duration;return Object.assign(async({config:s,next:a})=>{const i=e.key({config:s}),u=await t.getCache(i);if(u){if(await e.isValid({key:i,config:s,cachedData:u}))return u;t.removeItem(i)}const h=await a(),I=n({key:i,config:s,cachedData:u,response:h}),ce=O(h,I);return t.setItem(i,ce),h},{__middlewareType:g.CACHE,storage:t})},T=new Map,re=(r,e=C)=>{T.set(e,r)},F=(r=C)=>{const e=T.get(r);if(!e)throw new Error(`Requestor实例 ${String(r)} 未注册`);return e},D={get:(r,e)=>({url:r,method:y.GET,...e,params:e?.params}),post:(r,e,t)=>({url:r,method:y.POST,data:e,...t}),delete:(r,e)=>({url:r,method:y.DELETE,...e}),put:(r,e,t)=>({url:r,method:y.PUT,data:e,...t}),request:r=>r},ne=Object.keys(D);function oe(r,e,t){const n={},o=s=>{if(s===e.length)return t(r);const a=e[s];return a({config:r,ctx:n,next:()=>o(s+1)})};return o(0)}function se(r,e){const t={},n=e??[];return ne.forEach(o=>{t[o]=(...s)=>{const a=D[o](...s);return oe(a,n,r)}}),t}function p(r){const{extensions:e,instanceKey:t}=r??{},n=F(t);return se(n,e)}function ie(r){const{instanceKey:e,key:t,duration:n,isValid:o,store:s,...a}=r;return p({instanceKey:e,extensions:[S(a),x({key:t,duration:n,isValid:o,store:s})]})}function ae(r){const{instanceKey:e,parallelCount:t,createId:n,retries:o,delay:s,retryCondition:a}=r;return p({instanceKey:e,extensions:[v({parallelCount:t,createId:n}),k({retries:o,delay:s,retryCondition:a})]})}c.cache=x,c.concurrent=v,c.createCachedIdempotentRequestor=ie,c.createConcurrentRetryRequestor=ae,c.createRequestor=p,c.idempotent=S,c.inject=re,c.retry=k,c.useRequestor=F,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});
|