vigor-fetch 1.0.20 โ 2.0.1
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 +395 -219
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,289 +1,465 @@
|
|
|
1
1
|
# vigor-fetch
|
|
2
2
|
|
|
3
|
-
**Vigor** is a lightweight TypeScript HTTP utility library.
|
|
4
|
-
|
|
3
|
+
**Vigor** is a lightweight (gzipped ~7.7kb) TypeScript HTTP / Retry utility library.
|
|
4
|
+
Vigor provides a fluent, chainable API for building robust network logic with built-in retry, backoff, interceptors, parsing, and concurrency control.
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
- โก **Parallel Requests** โ
|
|
14
|
-
- ๐ **
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
10
|
+
- ๐งฉ **Fluent & Immutable API** โ Fully composable, side-effect-free chaining
|
|
11
|
+
- ๐ **Advanced Retry System** โ Exponential backoff with jitter support.
|
|
12
|
+
- ๐ **Smart Fetch Layer** โ Automatic 429 handling & configurable retry rules
|
|
13
|
+
- โก **Parallel Requests** โ Concurrency-limited task runner
|
|
14
|
+
- ๐ **Smart Response Parsing** โ Auto parsing based on Content-Type
|
|
15
|
+
- โก **Zero Dependencies** โ Built on native Fetch + AbortController
|
|
16
|
+
- ๐ช **Powerful Interceptors** โ Lifecycle hooks for full control flow
|
|
17
|
+
- ๐ง **TypeScript First** โ Fully typed inference across all modules
|
|
18
|
+
|
|
19
|
+
|
|
18
20
|
---
|
|
19
21
|
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install vigor-fetch
|
|
27
|
+
```
|
|
28
|
+
|
|
20
29
|
## Why Vigor?
|
|
21
30
|
|
|
22
31
|
| Feature | Vigor | native fetch | ky | axios |
|
|
23
32
|
|---|:---:|:---:|:---:|:---:|
|
|
24
|
-
| Zero dependencies | โ
| โ
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
| Auto response parsing | โ
| โ |
|
|
33
|
+
| Zero dependencies | โ
| โ
| โ | โ
|
|
|
34
|
+
| 429 rate-limit handling | โ
| โ | โ
(manual/config-based) | โ |
|
|
35
|
+
| Retry with jitter | โ
| โ | โ
| โ |
|
|
36
|
+
| Exponential backoff | โ
| โ | โ
| โ |
|
|
37
|
+
| Auto response parsing | โ
| โ | โ
| โ
|
|
|
29
38
|
| Fluent chaining API | โ
| โ | โ
| โ |
|
|
30
|
-
| Concurrency
|
|
31
|
-
| Lifecycle interceptors | โ
| โ |
|
|
39
|
+
| Concurrency control | โ
| โ | โ | โ |
|
|
40
|
+
| Lifecycle interceptors | โ
| โ | partial | โ |
|
|
32
41
|
| Plugin system | โ
| โ | โ | โ |
|
|
33
|
-
| TypeScript-first | โ
| โ | โ
| partial |
|
|
34
42
|
|
|
35
|
-
##
|
|
43
|
+
## Quick Start
|
|
36
44
|
|
|
37
|
-
```
|
|
38
|
-
|
|
45
|
+
```ts
|
|
46
|
+
import vigor from "vigor-fetch";
|
|
47
|
+
const data = await vigor
|
|
48
|
+
.fetch("https://api.example.com")
|
|
49
|
+
.path("api", "v1", "main")
|
|
50
|
+
.request()
|
|
39
51
|
```
|
|
40
52
|
|
|
53
|
+
# ๐ ๏ธ Vigor API Reference
|
|
54
|
+
|
|
55
|
+
|
|
41
56
|
---
|
|
42
57
|
|
|
43
|
-
## Quick Start
|
|
44
58
|
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
# ๐ก vigor.fetch(origin)
|
|
60
|
+
|
|
61
|
+
vigor.fetch(origin: string)
|
|
62
|
+
|
|
63
|
+
## Chain Methods
|
|
64
|
+
|
|
65
|
+
| Method | Type | Description |
|
|
66
|
+
|--------|------|-------------|
|
|
67
|
+
| origin | (string) => VigorFetch | Set base URL |
|
|
68
|
+
| path | (...string[]) => VigorFetch | Append URL path segments |
|
|
69
|
+
| query | (object) => VigorFetch | Set query parameters |
|
|
70
|
+
| method | (VigorFetchMethods) => VigorFetch | Set HTTP method |
|
|
71
|
+
| headers | (HeadersInit) => VigorFetch | Set request headers |
|
|
72
|
+
| body | (any) => VigorFetch | Set request body |
|
|
73
|
+
| options | (object) => VigorFetch | Merge fetch options |
|
|
74
|
+
| setting | (fn: (s: VigorFetchSettings) => VigorFetchSettings) => VigorFetch | Settings pipeline |
|
|
75
|
+
| retryConfig | (fn: (r: VigorRetry) => VigorRetry) => VigorFetch | Retry engine config |
|
|
76
|
+
| parseConfig | (fn: (p: VigorParse) => VigorParse) => VigorFetch | Response parser config |
|
|
77
|
+
| interceptors | (fn: (i: VigorFetchInterceptors) => VigorFetchInterceptors) => VigorFetch | Lifecycle hooks |
|
|
78
|
+
| request | () => Promise<T> | Execute request |
|
|
47
79
|
|
|
48
|
-
// Basic GET request
|
|
49
|
-
const data = await vigor
|
|
50
|
-
.fetch('https://api.example.com')
|
|
51
|
-
.path('/users')
|
|
52
|
-
.request();
|
|
53
|
-
|
|
54
|
-
// POST request
|
|
55
|
-
const result = await vigor
|
|
56
|
-
.fetch('https://api.example.com')
|
|
57
|
-
.path('/users')
|
|
58
|
-
.body({ name: 'John', age: 30 })
|
|
59
|
-
.request();
|
|
60
|
-
```
|
|
61
80
|
|
|
62
81
|
---
|
|
63
82
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
|
71
|
-
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
|
87
|
-
|
|
88
|
-
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
83
|
+
|
|
84
|
+
## โ๏ธ fetch().setting(s => s)
|
|
85
|
+
|
|
86
|
+
| Field | Type | Description |
|
|
87
|
+
|------|------|-------------|
|
|
88
|
+
| origin | string | Base URL |
|
|
89
|
+
| path | string[] | URL segments |
|
|
90
|
+
| query | object | Query params |
|
|
91
|
+
| unretry | number[] | Non-retry status codes |
|
|
92
|
+
| retryHeaders | string[] | Retry-related headers |
|
|
93
|
+
| method | string | HTTP method |
|
|
94
|
+
| headers | object | Request headers |
|
|
95
|
+
| body | any | Request body |
|
|
96
|
+
| options | object | Fetch options |
|
|
97
|
+
| default | T | Fallback value |
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
## ๐งฉ fetch().interceptors(i => i)
|
|
104
|
+
|
|
105
|
+
| Hook | Signature | Description |
|
|
106
|
+
|------|----------|-------------|
|
|
107
|
+
| before | (ctx, { setOptions, throwError }) => void | Before request |
|
|
108
|
+
| after | (ctx, { throwError }) => void | After success |
|
|
109
|
+
| onError | (ctx, { setResult, throwError }) => void | Error handler |
|
|
110
|
+
| result | (ctx, { setResult, throwError }) => void | Final result hook |
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# ๐ vigor.retry(task)
|
|
117
|
+
|
|
118
|
+
vigor.retry(task: VigorRetryTask<T>)
|
|
119
|
+
|
|
120
|
+
## Methods
|
|
121
|
+
|
|
122
|
+
| Method | Type | Description |
|
|
123
|
+
|--------|------|-------------|
|
|
124
|
+
| target | (fn: VigorRetryTask<T>) => VigorRetry | Set retry function |
|
|
125
|
+
| setting | (fn: (s: VigorRetrySettings) => VigorRetrySettings) => VigorRetry | Retry settings |
|
|
126
|
+
| backoff | (fn: (b: VigorRetryBackoff) => VigorRetryBackoff) => VigorRetry | Backoff strategy |
|
|
127
|
+
| interceptors | (fn: (i: VigorRetryInterceptors) => VigorRetryInterceptors) => VigorRetry | Lifecycle hooks |
|
|
128
|
+
| request | () => Promise<T> | Execute retry flow |
|
|
129
|
+
| createController | () => (error: Error) => void | Abort controller |
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
## โ๏ธ retry().setting(s => s)
|
|
136
|
+
|
|
137
|
+
| Field | Type | Description |
|
|
138
|
+
|------|------|-------------|
|
|
139
|
+
| count | number | Max retry attempts |
|
|
140
|
+
| limit | number | Timeout per attempt |
|
|
141
|
+
| maxDelay | number | Max delay cap |
|
|
142
|
+
| default | T | Fallback value |
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
## ๐ retry().backoff(b => b)
|
|
149
|
+
|
|
150
|
+
| Field | Type | Description |
|
|
151
|
+
|------|------|-------------|
|
|
152
|
+
| initialDelay | number | Initial delay |
|
|
153
|
+
| baseDelay | number | Base delay |
|
|
154
|
+
| factor | number | Exponential multiplier |
|
|
155
|
+
| jitter | number | Random noise |
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
## ๐งฉ retry().interceptors(i => i)
|
|
162
|
+
|
|
163
|
+
| Hook | Signature | Description |
|
|
164
|
+
|------|----------|-------------|
|
|
165
|
+
| before | (ctx, { setAttempt, throwError, abort }) => void | Before execution |
|
|
166
|
+
| after | (ctx, { setAttempt, setResult, throwError }) => void | After success |
|
|
167
|
+
| onError | (ctx, { setResult, throwError }) => void | Error handling |
|
|
168
|
+
| onRetry | (ctx, { setDelay }) => void | Retry event |
|
|
169
|
+
| retryIf | (ctx, { proceedRetry, cancelRetry }) => void | Retry decision |
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# โก vigor.all(tasks)
|
|
176
|
+
|
|
177
|
+
vigor.all(tasks: VigorAllTask<T>[])
|
|
178
|
+
|
|
179
|
+
## Methods
|
|
180
|
+
|
|
181
|
+
| Method | Type | Description |
|
|
182
|
+
|--------|------|-------------|
|
|
183
|
+
| target | (...tasks) => VigorAll | Set tasks |
|
|
184
|
+
| setting | (fn: (s: VigorAllSettings) => VigorAllSettings) => VigorAll | Concurrency config |
|
|
185
|
+
| interceptors | (fn: (i: VigorAllInterceptors) => VigorAllInterceptors) => VigorAll | Hooks |
|
|
186
|
+
| request | () => Promise<Array<T | Error>> | Execute all tasks |
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
## โ๏ธ all().setting(s => s)
|
|
193
|
+
|
|
194
|
+
| Field | Type | Description |
|
|
195
|
+
|------|------|-------------|
|
|
196
|
+
| concurrency | number | Max parallel tasks |
|
|
197
|
+
| jitter | number | Delay randomness |
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
## ๐งฉ all().interceptors(i => i)
|
|
204
|
+
|
|
205
|
+
| Hook | Signature | Description |
|
|
206
|
+
|------|----------|-------------|
|
|
207
|
+
| before | (ctx) => void | Before each task |
|
|
208
|
+
| after | (ctx, { setResult }) => void | After success |
|
|
209
|
+
| onError | (ctx, { setResult }) => void | Error handling |
|
|
210
|
+
| result | (ctx, { setResult }) => void | Final aggregation |
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# ๐งช vigor.parse(response)
|
|
217
|
+
|
|
218
|
+
vigor.parse(response: Response)
|
|
219
|
+
|
|
220
|
+
| Method | Type | Description |
|
|
221
|
+
|--------|------|-------------|
|
|
222
|
+
| target | Response | Set response |
|
|
223
|
+
| original | boolean | Return raw response |
|
|
224
|
+
| type | keyof Response | Force parse type |
|
|
225
|
+
| request | () => Promise<T> | Execute parsing |
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
# ๐ vigor.fetch examples
|
|
232
|
+
|
|
233
|
+
## GET request
|
|
234
|
+
```ts
|
|
235
|
+
vigor.fetch("https://api.example.com")
|
|
236
|
+
.path("users", "profile")
|
|
237
|
+
.query({ id: 123 })
|
|
238
|
+
.method("GET")
|
|
239
|
+
.request()
|
|
240
|
+
```
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## POST request
|
|
244
|
+
```ts
|
|
245
|
+
vigor.fetch("https://api.example.com")
|
|
246
|
+
.path("users")
|
|
247
|
+
.method("POST")
|
|
248
|
+
.headers({
|
|
249
|
+
Authorization: "Bearer TOKEN"
|
|
101
250
|
})
|
|
102
|
-
.
|
|
103
|
-
|
|
251
|
+
.body({
|
|
252
|
+
name: "John",
|
|
253
|
+
age: 30
|
|
104
254
|
})
|
|
105
|
-
.request()
|
|
255
|
+
.request()
|
|
256
|
+
```
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## fetch + retry + backoff + parse
|
|
260
|
+
```ts
|
|
261
|
+
vigor.fetch("https://api.example.com")
|
|
262
|
+
.path("data")
|
|
263
|
+
.retryConfig(r =>
|
|
264
|
+
r
|
|
265
|
+
.setting(s =>
|
|
266
|
+
s
|
|
267
|
+
.count(3)
|
|
268
|
+
.limit(5000)
|
|
269
|
+
)
|
|
270
|
+
.backoff(b =>
|
|
271
|
+
b
|
|
272
|
+
.factor(2)
|
|
273
|
+
.jitter(300)
|
|
274
|
+
)
|
|
275
|
+
)
|
|
276
|
+
.parseConfig(p =>
|
|
277
|
+
p.original(false)
|
|
278
|
+
)
|
|
279
|
+
.request()
|
|
280
|
+
```
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
# ๐ vigor.retry examples
|
|
284
|
+
|
|
285
|
+
## basic retry
|
|
286
|
+
```ts
|
|
287
|
+
vigor.retry(async (ctx, { signal }) => {
|
|
288
|
+
const res = await fetch("https://api.example.com/data", { signal })
|
|
289
|
+
if (!res.ok) throw new Error("failed")
|
|
290
|
+
return res.json()
|
|
291
|
+
})
|
|
292
|
+
.setting(s =>
|
|
293
|
+
s
|
|
294
|
+
.count(5)
|
|
295
|
+
.limit(3000)
|
|
296
|
+
)
|
|
297
|
+
.backoff(b =>
|
|
298
|
+
b
|
|
299
|
+
.baseDelay(500)
|
|
300
|
+
.factor(2)
|
|
301
|
+
)
|
|
302
|
+
.request()
|
|
106
303
|
```
|
|
107
304
|
|
|
305
|
+
|
|
108
306
|
---
|
|
109
307
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
| `.onRetry(...fn)` | Interceptor called when a retry is triggered |
|
|
125
|
-
| `.onError(...fn)` | Interceptor called on final failure |
|
|
126
|
-
| `.request()` | Execute |
|
|
127
|
-
|
|
128
|
-
**Example**
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
const result = await vigor
|
|
132
|
-
.retry(async () => {
|
|
133
|
-
const res = await fetch('https://api.example.com/unstable');
|
|
134
|
-
if (!res.ok) throw new Error('Failed');
|
|
135
|
-
return res.json();
|
|
136
|
-
})
|
|
137
|
-
.count(5)
|
|
138
|
-
.baseDelay(1000)
|
|
139
|
-
.backoff(1.5)
|
|
140
|
-
.jitter(300)
|
|
141
|
-
.onRetry(async (ctx) => {
|
|
142
|
-
console.log(`Retry #${ctx.attempt}, waiting ${ctx.wait}ms`);
|
|
308
|
+
|
|
309
|
+
## retryIf control
|
|
310
|
+
```ts
|
|
311
|
+
vigor.retry(async () => {
|
|
312
|
+
const res = await fetch("https://api.example.com")
|
|
313
|
+
return res.json()
|
|
314
|
+
})
|
|
315
|
+
.interceptors(i =>
|
|
316
|
+
i.retryIf((ctx, { cancelRetry }) => {
|
|
317
|
+
const result = ctx.runtime.result
|
|
318
|
+
|
|
319
|
+
if (result?.error === "fatal") {
|
|
320
|
+
cancelRetry()
|
|
321
|
+
}
|
|
143
322
|
})
|
|
144
|
-
|
|
323
|
+
)
|
|
324
|
+
.request()
|
|
145
325
|
```
|
|
146
326
|
|
|
327
|
+
|
|
147
328
|
---
|
|
148
329
|
|
|
149
|
-
### `vigor.parse(response?)` โ VigorParse
|
|
150
330
|
|
|
151
|
-
|
|
331
|
+
## abort controller
|
|
332
|
+
```ts
|
|
333
|
+
const retry = vigor.retry(async (ctx, { signal }) => {
|
|
334
|
+
const res = await fetch("https://api.example.com", { signal })
|
|
335
|
+
return res.json()
|
|
336
|
+
})
|
|
152
337
|
|
|
153
|
-
|
|
154
|
-
|---|---|
|
|
155
|
-
| `application/json` | `response.json()` |
|
|
156
|
-
| `multipart/form-data` | `response.formData()` |
|
|
157
|
-
| `application/octet-stream` | `response.arrayBuffer()` |
|
|
158
|
-
| `image/*`, `video/*`, `audio/*`, `pdf` | `response.blob()` |
|
|
159
|
-
| anything else | `response.text()` |
|
|
338
|
+
const abort = retry.createController()
|
|
160
339
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
| `.type(str)` | Force a specific parsing method: `'json'`, `'text'`, `'blob'`, etc. |
|
|
165
|
-
| `.before(...fn)` | Interceptor called before parsing |
|
|
166
|
-
| `.after(...fn)` | Interceptor called after parsing |
|
|
167
|
-
| `.onError(...fn)` | Interceptor called on error |
|
|
168
|
-
| `.request()` | Execute parsing |
|
|
340
|
+
setTimeout(() => {
|
|
341
|
+
abort(new Error("manual abort"))
|
|
342
|
+
}, 2000)
|
|
169
343
|
|
|
170
|
-
|
|
344
|
+
await retry.request()
|
|
345
|
+
```
|
|
171
346
|
|
|
172
|
-
```typescript
|
|
173
|
-
const raw = await fetch('https://api.example.com/data');
|
|
174
347
|
|
|
175
|
-
|
|
176
|
-
const parsed = await vigor.parse(raw).request();
|
|
348
|
+
---
|
|
177
349
|
|
|
178
|
-
// Force text parsing
|
|
179
|
-
const text = await vigor.parse(raw).type('text').request();
|
|
180
350
|
|
|
181
|
-
|
|
182
|
-
|
|
351
|
+
# โก vigor.all examples
|
|
352
|
+
```ts
|
|
353
|
+
vigor.all([
|
|
354
|
+
async () => fetch("https://api.com/a").then(r => r.json()),
|
|
355
|
+
async () => fetch("https://api.com/b").then(r => r.json()),
|
|
356
|
+
async () => fetch("https://api.com/c").then(r => r.json())
|
|
357
|
+
]).request()
|
|
183
358
|
```
|
|
184
359
|
|
|
360
|
+
|
|
185
361
|
---
|
|
186
362
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
**Example**
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
const tasks = [1, 2, 3, 4, 5].map(id =>
|
|
205
|
-
() => vigor.fetch('https://api.example.com').path(`/items/${id}`).request()
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
const results = await vigor
|
|
209
|
-
.all()
|
|
210
|
-
.promises(...tasks)
|
|
211
|
-
.limit(3) // Run at most 3 tasks concurrently
|
|
212
|
-
.jitter(200) // Add 0โ200ms random delay before each task starts
|
|
213
|
-
.request();
|
|
214
|
-
|
|
215
|
-
results.forEach((res, i) => {
|
|
216
|
-
if (res instanceof VigorAllError) {
|
|
217
|
-
console.error(`Task ${i} failed:`, res.message);
|
|
218
|
-
} else {
|
|
219
|
-
console.log(`Task ${i} succeeded:`, res);
|
|
220
|
-
}
|
|
221
|
-
});
|
|
363
|
+
|
|
364
|
+
```ts
|
|
365
|
+
vigor.all([
|
|
366
|
+
async () => "A",
|
|
367
|
+
async () => "B",
|
|
368
|
+
async () => "C",
|
|
369
|
+
async () => "D"
|
|
370
|
+
])
|
|
371
|
+
.setting(s =>
|
|
372
|
+
s
|
|
373
|
+
.concurrency(2)
|
|
374
|
+
.jitter(500)
|
|
375
|
+
)
|
|
376
|
+
.request()
|
|
222
377
|
```
|
|
223
378
|
|
|
379
|
+
|
|
224
380
|
---
|
|
225
381
|
|
|
226
|
-
## Interceptor Context (`ctx`)
|
|
227
382
|
|
|
228
|
-
|
|
229
|
-
|
|
383
|
+
```ts
|
|
384
|
+
vigor.all([
|
|
385
|
+
async () => "ok1",
|
|
386
|
+
async () => { throw new Error("fail") },
|
|
387
|
+
async () => "ok2"
|
|
388
|
+
]).request()
|
|
389
|
+
```
|
|
230
390
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
// ctx.requestId === 'abc-123'
|
|
240
|
-
// ctx.result: current response object
|
|
241
|
-
})
|
|
242
|
-
.request();
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
# ๐งช vigor.parse examples
|
|
395
|
+
```ts
|
|
396
|
+
const res = await fetch("https://api.com/data")
|
|
397
|
+
|
|
398
|
+
vigor.parse(res).request()
|
|
243
399
|
```
|
|
244
400
|
|
|
401
|
+
|
|
245
402
|
---
|
|
246
403
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
| `VigorParseError` | Error thrown during parsing |
|
|
255
|
-
| `VigorAllError` | Error thrown during parallel execution |
|
|
256
|
-
|
|
257
|
-
All errors share the following shape:
|
|
258
|
-
|
|
259
|
-
```typescript
|
|
260
|
-
interface VigorErrorOptions {
|
|
261
|
-
type?: string; // Error category
|
|
262
|
-
data?: any; // Related data
|
|
263
|
-
status?: number; // HTTP status code
|
|
264
|
-
response?: any; // Original response
|
|
265
|
-
message?: string; // Custom message
|
|
266
|
-
origin?: string; // Request origin
|
|
267
|
-
}
|
|
404
|
+
|
|
405
|
+
```ts
|
|
406
|
+
const img = await fetch("https://api.com/image.png")
|
|
407
|
+
|
|
408
|
+
vigor.parse(img)
|
|
409
|
+
.type("blob")
|
|
410
|
+
.request()
|
|
268
411
|
```
|
|
269
412
|
|
|
413
|
+
|
|
270
414
|
---
|
|
271
415
|
|
|
272
|
-
## Plugins
|
|
273
416
|
|
|
274
|
-
|
|
417
|
+
```ts
|
|
418
|
+
const raw = await fetch("https://api.com")
|
|
275
419
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
original(origin, config).headers({ Authorization: `Bearer ${options.token}` });
|
|
281
|
-
};
|
|
420
|
+
vigor.parse(raw)
|
|
421
|
+
.original(true)
|
|
422
|
+
.request()
|
|
423
|
+
```
|
|
282
424
|
|
|
283
|
-
vigor.use(authPlugin, { token: 'MY_TOKEN' });
|
|
284
425
|
|
|
285
|
-
|
|
286
|
-
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
# ๐ฅ full pipeline example
|
|
430
|
+
```ts
|
|
431
|
+
vigor.fetch("https://api.example.com")
|
|
432
|
+
.path("users")
|
|
433
|
+
.query({ page: 1 })
|
|
434
|
+
.method("GET")
|
|
435
|
+
.retryConfig(r =>
|
|
436
|
+
r
|
|
437
|
+
.setting(s =>
|
|
438
|
+
s
|
|
439
|
+
.count(3)
|
|
440
|
+
.limit(5000)
|
|
441
|
+
)
|
|
442
|
+
.backoff(b =>
|
|
443
|
+
b
|
|
444
|
+
.factor(2)
|
|
445
|
+
.jitter(200)
|
|
446
|
+
)
|
|
447
|
+
.interceptors(i =>
|
|
448
|
+
i.onRetry((ctx, { setDelay }) => {
|
|
449
|
+
setDelay(1000)
|
|
450
|
+
})
|
|
451
|
+
)
|
|
452
|
+
)
|
|
453
|
+
.parseConfig(p =>
|
|
454
|
+
p.original(false)
|
|
455
|
+
)
|
|
456
|
+
.interceptors(i =>
|
|
457
|
+
i.result(() => {
|
|
458
|
+
console.log("done")
|
|
459
|
+
})
|
|
460
|
+
)
|
|
461
|
+
.request()
|
|
287
462
|
```
|
|
288
463
|
|
|
464
|
+
|
|
289
465
|
---
|
package/package.json
CHANGED