vigor-fetch 2.0.6 → 2.1.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 +1 -1
- package/dist/index.d.ts +179 -183
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +169 -223
- package/dist/index.mjs +169 -223
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
class VigorError extends Error {
|
|
6
|
-
timestamp;
|
|
6
|
+
timestamp = new Date();
|
|
7
7
|
method;
|
|
8
8
|
cause;
|
|
9
9
|
context;
|
|
@@ -12,15 +12,10 @@ class VigorError extends Error {
|
|
|
12
12
|
constructor(message, options) {
|
|
13
13
|
super(message, { cause: options?.cause });
|
|
14
14
|
this.name = new.target.name;
|
|
15
|
-
this.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.context = options.context;
|
|
20
|
-
if (options?.type !== undefined)
|
|
21
|
-
this.type = options.type;
|
|
22
|
-
if (options?.data !== undefined)
|
|
23
|
-
this.data = options.data;
|
|
15
|
+
this.method = options?.method;
|
|
16
|
+
this.context = options?.context;
|
|
17
|
+
this.type = options?.type;
|
|
18
|
+
this.data = options?.data;
|
|
24
19
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
25
20
|
Error.captureStackTrace?.(this, new.target);
|
|
26
21
|
}
|
|
@@ -46,114 +41,87 @@ class VigorAllError extends VigorError {
|
|
|
46
41
|
}
|
|
47
42
|
}
|
|
48
43
|
class VigorStatus {
|
|
44
|
+
_base;
|
|
49
45
|
_config;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this._ctor = _ctor;
|
|
55
|
-
this._errorCtor = _errorCtor;
|
|
56
|
-
}
|
|
57
|
-
_create(config) { return this._ctor(config); }
|
|
58
|
-
_next(config) { return this._create({ ...this._config, ...config }); }
|
|
46
|
+
constructor(config, _base) {
|
|
47
|
+
this._base = _base;
|
|
48
|
+
this._config = { ...this._base, ...config };
|
|
49
|
+
}
|
|
59
50
|
getConfig() { return this._config; }
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
method: errorKey,
|
|
65
|
-
type: "invalid_input",
|
|
66
|
-
data: { expected: "function", received: fn }
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
return fn(new Ctor(value)).getConfig();
|
|
51
|
+
getBase() { return this._base; }
|
|
52
|
+
_next(config) { return new this.constructor({ ...this._config, ...config }, this._base); }
|
|
53
|
+
_pipsub(config, fn, ctor) {
|
|
54
|
+
return fn(new ctor(config)).getConfig();
|
|
70
55
|
}
|
|
71
56
|
}
|
|
72
57
|
class VigorRetrySettings extends VigorStatus {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const base = {
|
|
58
|
+
constructor(config = {}) {
|
|
59
|
+
super(config, {
|
|
76
60
|
count: 5,
|
|
77
61
|
limit: 10000,
|
|
78
62
|
maxDelay: 10000,
|
|
79
|
-
};
|
|
80
|
-
super({ ...base, ...config }, (c) => new VigorRetrySettings(c));
|
|
81
|
-
this._base = base;
|
|
63
|
+
});
|
|
82
64
|
}
|
|
83
|
-
getBase() { return this._base; }
|
|
84
65
|
count(num) { return this._next({ count: num }); }
|
|
85
66
|
limit(num) { return this._next({ limit: num }); }
|
|
86
67
|
maxDelay(num) { return this._next({ maxDelay: num }); }
|
|
87
68
|
default(obj) { return this._next({ default: obj }); }
|
|
88
69
|
}
|
|
89
70
|
class VigorRetryBackoff extends VigorStatus {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const base = {
|
|
71
|
+
constructor(config = {}) {
|
|
72
|
+
super(config, {
|
|
93
73
|
initialDelay: 0,
|
|
94
74
|
baseDelay: 1000,
|
|
95
75
|
factor: 1.7,
|
|
96
76
|
jitter: 1000
|
|
97
|
-
};
|
|
98
|
-
super({ ...base, ...config }, (c) => new VigorRetryBackoff(c));
|
|
99
|
-
this._base = base;
|
|
77
|
+
});
|
|
100
78
|
}
|
|
101
|
-
getBase() { return this._base; }
|
|
102
79
|
initialDelay(num) { return this._next({ initialDelay: num }); }
|
|
103
80
|
baseDelay(num) { return this._next({ baseDelay: num }); }
|
|
104
81
|
factor(num) { return this._next({ factor: num }); }
|
|
105
82
|
jitter(num) { return this._next({ jitter: num }); }
|
|
83
|
+
static randomJitter(num) { return Math.random() * num; }
|
|
106
84
|
}
|
|
107
85
|
class VigorRetryInterceptors extends VigorStatus {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const base = {
|
|
86
|
+
constructor(config = {}) {
|
|
87
|
+
super(config, {
|
|
111
88
|
before: [],
|
|
112
89
|
after: [],
|
|
113
90
|
onError: [],
|
|
114
91
|
onRetry: [],
|
|
115
92
|
retryIf: []
|
|
116
|
-
};
|
|
117
|
-
super({ ...base, ...config }, (c) => new VigorRetryInterceptors(c));
|
|
118
|
-
this._base = base;
|
|
93
|
+
});
|
|
119
94
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
retryIf(...funcs) { return this._next({ retryIf: [...this.getConfig().retryIf, ...funcs.flat()] }); }
|
|
95
|
+
before(...funcs) { return this._next({ ...this._config, before: [...this._config.before, ...funcs.flat()] }); }
|
|
96
|
+
after(...funcs) { return this._next({ ...this._config, after: [...this._config.after, ...funcs.flat()] }); }
|
|
97
|
+
onError(...funcs) { return this._next({ ...this._config, onError: [...this._config.onError, ...funcs.flat()] }); }
|
|
98
|
+
onRetry(...funcs) { return this._next({ ...this._config, onRetry: [...this._config.onRetry, ...funcs.flat()] }); }
|
|
99
|
+
retryIf(...funcs) { return this._next({ ...this._config, retryIf: [...this._config.retryIf, ...funcs.flat()] }); }
|
|
126
100
|
}
|
|
127
101
|
class VigorRetry extends VigorStatus {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
constructor(config) {
|
|
131
|
-
const base = {
|
|
102
|
+
constructor(config = {}) {
|
|
103
|
+
super(config, {
|
|
132
104
|
target: null,
|
|
133
105
|
setting: new VigorRetrySettings().getBase(),
|
|
134
106
|
backoff: new VigorRetryBackoff().getBase(),
|
|
135
|
-
interceptors: new VigorRetryInterceptors().getBase()
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
this._base = base;
|
|
107
|
+
interceptors: new VigorRetryInterceptors().getBase(),
|
|
108
|
+
controller: config.controller || new AbortController()
|
|
109
|
+
});
|
|
139
110
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
111
|
+
_transfer(config) { return new VigorRetry({ ...this._config, ...config }); }
|
|
112
|
+
_calculateDelay(initialDelay, baseDelay, factor, attempt, jitter, maxDelay) {
|
|
113
|
+
return Math.max(0, Math.min(maxDelay, initialDelay + baseDelay * Math.pow(factor, attempt) + VigorRetryBackoff.randomJitter(jitter)));
|
|
114
|
+
}
|
|
115
|
+
createController() { return this._config.controller = new AbortController(); }
|
|
116
|
+
target(func) { return this._transfer({ target: func }); }
|
|
143
117
|
setting(func) {
|
|
144
|
-
return this._next({
|
|
145
|
-
setting: this._pipeSub(this._config.setting, VigorRetrySettings, func, "setting")
|
|
146
|
-
});
|
|
118
|
+
return this._next({ setting: this._pipsub(this._config.setting, func, VigorRetrySettings) });
|
|
147
119
|
}
|
|
148
120
|
backoff(func) {
|
|
149
|
-
return this._next({
|
|
150
|
-
backoff: this._pipeSub(this._config.backoff, VigorRetryBackoff, func, "backoff")
|
|
151
|
-
});
|
|
121
|
+
return this._next({ backoff: this._pipsub(this._config.backoff, func, VigorRetryBackoff) });
|
|
152
122
|
}
|
|
153
123
|
interceptors(func) {
|
|
154
|
-
return this._next({
|
|
155
|
-
interceptors: this._pipeSub(this._config.interceptors, VigorRetryInterceptors, func, "interceptors")
|
|
156
|
-
});
|
|
124
|
+
return this._next({ interceptors: this._pipsub(this._config.interceptors, func, VigorRetryInterceptors) });
|
|
157
125
|
}
|
|
158
126
|
async request() {
|
|
159
127
|
const config = this._config;
|
|
@@ -168,6 +136,7 @@ class VigorRetry extends VigorStatus {
|
|
|
168
136
|
retryIf: [...config.interceptors.retryIf],
|
|
169
137
|
},
|
|
170
138
|
backoff: { ...config.backoff },
|
|
139
|
+
controller: config.controller,
|
|
171
140
|
runtime: {
|
|
172
141
|
result: null,
|
|
173
142
|
controller: null,
|
|
@@ -187,7 +156,6 @@ class VigorRetry extends VigorStatus {
|
|
|
187
156
|
};
|
|
188
157
|
try {
|
|
189
158
|
while (ctx.runtime.attempt < ctx.setting.count) {
|
|
190
|
-
ctx.runtime.attempt++;
|
|
191
159
|
ctx.runtime.controller = new AbortController();
|
|
192
160
|
let listener;
|
|
193
161
|
let timerId;
|
|
@@ -197,7 +165,7 @@ class VigorRetry extends VigorStatus {
|
|
|
197
165
|
} };
|
|
198
166
|
try {
|
|
199
167
|
ctx.runtime.signal = AbortSignal.any([
|
|
200
|
-
|
|
168
|
+
ctx.controller.signal,
|
|
201
169
|
ctx.runtime.controller.signal
|
|
202
170
|
]);
|
|
203
171
|
ctx.runtime.abortPromise = new Promise((_, reject) => {
|
|
@@ -211,7 +179,11 @@ class VigorRetry extends VigorStatus {
|
|
|
211
179
|
timerId = setTimeout(() => {
|
|
212
180
|
if (ctx.runtime.aborted)
|
|
213
181
|
return;
|
|
214
|
-
abort(new VigorRetryError(`timeouted after ${ctx.setting.limit}`, {
|
|
182
|
+
abort(new VigorRetryError(`timeouted after ${ctx.setting.limit}`, {
|
|
183
|
+
method: "request", type: "timeout", data: {
|
|
184
|
+
limit: ctx.setting.limit, attempt: ctx.runtime.attempt
|
|
185
|
+
}
|
|
186
|
+
}));
|
|
215
187
|
}, ctx.setting.limit);
|
|
216
188
|
});
|
|
217
189
|
for (const func of ctx.interceptors.before) {
|
|
@@ -244,7 +216,8 @@ class VigorRetry extends VigorStatus {
|
|
|
244
216
|
if (!ctx.runtime.retry) {
|
|
245
217
|
throw ctx.runtime.error;
|
|
246
218
|
}
|
|
247
|
-
|
|
219
|
+
const { initialDelay, baseDelay, factor, jitter } = ctx.backoff;
|
|
220
|
+
ctx.runtime.delay = this._calculateDelay(initialDelay, baseDelay, factor, ctx.runtime.attempt, jitter, ctx.setting.maxDelay);
|
|
248
221
|
const setDelay = (delay) => ctx.runtime.delay = delay;
|
|
249
222
|
for (const func of ctx.interceptors.onRetry) {
|
|
250
223
|
await func(ctx, { setAttempt, throwError, setDelay });
|
|
@@ -253,11 +226,11 @@ class VigorRetry extends VigorStatus {
|
|
|
253
226
|
const timer = setTimeout(resolve, ctx.runtime.delay);
|
|
254
227
|
const abortHandler = () => {
|
|
255
228
|
clearTimeout(timer);
|
|
256
|
-
reject(
|
|
229
|
+
reject(ctx.controller.signal.reason);
|
|
257
230
|
};
|
|
258
|
-
if (
|
|
231
|
+
if (ctx.controller.signal.aborted)
|
|
259
232
|
return abortHandler();
|
|
260
|
-
|
|
233
|
+
ctx.controller.signal.addEventListener("abort", abortHandler, { once: true });
|
|
261
234
|
});
|
|
262
235
|
}
|
|
263
236
|
finally {
|
|
@@ -265,8 +238,13 @@ class VigorRetry extends VigorStatus {
|
|
|
265
238
|
if (listener)
|
|
266
239
|
ctx.runtime.signal.removeEventListener("abort", listener);
|
|
267
240
|
}
|
|
241
|
+
ctx.runtime.attempt++;
|
|
268
242
|
}
|
|
269
|
-
throw new VigorRetryError(`Maximum retry attempts (${ctx.setting.count}) reached. Task failed or timed out.`, {
|
|
243
|
+
throw new VigorRetryError(`Maximum retry attempts (${ctx.setting.count}) reached. Task failed or timed out.`, {
|
|
244
|
+
method: "request", type: "exhausted", data: {
|
|
245
|
+
limit: ctx.setting.limit, attempt: ctx.runtime.attempt, maxAttempts: ctx.setting.count
|
|
246
|
+
}
|
|
247
|
+
});
|
|
270
248
|
}
|
|
271
249
|
catch (error) {
|
|
272
250
|
ctx.runtime.error = error;
|
|
@@ -283,37 +261,37 @@ class VigorRetry extends VigorStatus {
|
|
|
283
261
|
}
|
|
284
262
|
}
|
|
285
263
|
}
|
|
286
|
-
const basic = { key: /text/, parse: (res) => res.text(), type: "text" };
|
|
287
|
-
const parser = [
|
|
288
|
-
{ key: /json/, parse: (res) => res.json(), type: "json" },
|
|
289
|
-
{ key: /multipart\/form-data/, parse: (res) => res.formData(), type: "formData" },
|
|
290
|
-
{ key: /octet-stream/, parse: (res) => res.arrayBuffer(), type: "arrayBuffer" },
|
|
291
|
-
{ key: /(image|video|audio|pdf)/, parse: (res) => res.blob(), type: "blob" },
|
|
292
|
-
basic
|
|
293
|
-
];
|
|
294
|
-
const supported = parser.map(i => i.type);
|
|
295
264
|
class VigorParse extends VigorStatus {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const base = {
|
|
265
|
+
constructor(config = {}) {
|
|
266
|
+
super(config, {
|
|
299
267
|
original: false
|
|
300
|
-
};
|
|
301
|
-
super({ ...base, ...config }, (c) => new VigorParse(c));
|
|
302
|
-
this._base = base;
|
|
268
|
+
});
|
|
303
269
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
270
|
+
static stategy = [
|
|
271
|
+
{ key: /text/, parse: (res) => res.text(), type: "text" },
|
|
272
|
+
{ key: /json/, parse: (res) => res.json(), type: "json" },
|
|
273
|
+
{ key: /multipart\/form-data/, parse: (res) => res.formData(), type: "formData" },
|
|
274
|
+
{ key: /octet-stream/, parse: (res) => res.arrayBuffer(), type: "arrayBuffer" },
|
|
275
|
+
{ key: /(image|video|audio|pdf)/, parse: (res) => res.blob(), type: "blob" },
|
|
276
|
+
];
|
|
277
|
+
static supported = this.stategy.map(i => i.type);
|
|
278
|
+
_transfer(config) { return new VigorParse({ ...this._config, ...config }); }
|
|
279
|
+
target(res) { return this._next({ target: res }); }
|
|
280
|
+
original(bool) { return this._transfer({ ...this._config, original: bool }); }
|
|
281
|
+
type(type) { return this._transfer({ ...this._config, result: undefined, type }); }
|
|
308
282
|
async request() {
|
|
309
283
|
const config = this._config;
|
|
310
|
-
if (!config.target)
|
|
311
|
-
throw new VigorParseError(
|
|
284
|
+
if (!(config.target instanceof Response)) {
|
|
285
|
+
throw new VigorParseError(`target not found`, {
|
|
286
|
+
method: "request", type: "args_missing", data: {
|
|
312
287
|
expected: "Response",
|
|
313
|
-
received: config.target
|
|
314
|
-
}
|
|
315
|
-
|
|
288
|
+
received: config.target
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
if (config.original) {
|
|
316
293
|
return config.target;
|
|
294
|
+
}
|
|
317
295
|
const contentType = config.target.headers.get("Content-Type") || "";
|
|
318
296
|
let strategy;
|
|
319
297
|
try {
|
|
@@ -323,13 +301,13 @@ class VigorParse extends VigorStatus {
|
|
|
323
301
|
if (!parser || typeof parser !== 'function')
|
|
324
302
|
throw new VigorParseError(`failed to parse: '${strategy?.type ?? "unknown"}'`, { method: "request", type: "invalid_type", data: {
|
|
325
303
|
expected: config.type,
|
|
326
|
-
supported: supported,
|
|
304
|
+
supported: VigorParse.supported,
|
|
327
305
|
response: config.target,
|
|
328
306
|
headers: contentType,
|
|
329
307
|
} });
|
|
330
308
|
return await parser();
|
|
331
309
|
}
|
|
332
|
-
strategy =
|
|
310
|
+
strategy = VigorParse.stategy.find(i => i.key.test(contentType)) ?? VigorParse.stategy[0];
|
|
333
311
|
return await strategy.parse(config.target);
|
|
334
312
|
}
|
|
335
313
|
catch (error) {
|
|
@@ -337,7 +315,7 @@ class VigorParse extends VigorStatus {
|
|
|
337
315
|
throw error;
|
|
338
316
|
throw new VigorParseError(`failed to parse: '${strategy?.type ?? "unknown"}'`, { method: "request", type: "parse_failed", data: {
|
|
339
317
|
expected: strategy?.type ?? "unknown",
|
|
340
|
-
supported: supported,
|
|
318
|
+
supported: VigorParse.supported,
|
|
341
319
|
response: config.target,
|
|
342
320
|
headers: contentType,
|
|
343
321
|
error
|
|
@@ -346,19 +324,15 @@ class VigorParse extends VigorStatus {
|
|
|
346
324
|
}
|
|
347
325
|
}
|
|
348
326
|
class VigorFetchSettings extends VigorStatus {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const base = {
|
|
327
|
+
constructor(config = {}) {
|
|
328
|
+
super(config, {
|
|
352
329
|
origin: "",
|
|
353
330
|
path: [],
|
|
354
331
|
query: {},
|
|
355
332
|
unretry: [400, 401, 403, 404, 405, 413, 422],
|
|
356
333
|
retryHeaders: ["retry-after", "ratelimit-reset", "x-ratelimit-reset", "x-retry-after", "x-amz-retry-after", "chrome-proxy-next-link"],
|
|
357
|
-
};
|
|
358
|
-
super({ ...base, ...config }, (c) => new VigorFetchSettings(c));
|
|
359
|
-
this._base = base;
|
|
334
|
+
});
|
|
360
335
|
}
|
|
361
|
-
getBase() { return this._base; }
|
|
362
336
|
origin(str) { return this._next({ origin: str }); }
|
|
363
337
|
path(...strs) { return this._next({ path: [...this._config.path, ...strs.flat()] }); }
|
|
364
338
|
query(obj) { return this._next({ query: { ...this._config.query, ...obj } }); }
|
|
@@ -371,36 +345,28 @@ class VigorFetchSettings extends VigorStatus {
|
|
|
371
345
|
default(obj) { return this._next({ default: obj }); }
|
|
372
346
|
}
|
|
373
347
|
class VigorFetchInterceptors extends VigorStatus {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const base = {
|
|
348
|
+
constructor(config = {}) {
|
|
349
|
+
super(config, {
|
|
377
350
|
before: [],
|
|
378
351
|
after: [],
|
|
379
352
|
onError: [],
|
|
380
353
|
result: []
|
|
381
|
-
};
|
|
382
|
-
super({ ...base, ...config }, (c) => new VigorFetchInterceptors(c));
|
|
383
|
-
this._base = base;
|
|
354
|
+
});
|
|
384
355
|
}
|
|
385
|
-
getBase() { return this._base; }
|
|
386
356
|
before(...funcs) { return this._next({ before: [...this.getConfig().before, ...funcs.flat()] }); }
|
|
387
357
|
after(...funcs) { return this._next({ after: [...this.getConfig().after, ...funcs.flat()] }); }
|
|
388
358
|
onError(...funcs) { return this._next({ onError: [...this.getConfig().onError, ...funcs.flat()] }); }
|
|
389
359
|
result(...funcs) { return this._next({ result: [...this.getConfig().result, ...funcs.flat()] }); }
|
|
390
360
|
}
|
|
391
361
|
class VigorFetch extends VigorStatus {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
const base = {
|
|
362
|
+
constructor(config = {}) {
|
|
363
|
+
super(config, {
|
|
395
364
|
setting: new VigorFetchSettings().getBase(),
|
|
396
365
|
retryConfig: new VigorRetry().getBase(),
|
|
397
366
|
parseConfig: new VigorParse().getBase(),
|
|
398
367
|
interceptors: new VigorFetchInterceptors().getBase(),
|
|
399
|
-
};
|
|
400
|
-
super({ ...base, ...config }, (c) => new VigorFetch(c), () => VigorRetryError);
|
|
401
|
-
this._base = base;
|
|
368
|
+
});
|
|
402
369
|
}
|
|
403
|
-
getBase() { return this._base; }
|
|
404
370
|
origin(str) { return this._next({ setting: { ...this._config.setting, origin: str } }); }
|
|
405
371
|
path(...strs) { return this._next({ setting: { ...this._config.setting, path: [...this._config.setting.path, ...strs.flat()] } }); }
|
|
406
372
|
query(obj) { return this._next({ setting: { ...this._config.setting, query: { ...this._config.setting.query, ...obj } } }); }
|
|
@@ -409,63 +375,50 @@ class VigorFetch extends VigorStatus {
|
|
|
409
375
|
body(obj) { return this._next({ setting: { ...this._config.setting, body: obj } }); }
|
|
410
376
|
options(obj) { return this._next({ setting: { ...this._config.setting, options: obj } }); }
|
|
411
377
|
setting(func) {
|
|
412
|
-
return this._next({
|
|
413
|
-
|
|
414
|
-
|
|
378
|
+
return this._next({ setting: this._pipsub(this._config.setting, func, VigorFetchSettings) });
|
|
379
|
+
}
|
|
380
|
+
interceptors(func) {
|
|
381
|
+
return this._next({ interceptors: this._pipsub(this._config.interceptors, func, VigorFetchInterceptors) });
|
|
415
382
|
}
|
|
416
383
|
retryConfig(func) {
|
|
417
|
-
return this._next({
|
|
418
|
-
retryConfig: this._pipeSub(this._config.retryConfig, VigorRetry, func, "retryConfig")
|
|
419
|
-
});
|
|
384
|
+
return this._next({ retryConfig: this._pipsub(this._config.retryConfig, func, VigorRetry) });
|
|
420
385
|
}
|
|
421
386
|
parseConfig(func) {
|
|
422
|
-
return this._next({
|
|
423
|
-
parseConfig: this._pipeSub(this._config.parseConfig, VigorParse, func, "parseConfig")
|
|
424
|
-
});
|
|
387
|
+
return this._next({ parseConfig: this._pipsub(this._config.parseConfig, func, VigorParse) });
|
|
425
388
|
}
|
|
426
389
|
buildUrl(origin, path, query) {
|
|
427
390
|
if (!origin)
|
|
428
|
-
throw new VigorFetchError(
|
|
429
|
-
type: "
|
|
430
|
-
|
|
391
|
+
throw new VigorFetchError(`Invalid URL origin: ${origin}`, {
|
|
392
|
+
type: "invalid_url",
|
|
393
|
+
method: "buildUrl",
|
|
394
|
+
data: {
|
|
395
|
+
expected: "string",
|
|
396
|
+
received: origin
|
|
431
397
|
}
|
|
432
398
|
});
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
399
|
+
const url = new URL(origin);
|
|
400
|
+
const segments = [
|
|
401
|
+
url.pathname,
|
|
402
|
+
...path
|
|
403
|
+
]
|
|
404
|
+
.flat()
|
|
405
|
+
.filter(Boolean)
|
|
406
|
+
.flatMap(p => p.split('/'))
|
|
407
|
+
.filter(Boolean);
|
|
408
|
+
url.pathname = '/' + segments.join('/');
|
|
409
|
+
const params = new URLSearchParams(url.search);
|
|
410
|
+
for (const [k, v] of Object.entries(query ?? {})) {
|
|
411
|
+
if (v == null)
|
|
412
|
+
continue;
|
|
413
|
+
if (Array.isArray(v)) {
|
|
414
|
+
v.forEach(i => params.append(k, String(i)));
|
|
444
415
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
if (value === null || value === undefined)
|
|
448
|
-
return;
|
|
449
|
-
if (Array.isArray(value)) {
|
|
450
|
-
value.forEach(v => url.searchParams.append(key, String(v)));
|
|
451
|
-
}
|
|
452
|
-
else {
|
|
453
|
-
url.searchParams.set(key, String(value));
|
|
454
|
-
}
|
|
455
|
-
});
|
|
416
|
+
else {
|
|
417
|
+
params.set(k, String(v));
|
|
456
418
|
}
|
|
457
|
-
return url.toString();
|
|
458
419
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
type: "invalid_url", method: "buildUrl", data: { error: e }
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
interceptors(func) {
|
|
466
|
-
return this._next({
|
|
467
|
-
interceptors: this._pipeSub(this._config.interceptors, VigorFetchInterceptors, func, "interceptors")
|
|
468
|
-
});
|
|
420
|
+
url.search = params.toString();
|
|
421
|
+
return url.toString();
|
|
469
422
|
}
|
|
470
423
|
async request() {
|
|
471
424
|
const config = this._config;
|
|
@@ -576,87 +529,75 @@ class VigorFetch extends VigorStatus {
|
|
|
576
529
|
}
|
|
577
530
|
}
|
|
578
531
|
class VigorAllSettings extends VigorStatus {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
const base = {
|
|
532
|
+
constructor(config = {}) {
|
|
533
|
+
super(config, {
|
|
582
534
|
concurrency: 5,
|
|
583
535
|
jitter: 1000
|
|
584
|
-
};
|
|
585
|
-
super({ ...base, ...config }, (c) => new VigorAllSettings(c));
|
|
586
|
-
this._base = base;
|
|
536
|
+
});
|
|
587
537
|
}
|
|
588
|
-
getBase() { return this._base; }
|
|
589
538
|
concurrency(num) { return this._next({ concurrency: num }); }
|
|
590
539
|
jitter(num) { return this._next({ jitter: num }); }
|
|
591
540
|
}
|
|
592
541
|
class VigorAllInterceptors extends VigorStatus {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
const base = {
|
|
542
|
+
constructor(config = {}) {
|
|
543
|
+
super(config, {
|
|
596
544
|
before: [],
|
|
597
545
|
after: [],
|
|
598
546
|
onError: [],
|
|
599
547
|
result: []
|
|
600
|
-
};
|
|
601
|
-
super({ ...base, ...config }, (c) => new VigorAllInterceptors(c));
|
|
602
|
-
this._base = base;
|
|
548
|
+
});
|
|
603
549
|
}
|
|
604
|
-
getBase() { return this._base; }
|
|
605
550
|
before(...funcs) { return this._next({ before: [...this.getConfig().before, ...funcs.flat()] }); }
|
|
606
551
|
after(...funcs) { return this._next({ after: [...this.getConfig().after, ...funcs.flat()] }); }
|
|
607
552
|
onError(...funcs) { return this._next({ onError: [...this.getConfig().onError, ...funcs.flat()] }); }
|
|
608
553
|
result(...funcs) { return this._next({ result: [...this.getConfig().result, ...funcs.flat()] }); }
|
|
609
554
|
}
|
|
610
555
|
class VigorAll extends VigorStatus {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
const base = {
|
|
556
|
+
constructor(config = {}) {
|
|
557
|
+
super(config, {
|
|
614
558
|
target: [],
|
|
615
559
|
setting: new VigorAllSettings().getBase(),
|
|
616
560
|
interceptors: new VigorAllInterceptors().getBase()
|
|
617
|
-
};
|
|
618
|
-
|
|
619
|
-
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
target(...funcs) {
|
|
564
|
+
return this._next({
|
|
565
|
+
target: [...this._config.target, ...funcs.flat()]
|
|
566
|
+
});
|
|
620
567
|
}
|
|
621
|
-
getBase() { return this._base; }
|
|
622
|
-
target(...funcs) { return this._next({ target: [...this._config.target, ...funcs.flat()] }); }
|
|
623
568
|
setting(func) {
|
|
624
569
|
return this._next({
|
|
625
|
-
setting: this.
|
|
570
|
+
setting: this._pipsub(this._config.setting, func, VigorAllSettings)
|
|
626
571
|
});
|
|
627
572
|
}
|
|
628
573
|
interceptors(func) {
|
|
629
574
|
return this._next({
|
|
630
|
-
interceptors: this.
|
|
575
|
+
interceptors: this._pipsub(this._config.interceptors, func, VigorAllInterceptors)
|
|
631
576
|
});
|
|
632
577
|
}
|
|
633
578
|
async request() {
|
|
634
579
|
const config = this._config;
|
|
635
580
|
let ctx = {
|
|
636
581
|
target: [...config.target],
|
|
637
|
-
setting: { ...config.setting },
|
|
638
|
-
interceptors: {
|
|
639
|
-
before: [...config.interceptors.before],
|
|
640
|
-
after: [...config.interceptors.after],
|
|
641
|
-
onError: [...config.interceptors.onError],
|
|
642
|
-
result: [...config.interceptors.result]
|
|
643
|
-
},
|
|
644
582
|
runtime: {
|
|
645
583
|
tasks: [],
|
|
646
584
|
result: []
|
|
647
585
|
}
|
|
648
586
|
};
|
|
649
|
-
if (ctx.target
|
|
587
|
+
if (ctx.target.length == 0)
|
|
650
588
|
throw new VigorFetchError("request expects 'target'", {
|
|
651
|
-
type: "invalid_input",
|
|
652
|
-
|
|
589
|
+
type: "invalid_input",
|
|
590
|
+
method: "request",
|
|
591
|
+
data: {
|
|
592
|
+
expected: "string",
|
|
593
|
+
received: ctx.target
|
|
653
594
|
}
|
|
654
595
|
});
|
|
655
596
|
let active = 0;
|
|
656
597
|
const queue = [];
|
|
657
598
|
const runTask = async (task) => {
|
|
658
599
|
await new Promise(resolve => {
|
|
659
|
-
if (active <
|
|
600
|
+
if (active < config.setting.concurrency) {
|
|
660
601
|
active++;
|
|
661
602
|
resolve();
|
|
662
603
|
}
|
|
@@ -669,14 +610,14 @@ class VigorAll extends VigorStatus {
|
|
|
669
610
|
});
|
|
670
611
|
const throwError = (error) => { throw error; };
|
|
671
612
|
try {
|
|
672
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
613
|
+
await new Promise(resolve => setTimeout(resolve, VigorRetryBackoff.randomJitter(config.setting.jitter)));
|
|
673
614
|
let res;
|
|
674
|
-
for (const func of
|
|
615
|
+
for (const func of config.interceptors.before) {
|
|
675
616
|
await func(ctx, { throwError });
|
|
676
617
|
}
|
|
677
618
|
res = await task(ctx, {});
|
|
678
619
|
const setResult = (result) => res = result;
|
|
679
|
-
for (const func of
|
|
620
|
+
for (const func of config.interceptors.after) {
|
|
680
621
|
await func(ctx, { setResult, throwError });
|
|
681
622
|
}
|
|
682
623
|
return res;
|
|
@@ -684,8 +625,11 @@ class VigorAll extends VigorStatus {
|
|
|
684
625
|
catch (error) {
|
|
685
626
|
let res;
|
|
686
627
|
let overrided = false;
|
|
687
|
-
const setResult = (result) => {
|
|
688
|
-
|
|
628
|
+
const setResult = (result) => {
|
|
629
|
+
overrided = true;
|
|
630
|
+
return (res = result);
|
|
631
|
+
};
|
|
632
|
+
for (const func of config.interceptors.onError) {
|
|
689
633
|
await func(ctx, { setResult, throwError });
|
|
690
634
|
}
|
|
691
635
|
if (overrided && res !== undefined)
|
|
@@ -705,22 +649,21 @@ class VigorAll extends VigorStatus {
|
|
|
705
649
|
if (i.status === "fulfilled")
|
|
706
650
|
return i.value;
|
|
707
651
|
return new VigorAllError(`this request failed`, {
|
|
708
|
-
method: "request",
|
|
652
|
+
method: "request",
|
|
653
|
+
type: "request_failed",
|
|
654
|
+
data: {
|
|
709
655
|
error: i.reason
|
|
710
656
|
}
|
|
711
657
|
});
|
|
712
658
|
});
|
|
713
659
|
const setResult = (result) => ctx.runtime.result = result;
|
|
714
660
|
const throwError = (error) => { throw error; };
|
|
715
|
-
for (const func of
|
|
661
|
+
for (const func of config.interceptors.result) {
|
|
716
662
|
await func(ctx, { setResult, throwError });
|
|
717
663
|
}
|
|
718
664
|
return ctx.runtime.result;
|
|
719
665
|
}
|
|
720
666
|
}
|
|
721
|
-
function calculateJitter(jitter) {
|
|
722
|
-
return jitter * (Math.random() * 2 - 1);
|
|
723
|
-
}
|
|
724
667
|
class Vigor {
|
|
725
668
|
registry;
|
|
726
669
|
constructor(config) {
|
|
@@ -754,8 +697,11 @@ class Vigor {
|
|
|
754
697
|
fetch(origin) {
|
|
755
698
|
return this.registry.VigorFetch.main().origin(origin);
|
|
756
699
|
}
|
|
757
|
-
all(
|
|
758
|
-
|
|
700
|
+
all(...args) {
|
|
701
|
+
const flatTasks = args.flat();
|
|
702
|
+
return this.registry.VigorAll
|
|
703
|
+
.main()
|
|
704
|
+
.target(...flatTasks);
|
|
759
705
|
}
|
|
760
706
|
parse(response) {
|
|
761
707
|
return this.registry.VigorParse.main().target(response);
|