@ahoo-wang/fetcher-cosec 0.3.8 → 0.5.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 +150 -33
- package/README.zh-CN.md +149 -32
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
# @ahoo-wang/fetcher-cosec
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@ahoo-wang/fetcher-cosec)
|
|
4
|
+
[](https://github.com/Ahoo-Wang/fetcher/actions)
|
|
5
|
+
[](https://codecov.io/gh/Ahoo-Wang/fetcher)
|
|
6
|
+
[](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/@ahoo-wang/fetcher-cosec)
|
|
8
|
+
|
|
3
9
|
Support for CoSec authentication in Fetcher HTTP client.
|
|
4
10
|
|
|
5
11
|
[CoSec](https://github.com/Ahoo-Wang/CoSec) is a comprehensive authentication and authorization framework.
|
|
6
12
|
|
|
7
13
|
This package provides integration between the Fetcher HTTP client and the CoSec authentication framework.
|
|
8
14
|
|
|
9
|
-
## Features
|
|
15
|
+
## 🌟 Features
|
|
16
|
+
|
|
17
|
+
- **🔐 Automatic Authentication**: Automatic CoSec authentication headers
|
|
18
|
+
- **📱 Device Management**: Device ID management with localStorage persistence
|
|
19
|
+
- **🔄 Token Refresh**: Automatic token refresh based on response codes (401)
|
|
20
|
+
- **追踪 Request Tracking**: Unique request ID generation for tracking
|
|
21
|
+
- **💾 Token Storage**: Secure token storage management
|
|
22
|
+
- **🛡️ TypeScript Support**: Complete TypeScript type definitions
|
|
10
23
|
|
|
11
|
-
|
|
12
|
-
- Device ID management with localStorage persistence
|
|
13
|
-
- Automatic token refresh based on response codes (401)
|
|
14
|
-
- Request ID generation for tracking
|
|
15
|
-
- Token storage management
|
|
24
|
+
## 🚀 Quick Start
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
### Installation
|
|
18
27
|
|
|
19
28
|
```bash
|
|
29
|
+
# Using npm
|
|
20
30
|
npm install @ahoo-wang/fetcher-cosec
|
|
21
|
-
```
|
|
22
31
|
|
|
23
|
-
|
|
32
|
+
# Using pnpm
|
|
33
|
+
pnpm add @ahoo-wang/fetcher-cosec
|
|
34
|
+
|
|
35
|
+
# Using yarn
|
|
36
|
+
yarn add @ahoo-wang/fetcher-cosec
|
|
37
|
+
```
|
|
24
38
|
|
|
25
39
|
### Basic Setup
|
|
26
40
|
|
|
@@ -85,7 +99,9 @@ fetcher.interceptors.response.use(
|
|
|
85
99
|
);
|
|
86
100
|
```
|
|
87
101
|
|
|
88
|
-
|
|
102
|
+
## 🔧 Configuration
|
|
103
|
+
|
|
104
|
+
### CoSecOptions Interface
|
|
89
105
|
|
|
90
106
|
```typescript
|
|
91
107
|
interface CoSecOptions {
|
|
@@ -120,18 +136,37 @@ The interceptor automatically adds the following headers to requests:
|
|
|
120
136
|
3. `Authorization`: Bearer token
|
|
121
137
|
4. `CoSec-Request-Id`: Unique request identifier for each request
|
|
122
138
|
|
|
123
|
-
|
|
139
|
+
## 📚 API Reference
|
|
124
140
|
|
|
125
|
-
|
|
126
|
-
the `tokenRefresher.refresh` function is called to obtain new access and refresh tokens.
|
|
141
|
+
### Core Classes
|
|
127
142
|
|
|
128
|
-
|
|
143
|
+
#### CoSecRequestInterceptor
|
|
129
144
|
|
|
130
|
-
|
|
145
|
+
Adds CoSec authentication headers to outgoing requests.
|
|
131
146
|
|
|
132
147
|
```typescript
|
|
133
|
-
|
|
148
|
+
new CoSecRequestInterceptor(options
|
|
149
|
+
:
|
|
150
|
+
CoSecOptions
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### CoSecResponseInterceptor
|
|
134
155
|
|
|
156
|
+
Handles token refresh when the server returns status code 401.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
new CoSecResponseInterceptor(options
|
|
160
|
+
:
|
|
161
|
+
CoSecOptions
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### TokenStorage
|
|
166
|
+
|
|
167
|
+
Manages token storage in localStorage.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
135
170
|
const tokenStorage = new TokenStorage();
|
|
136
171
|
|
|
137
172
|
// Store tokens
|
|
@@ -142,22 +177,16 @@ tokenStorage.set({
|
|
|
142
177
|
|
|
143
178
|
// Get tokens
|
|
144
179
|
const token = tokenStorage.get();
|
|
145
|
-
if (token) {
|
|
146
|
-
console.log('Access token:', token.accessToken);
|
|
147
|
-
console.log('Refresh token:', token.refreshToken);
|
|
148
|
-
}
|
|
149
180
|
|
|
150
181
|
// Clear tokens
|
|
151
182
|
tokenStorage.clear();
|
|
152
183
|
```
|
|
153
184
|
|
|
154
|
-
|
|
185
|
+
#### DeviceIdStorage
|
|
155
186
|
|
|
156
|
-
|
|
187
|
+
Manages device ID storage in localStorage.
|
|
157
188
|
|
|
158
189
|
```typescript
|
|
159
|
-
import { DeviceIdStorage } from '@ahoo-wang/fetcher-cosec';
|
|
160
|
-
|
|
161
190
|
const deviceIdStorage = new DeviceIdStorage();
|
|
162
191
|
|
|
163
192
|
// Get or create a device ID
|
|
@@ -176,7 +205,13 @@ deviceIdStorage.clear();
|
|
|
176
205
|
const newDeviceId = deviceIdStorage.generateDeviceId();
|
|
177
206
|
```
|
|
178
207
|
|
|
179
|
-
|
|
208
|
+
#### InMemoryStorage
|
|
209
|
+
|
|
210
|
+
In-memory storage fallback for environments without localStorage.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
const inMemoryStorage = new InMemoryStorage();
|
|
214
|
+
```
|
|
180
215
|
|
|
181
216
|
### Interfaces
|
|
182
217
|
|
|
@@ -185,20 +220,102 @@ const newDeviceId = deviceIdStorage.generateDeviceId();
|
|
|
185
220
|
- `CompositeToken`: Contains both access and refresh tokens
|
|
186
221
|
- `TokenRefresher`: Provides a method to refresh tokens
|
|
187
222
|
|
|
188
|
-
|
|
223
|
+
## 🛠️ Examples
|
|
224
|
+
|
|
225
|
+
### Complete Authentication Setup
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { Fetcher } from '@ahoo-wang/fetcher';
|
|
229
|
+
import {
|
|
230
|
+
CoSecRequestInterceptor,
|
|
231
|
+
CoSecResponseInterceptor,
|
|
232
|
+
DeviceIdStorage,
|
|
233
|
+
TokenStorage,
|
|
234
|
+
} from '@ahoo-wang/fetcher-cosec';
|
|
235
|
+
|
|
236
|
+
// Create storage instances
|
|
237
|
+
const deviceIdStorage = new DeviceIdStorage();
|
|
238
|
+
const tokenStorage = new TokenStorage();
|
|
239
|
+
|
|
240
|
+
// Create token refresher
|
|
241
|
+
const tokenRefresher = {
|
|
242
|
+
async refresh(token) {
|
|
243
|
+
const response = await fetch('/api/auth/refresh', {
|
|
244
|
+
method: 'POST',
|
|
245
|
+
headers: {
|
|
246
|
+
'Content-Type': 'application/json',
|
|
247
|
+
},
|
|
248
|
+
body: JSON.stringify({
|
|
249
|
+
refreshToken: token.refreshToken,
|
|
250
|
+
}),
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
if (!response.ok) {
|
|
254
|
+
throw new Error('Token refresh failed');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const tokens = await response.json();
|
|
258
|
+
return {
|
|
259
|
+
accessToken: tokens.accessToken,
|
|
260
|
+
refreshToken: tokens.refreshToken,
|
|
261
|
+
};
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// Create fetcher with CoSec interceptors
|
|
266
|
+
const secureFetcher = new Fetcher({
|
|
267
|
+
baseURL: 'https://api.example.com',
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
secureFetcher.interceptors.request.use(
|
|
271
|
+
new CoSecRequestInterceptor({
|
|
272
|
+
appId: 'my-app-id',
|
|
273
|
+
deviceIdStorage,
|
|
274
|
+
tokenStorage,
|
|
275
|
+
tokenRefresher,
|
|
276
|
+
}),
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
secureFetcher.interceptors.response.use(
|
|
280
|
+
new CoSecResponseInterceptor({
|
|
281
|
+
appId: 'my-app-id',
|
|
282
|
+
deviceIdStorage,
|
|
283
|
+
tokenStorage,
|
|
284
|
+
tokenRefresher,
|
|
285
|
+
}),
|
|
286
|
+
);
|
|
189
287
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
- `CoSecResponseInterceptor`: Handles token refresh on 401 responses
|
|
194
|
-
- `InMemoryStorage`: In-memory storage fallback for environments without localStorage
|
|
288
|
+
// Use the fetcher
|
|
289
|
+
const response = await secureFetcher.get('/api/user/profile');
|
|
290
|
+
```
|
|
195
291
|
|
|
196
|
-
##
|
|
292
|
+
## 🧪 Testing
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Run tests
|
|
296
|
+
pnpm test
|
|
297
|
+
|
|
298
|
+
# Run tests with coverage
|
|
299
|
+
pnpm test --coverage
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## 🌐 CoSec Framework
|
|
197
303
|
|
|
198
304
|
This package is designed to work with the [CoSec authentication framework](https://github.com/Ahoo-Wang/CoSec). For more
|
|
199
305
|
information about CoSec features and capabilities, please visit
|
|
200
306
|
the [CoSec GitHub repository](https://github.com/Ahoo-Wang/CoSec).
|
|
201
307
|
|
|
202
|
-
##
|
|
308
|
+
## 🤝 Contributing
|
|
309
|
+
|
|
310
|
+
Contributions are welcome! Please see
|
|
311
|
+
the [contributing guide](https://github.com/Ahoo-Wang/fetcher/blob/main/CONTRIBUTING.md) for more details.
|
|
312
|
+
|
|
313
|
+
## 📄 License
|
|
203
314
|
|
|
204
315
|
Apache-2.0
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
<p align="center">
|
|
320
|
+
Part of the <a href="https://github.com/Ahoo-Wang/fetcher">Fetcher</a> ecosystem
|
|
321
|
+
</p>
|
package/README.zh-CN.md
CHANGED
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
# @ahoo-wang/fetcher-cosec
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@ahoo-wang/fetcher-cosec)
|
|
4
|
+
[](https://github.com/Ahoo-Wang/fetcher/actions)
|
|
5
|
+
[](https://codecov.io/gh/Ahoo-Wang/fetcher)
|
|
6
|
+
[](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/@ahoo-wang/fetcher-cosec)
|
|
8
|
+
|
|
3
9
|
Fetcher HTTP 客户端的 CoSec 认证支持。
|
|
4
10
|
|
|
5
11
|
[CoSec](https://github.com/Ahoo-Wang/CoSec) 是一个全面的身份认证和授权框架。
|
|
6
12
|
|
|
7
13
|
此包提供了 Fetcher HTTP 客户端与 CoSec 认证框架之间的集成。
|
|
8
14
|
|
|
9
|
-
## 功能特性
|
|
15
|
+
## 🌟 功能特性
|
|
16
|
+
|
|
17
|
+
- **🔐 自动认证**:自动添加 CoSec 认证头
|
|
18
|
+
- **📱 设备管理**:设备 ID 管理与 localStorage 持久化
|
|
19
|
+
- **🔄 令牌刷新**:基于响应码(401)的自动令牌刷新
|
|
20
|
+
- **追踪 请求跟踪**:请求 ID 生成用于跟踪
|
|
21
|
+
- **💾 令牌存储**:安全的令牌存储管理
|
|
22
|
+
- **🛡️ TypeScript 支持**:完整的 TypeScript 类型定义
|
|
10
23
|
|
|
11
|
-
|
|
12
|
-
- 设备 ID 管理与 localStorage 持久化
|
|
13
|
-
- 基于响应码(401)的自动令牌刷新
|
|
14
|
-
- 请求 ID 生成用于跟踪
|
|
15
|
-
- 令牌存储管理
|
|
24
|
+
## 🚀 快速开始
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
### 安装
|
|
18
27
|
|
|
19
28
|
```bash
|
|
29
|
+
# 使用 npm
|
|
20
30
|
npm install @ahoo-wang/fetcher-cosec
|
|
21
|
-
```
|
|
22
31
|
|
|
23
|
-
|
|
32
|
+
# 使用 pnpm
|
|
33
|
+
pnpm add @ahoo-wang/fetcher-cosec
|
|
34
|
+
|
|
35
|
+
# 使用 yarn
|
|
36
|
+
yarn add @ahoo-wang/fetcher-cosec
|
|
37
|
+
```
|
|
24
38
|
|
|
25
39
|
### 基本设置
|
|
26
40
|
|
|
@@ -85,7 +99,9 @@ fetcher.interceptors.response.use(
|
|
|
85
99
|
);
|
|
86
100
|
```
|
|
87
101
|
|
|
88
|
-
|
|
102
|
+
## 🔧 配置
|
|
103
|
+
|
|
104
|
+
### CoSecOptions 接口
|
|
89
105
|
|
|
90
106
|
```typescript
|
|
91
107
|
interface CoSecOptions {
|
|
@@ -120,17 +136,37 @@ interface CoSecOptions {
|
|
|
120
136
|
3. `Authorization`: Bearer 令牌
|
|
121
137
|
4. `CoSec-Request-Id`: 每个请求的唯一请求标识符
|
|
122
138
|
|
|
123
|
-
|
|
139
|
+
## 📚 API 参考
|
|
124
140
|
|
|
125
|
-
|
|
141
|
+
### 核心类
|
|
126
142
|
|
|
127
|
-
|
|
143
|
+
#### CoSecRequestInterceptor
|
|
128
144
|
|
|
129
|
-
|
|
145
|
+
向传出请求添加 CoSec 认证头部。
|
|
130
146
|
|
|
131
147
|
```typescript
|
|
132
|
-
|
|
148
|
+
new CoSecRequestInterceptor(options
|
|
149
|
+
:
|
|
150
|
+
CoSecOptions
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### CoSecResponseInterceptor
|
|
133
155
|
|
|
156
|
+
在服务器返回状态码 401 时处理令牌刷新。
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
new CoSecResponseInterceptor(options
|
|
160
|
+
:
|
|
161
|
+
CoSecOptions
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### TokenStorage
|
|
166
|
+
|
|
167
|
+
管理 localStorage 中的令牌存储。
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
134
170
|
const tokenStorage = new TokenStorage();
|
|
135
171
|
|
|
136
172
|
// 存储令牌
|
|
@@ -141,22 +177,16 @@ tokenStorage.set({
|
|
|
141
177
|
|
|
142
178
|
// 获取令牌
|
|
143
179
|
const token = tokenStorage.get();
|
|
144
|
-
if (token) {
|
|
145
|
-
console.log('访问令牌:', token.accessToken);
|
|
146
|
-
console.log('刷新令牌:', token.refreshToken);
|
|
147
|
-
}
|
|
148
180
|
|
|
149
181
|
// 清除令牌
|
|
150
182
|
tokenStorage.clear();
|
|
151
183
|
```
|
|
152
184
|
|
|
153
|
-
|
|
185
|
+
#### DeviceIdStorage
|
|
154
186
|
|
|
155
|
-
|
|
187
|
+
管理 localStorage 中的设备 ID 存储。
|
|
156
188
|
|
|
157
189
|
```typescript
|
|
158
|
-
import { DeviceIdStorage } from '@ahoo-wang/fetcher-cosec';
|
|
159
|
-
|
|
160
190
|
const deviceIdStorage = new DeviceIdStorage();
|
|
161
191
|
|
|
162
192
|
// 获取或创建设备 ID
|
|
@@ -175,7 +205,13 @@ deviceIdStorage.clear();
|
|
|
175
205
|
const newDeviceId = deviceIdStorage.generateDeviceId();
|
|
176
206
|
```
|
|
177
207
|
|
|
178
|
-
|
|
208
|
+
#### InMemoryStorage
|
|
209
|
+
|
|
210
|
+
无 localStorage 环境的内存存储后备。
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
const inMemoryStorage = new InMemoryStorage();
|
|
214
|
+
```
|
|
179
215
|
|
|
180
216
|
### 接口
|
|
181
217
|
|
|
@@ -184,19 +220,100 @@ const newDeviceId = deviceIdStorage.generateDeviceId();
|
|
|
184
220
|
- `CompositeToken`: 包含访问和刷新令牌
|
|
185
221
|
- `TokenRefresher`: 提供刷新令牌的方法
|
|
186
222
|
|
|
187
|
-
|
|
223
|
+
## 🛠️ 示例
|
|
224
|
+
|
|
225
|
+
### 完整认证设置
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { Fetcher } from '@ahoo-wang/fetcher';
|
|
229
|
+
import {
|
|
230
|
+
CoSecRequestInterceptor,
|
|
231
|
+
CoSecResponseInterceptor,
|
|
232
|
+
DeviceIdStorage,
|
|
233
|
+
TokenStorage,
|
|
234
|
+
} from '@ahoo-wang/fetcher-cosec';
|
|
235
|
+
|
|
236
|
+
// 创建存储实例
|
|
237
|
+
const deviceIdStorage = new DeviceIdStorage();
|
|
238
|
+
const tokenStorage = new TokenStorage();
|
|
239
|
+
|
|
240
|
+
// 创建令牌刷新器
|
|
241
|
+
const tokenRefresher = {
|
|
242
|
+
async refresh(token) {
|
|
243
|
+
const response = await fetch('/api/auth/refresh', {
|
|
244
|
+
method: 'POST',
|
|
245
|
+
headers: {
|
|
246
|
+
'Content-Type': 'application/json',
|
|
247
|
+
},
|
|
248
|
+
body: JSON.stringify({
|
|
249
|
+
refreshToken: token.refreshToken,
|
|
250
|
+
}),
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
if (!response.ok) {
|
|
254
|
+
throw new Error('令牌刷新失败');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const tokens = await response.json();
|
|
258
|
+
return {
|
|
259
|
+
accessToken: tokens.accessToken,
|
|
260
|
+
refreshToken: tokens.refreshToken,
|
|
261
|
+
};
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// 创建带 CoSec 拦截器的 fetcher
|
|
266
|
+
const secureFetcher = new Fetcher({
|
|
267
|
+
baseURL: 'https://api.example.com',
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
secureFetcher.interceptors.request.use(
|
|
271
|
+
new CoSecRequestInterceptor({
|
|
272
|
+
appId: 'my-app-id',
|
|
273
|
+
deviceIdStorage,
|
|
274
|
+
tokenStorage,
|
|
275
|
+
tokenRefresher,
|
|
276
|
+
}),
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
secureFetcher.interceptors.response.use(
|
|
280
|
+
new CoSecResponseInterceptor({
|
|
281
|
+
appId: 'my-app-id',
|
|
282
|
+
deviceIdStorage,
|
|
283
|
+
tokenStorage,
|
|
284
|
+
tokenRefresher,
|
|
285
|
+
}),
|
|
286
|
+
);
|
|
188
287
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
- `CoSecResponseInterceptor`: 处理 401 响应的令牌刷新
|
|
193
|
-
- `InMemoryStorage`: 无 localStorage 环境的内存存储后备
|
|
288
|
+
// 使用 fetcher
|
|
289
|
+
const response = await secureFetcher.get('/api/user/profile');
|
|
290
|
+
```
|
|
194
291
|
|
|
195
|
-
##
|
|
292
|
+
## 🧪 测试
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# 运行测试
|
|
296
|
+
pnpm test
|
|
297
|
+
|
|
298
|
+
# 运行带覆盖率的测试
|
|
299
|
+
pnpm test --coverage
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## 🌐 CoSec 框架
|
|
196
303
|
|
|
197
304
|
此包设计用于与 [CoSec 认证框架](https://github.com/Ahoo-Wang/CoSec) 配合使用。有关 CoSec
|
|
198
305
|
功能和特性的更多信息,请访问 [CoSec GitHub 仓库](https://github.com/Ahoo-Wang/CoSec)。
|
|
199
306
|
|
|
200
|
-
##
|
|
307
|
+
## 🤝 贡献
|
|
308
|
+
|
|
309
|
+
欢迎贡献!请查看 [贡献指南](https://github.com/Ahoo-Wang/fetcher/blob/main/CONTRIBUTING.md) 了解更多详情。
|
|
310
|
+
|
|
311
|
+
## 📄 许可证
|
|
201
312
|
|
|
202
313
|
Apache-2.0
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
<p align="center">
|
|
318
|
+
Fetcher 生态系统的一部分
|
|
319
|
+
</p>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ahoo-wang/fetcher-cosec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Support for CoSec authentication in Fetcher",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fetch",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"nanoid": "^5.1.5",
|
|
38
|
-
"@ahoo-wang/fetcher": "0.
|
|
38
|
+
"@ahoo-wang/fetcher": "0.5.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@vitest/coverage-v8": "^3.2.4",
|