vigor-fetch 2.2.8 → 3.0.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/dist/index.js CHANGED
@@ -2,43 +2,37 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const VIGOR_ERROR_MESSAGES = {
6
- TIMEOUT: ({ limit, attempt }) => `Timeout: exceeded ${limit}ms (attempt: ${attempt})`,
5
+ const VigorErrorMessageFuncs = {
6
+ INVALID_TARGET: ({ expected, received }) => `Invalid Task: ${typeof received} (expected: ${expected.join(', ')})`,
7
7
  EXHAUSTED: ({ maxAttempts }) => `Retry exhausted: max ${maxAttempts})`,
8
- INVALID_URL: ({ received }) => `Invalid URL: ${received}`,
9
- INVALID_PROTOCOL: ({ expected, received }) => `Invalid protocol: ${received} (expected ${expected.join(", ")})`,
10
- FETCH_ERROR: ({ status, statusText, url }) => `HTTP Error: ${status} ${statusText} (url: ${url})`,
11
- PARSE_FAILED: ({ expected }) => `Parse failed: expected ${expected}`,
12
- INVALID_TYPE: ({ expected, received }) => `Invalid parser type: ${expected}`,
13
- TARGET_MISSING: () => `Target missing`,
14
- REQUEST_FAILED: ({ index, error }) => `Request failed at index ${index}: ${error?.message || "unknown"}`,
15
- RESULT_NOT_SET: (() => `Result was not resolved`),
16
- UNKNOWN: () => `Unknown error`
17
- };
18
- const normalizeError = (obj) => {
19
- if (obj instanceof Error) {
20
- throw obj;
21
- }
22
- throw new Error(String(obj));
8
+ TIMED_OUT: ({ limit, attempt }) => `Timeout: exceeded ${limit}ms (attempt: ${attempt})`,
9
+ INVALID_CONTENT_TYPE: ({ expected, received, response }) => `Invalid Content Type Header: ${typeof received} (expected: ${expected.join(', ')})`,
10
+ PARSER_NOT_FOUND: ({ expected, received, response }) => `Parser Not Found For Header: ${typeof received} (expected: ${expected.join(', ')})`,
11
+ PARSER_ALL_FAILED: ({ tried, response }) => `All Parser Failed, Tried: ${tried.join(', ')}`,
12
+ INVALID_PROTOCOL: ({ expected, received }) => `Invalid Protocol: ${typeof received} (expected: ${expected.join(', ')})`,
13
+ INVALID_BODY: ({ expected, received }) => `Invalid Body: ${typeof received} (expected: ${expected.join(', ')})`,
14
+ FETCH_FAILED: ({ status, response, url, headers, body, statusText }) => `Fetch Failed: ${status}`,
15
+ EMPTY_TARGET: ({}) => `Empty Body`
23
16
  };
24
17
  class VigorError extends Error {
25
18
  timestamp = new Date();
26
- method;
27
- code;
28
19
  cause;
29
- context;
30
- type;
20
+ code;
31
21
  data;
22
+ method;
23
+ stats;
24
+ context;
32
25
  constructor(code, options) {
33
- const messageFn = VIGOR_ERROR_MESSAGES[code];
26
+ const messageFn = VigorErrorMessageFuncs[code];
34
27
  const message = `[${code}] ${messageFn(options?.data)}`;
35
28
  super(message, { cause: options?.cause });
36
29
  this.name = new.target.name;
37
- this.method = options?.method;
38
30
  this.code = code;
39
- this.context = options?.context;
40
- this.type = options?.type;
31
+ this.cause = options.cause;
41
32
  this.data = options.data;
33
+ this.method = options.method;
34
+ this.stats = options.stats;
35
+ this.context = options.context;
42
36
  Object.setPrototypeOf(this, new.target.prototype);
43
37
  Error.captureStackTrace?.(this, new.target);
44
38
  }
@@ -63,760 +57,1123 @@ class VigorAllError extends VigorError {
63
57
  super(code, options);
64
58
  }
65
59
  }
66
- const EMPTY = Symbol("EMPTY");
67
60
  class VigorStatus {
68
61
  _base;
62
+ ctor;
69
63
  _config;
70
- constructor(config, _base) {
64
+ constructor(config = {}, _base, ctor) {
71
65
  this._base = _base;
72
- this._config = { ...this._base, ...config };
66
+ this.ctor = ctor;
67
+ this._config = { ..._base, ...config };
73
68
  }
74
- getConfig() { return this._config; }
75
- getBase() { return this._base; }
76
- _next(config) { return new this.constructor({ ...this._config, ...config }, this._base); }
77
- _pipsub(config, fn, ctor) {
78
- return fn(new ctor(config)).getConfig();
69
+ _mergeConfig(source, target) {
70
+ const isPlainObject = (val) => val !== null && typeof val === 'object' && Object.getPrototypeOf(val) === Object.prototype;
71
+ if (target === undefined || target === null) {
72
+ return source;
73
+ }
74
+ if (isPlainObject(source) && isPlainObject(target)) {
75
+ const result = { ...source };
76
+ Object.keys(target).forEach((key) => {
77
+ result[key] = this._mergeConfig(result[key], target[key]);
78
+ });
79
+ return result;
80
+ }
81
+ if (Array.isArray(source) && Array.isArray(target)) {
82
+ return [...source, ...target];
83
+ }
84
+ return target;
79
85
  }
86
+ _next(config) { return this.ctor(this._mergeConfig(this._config, config)); }
87
+ _getConfig() { return this._config; }
88
+ _getBase() { return this._base; }
80
89
  }
90
+ const VigorDefault = Symbol("DEFAULT");
81
91
  class VigorRetrySettings extends VigorStatus {
82
- constructor(config = {}) {
83
- super(config, {
84
- count: 5,
85
- limit: 10000,
86
- maxDelay: 10000,
87
- default: EMPTY
88
- });
89
- }
90
- count(num) { return this._next({ count: num }); }
91
- limit(num) { return this._next({ limit: num }); }
92
- maxDelay(num) { return this._next({ maxDelay: num }); }
93
- default(obj) { return this._next({ default: obj }); }
94
- }
95
- class VigorRetryBackoff extends VigorStatus {
96
- constructor(config = {}) {
97
- super(config, {
98
- initialDelay: 0,
99
- baseDelay: 1000,
100
- factor: 1.7,
92
+ constructor(config) {
93
+ const base = {
94
+ default: VigorDefault,
95
+ timeout: 20 * 1000,
96
+ attempt: 5,
101
97
  jitter: 1000
102
- });
98
+ };
99
+ super(config, base, (c) => new VigorRetrySettings(c));
103
100
  }
104
- initialDelay(num) { return this._next({ initialDelay: num }); }
105
- baseDelay(num) { return this._next({ baseDelay: num }); }
106
- factor(num) { return this._next({ factor: num }); }
101
+ default(unk) { return this._next({ default: unk }); }
102
+ timeout(num) { return this._next({ timeout: num }); }
103
+ attempt(num) { return this._next({ attempt: num }); }
107
104
  jitter(num) { return this._next({ jitter: num }); }
108
- static randomJitter(num) { return Math.random() * num; }
109
105
  }
110
106
  class VigorRetryInterceptors extends VigorStatus {
111
- constructor(config = {}) {
112
- super(config, {
107
+ constructor(config) {
108
+ const base = {
113
109
  before: [],
114
110
  after: [],
115
- onError: [],
111
+ result: [],
112
+ retryIf: [],
116
113
  onRetry: [],
117
- retryIf: []
118
- });
114
+ onError: []
115
+ };
116
+ super(config, base, (c) => new VigorRetryInterceptors(c));
119
117
  }
120
- before(...funcs) { return this._next({ ...this._config, before: [...this._config.before, ...funcs.flat()] }); }
121
- after(...funcs) { return this._next({ ...this._config, after: [...this._config.after, ...funcs.flat()] }); }
122
- onError(...funcs) { return this._next({ ...this._config, onError: [...this._config.onError, ...funcs.flat()] }); }
123
- onRetry(...funcs) { return this._next({ ...this._config, onRetry: [...this._config.onRetry, ...funcs.flat()] }); }
124
- retryIf(...funcs) { return this._next({ ...this._config, retryIf: [...this._config.retryIf, ...funcs.flat()] }); }
118
+ before(...funcs) { return this._next({ before: funcs.flat() }); }
119
+ after(...funcs) { return this._next({ after: funcs.flat() }); }
120
+ result(...funcs) { return this._next({ result: funcs.flat() }); }
121
+ retryIf(...funcs) { return this._next({ retryIf: funcs.flat() }); }
122
+ onRetry(...funcs) { return this._next({ onRetry: funcs.flat() }); }
123
+ onError(...funcs) { return this._next({ onError: funcs.flat() }); }
125
124
  }
126
- class VigorRetry extends VigorStatus {
127
- constructor(config = {}) {
128
- super(config, {
129
- target: null,
130
- setting: new VigorRetrySettings().getBase(),
131
- backoff: new VigorRetryBackoff().getBase(),
132
- interceptors: new VigorRetryInterceptors().getBase(),
133
- controller: config.controller || new AbortController()
134
- });
125
+ class VigorRetryAlgorithmsConstant extends VigorStatus {
126
+ constructor(config) {
127
+ const base = {
128
+ interval: 2000
129
+ };
130
+ super(config, base, (c) => new VigorRetryAlgorithmsConstant(c));
135
131
  }
136
- _transfer(config) { return new VigorRetry({ ...this._config, ...config }); }
137
- _calculateDelay(initialDelay, baseDelay, factor, attempt, jitter, maxDelay) {
138
- return Math.max(0, Math.min(maxDelay, initialDelay + baseDelay * Math.pow(factor, attempt) + VigorRetryBackoff.randomJitter(jitter)));
132
+ interval(num) { return this._next({ interval: num }); }
133
+ /** @internal */
134
+ _calculateDelay(attempt) {
135
+ return this._config.interval;
139
136
  }
140
- createController() { return this._config.controller = new AbortController(); }
141
- target(func) { return this._transfer({ target: func }); }
142
- setting(func) {
143
- return this._next({ setting: this._pipsub(this._config.setting, func, VigorRetrySettings) });
137
+ }
138
+ class VigorRetryAlgorithmsLinear extends VigorStatus {
139
+ constructor(config) {
140
+ const base = {
141
+ initial: 1000,
142
+ increment: 1000,
143
+ minDelay: 500,
144
+ maxDelay: 20 * 1000
145
+ };
146
+ super(config, base, (c) => new VigorRetryAlgorithmsLinear(c));
147
+ }
148
+ initial(num) { return this._next({ initial: num }); }
149
+ increment(num) { return this._next({ increment: num }); }
150
+ minDelay(num) { return this._next({ minDelay: num }); }
151
+ maxDelay(num) { return this._next({ maxDelay: num }); }
152
+ /** @internal */
153
+ _calculateDelay(attempt) {
154
+ const { initial, increment, minDelay, maxDelay } = this._config;
155
+ return Math.max(minDelay, Math.min(maxDelay, initial + increment * attempt));
144
156
  }
145
- backoff(func) {
146
- return this._next({ backoff: this._pipsub(this._config.backoff, func, VigorRetryBackoff) });
157
+ }
158
+ class VigorRetryAlgorithmsBackoff extends VigorStatus {
159
+ constructor(config) {
160
+ const base = {
161
+ initial: 1000,
162
+ multiplier: 1.7,
163
+ unit: 1000,
164
+ minDelay: 500,
165
+ maxDelay: 20 * 1000
166
+ };
167
+ super(config, base, (c) => new VigorRetryAlgorithmsBackoff(c));
168
+ }
169
+ initial(num) { return this._next({ initial: num }); }
170
+ multiplier(num) { return this._next({ multiplier: num }); }
171
+ unit(num) { return this._next({ unit: num }); }
172
+ minDelay(num) { return this._next({ minDelay: num }); }
173
+ maxDelay(num) { return this._next({ maxDelay: num }); }
174
+ /** @internal */
175
+ _calculateDelay(attempt) {
176
+ const { initial, multiplier, unit, minDelay, maxDelay } = this._config;
177
+ return Math.max(minDelay, Math.min(maxDelay, initial + unit * Math.pow(multiplier, attempt)));
178
+ }
179
+ }
180
+ class VigorRetryAlgorithmsCustom extends VigorStatus {
181
+ constructor(config) {
182
+ const base = {
183
+ func: (attempt) => attempt * 1000,
184
+ minDelay: 500,
185
+ maxDelay: 20 * 1000
186
+ };
187
+ super(config, base, (c) => new VigorRetryAlgorithmsCustom(c));
188
+ }
189
+ func(num) { return this._next({ func: num }); }
190
+ /** @internal */
191
+ _calculateDelay(attempt) {
192
+ const { func, minDelay, maxDelay } = this._config;
193
+ return Math.max(minDelay, Math.min(maxDelay, func(attempt)));
194
+ }
195
+ }
196
+ class VigorRetry extends VigorStatus {
197
+ constructor(config) {
198
+ const base = {
199
+ target: VigorDefault,
200
+ settings: new VigorRetrySettings()._getBase(),
201
+ interceptors: new VigorRetryInterceptors()._getBase(),
202
+ algorithm: new VigorRetryAlgorithmsBackoff()._calculateDelay,
203
+ abortSignals: []
204
+ };
205
+ super(config, base, (c) => new VigorRetry(c));
206
+ }
207
+ RetryAlgorithms = {
208
+ constant: (config) => new VigorRetryAlgorithmsConstant(config),
209
+ linear: (config) => new VigorRetryAlgorithmsLinear(config),
210
+ backoff: (config) => new VigorRetryAlgorithmsBackoff(config),
211
+ custom: (config) => new VigorRetryAlgorithmsCustom(config)
212
+ };
213
+ target(func) { return this._next({ target: func }); }
214
+ settings(func) {
215
+ if (typeof func === 'function') {
216
+ return this._next({ settings: func(new VigorRetrySettings(this._config.settings))._getConfig() });
217
+ }
218
+ return this._next({ settings: func });
147
219
  }
148
220
  interceptors(func) {
149
- return this._next({ interceptors: this._pipsub(this._config.interceptors, func, VigorRetryInterceptors) });
221
+ if (typeof func === 'function') {
222
+ return this._next({ interceptors: func(new VigorRetryInterceptors(this._config.interceptors))._getConfig() });
223
+ }
224
+ return this._next({ interceptors: func });
225
+ }
226
+ algorithms(func) {
227
+ const instance = func(this.RetryAlgorithms);
228
+ return this._next({ algorithm: (attempt) => instance._calculateDelay(attempt) });
150
229
  }
151
- async request() {
152
- const config = this._config;
230
+ abortSignals(...abortSignals) {
231
+ return this._next({ abortSignals: abortSignals.flat() });
232
+ }
233
+ async request(config, timeline = []) {
234
+ const stats = this._mergeConfig(this._config, config);
153
235
  let ctx = {
154
- target: config.target,
155
- setting: { ...config.setting },
156
- interceptors: {
157
- before: [...config.interceptors.before],
158
- after: [...config.interceptors.after],
159
- onError: [...config.interceptors.onError],
160
- onRetry: [...config.interceptors.onRetry],
161
- retryIf: [...config.interceptors.retryIf],
162
- },
163
- backoff: { ...config.backoff },
164
- controller: config.controller,
165
- runtime: {
166
- result: EMPTY,
167
- controller: null,
168
- attempt: 0,
169
- aborted: false,
170
- signal: null,
171
- delay: 0,
172
- retry: false,
173
- }
236
+ result: VigorDefault,
237
+ error: VigorDefault,
238
+ attempt: 0,
239
+ delay: 0,
240
+ controller: VigorDefault,
241
+ timeline: timeline,
242
+ stats,
243
+ };
244
+ const throwError = (error) => {
245
+ ctx.timeline.push({ action: "throwError called", content: error });
246
+ throw error;
174
247
  };
175
- const throwError = (error) => { throw error; };
176
248
  try {
177
- while (ctx.runtime.attempt < ctx.setting.count) {
178
- ctx.runtime.controller = new AbortController();
179
- let listener;
180
- let timerId;
181
- const setAttempt = (attempt) => ctx.runtime.attempt = attempt;
182
- const abort = (error) => { if (!ctx.runtime.aborted) {
183
- ctx.runtime.controller?.abort(error);
184
- } };
249
+ if (typeof stats.target !== 'function')
250
+ throw new VigorRetryError("INVALID_TARGET", {
251
+ method: "request",
252
+ data: {
253
+ expected: ["function"],
254
+ received: stats.target
255
+ },
256
+ stats: stats,
257
+ context: ctx
258
+ });
259
+ while (ctx.attempt < stats.settings.attempt) {
260
+ ctx.attempt++;
261
+ ctx.timeline.push({ action: "increased attempt", content: ctx.attempt });
262
+ let broke = false;
263
+ const breakRetry = (error) => {
264
+ ctx.timeline.push({ action: "breakRetry called", content: error });
265
+ broke = true;
266
+ throw error;
267
+ };
185
268
  try {
186
- ctx.runtime.signal = AbortSignal.any([
187
- ctx.controller.signal,
188
- ctx.runtime.controller.signal
189
- ]);
190
- ctx.runtime.abortPromise = new Promise((_, reject) => {
191
- if (ctx.runtime.signal.aborted)
192
- reject(ctx.runtime.signal.reason);
193
- listener = () => {
194
- ctx.runtime.aborted = true;
195
- reject(ctx.runtime.signal.reason);
196
- };
197
- ctx.runtime.signal.addEventListener("abort", listener, { once: true });
198
- timerId = setTimeout(() => {
199
- if (ctx.runtime.aborted)
200
- return;
201
- abort(new VigorRetryError("TIMEOUT", {
202
- method: "request",
203
- type: "timeout",
204
- data: {
205
- limit: ctx.setting.limit,
206
- attempt: ctx.runtime.attempt
207
- }
208
- }));
209
- }, ctx.setting.limit);
210
- });
211
- for (const func of ctx.interceptors.before) {
212
- await func(ctx, { setAttempt, throwError, abort });
213
- if (ctx.runtime.signal.aborted)
214
- normalizeError(ctx.runtime.signal.reason);
269
+ ctx.timeline.push({ action: "process request_once handling", content: ctx.attempt });
270
+ const controller = new AbortController();
271
+ const timeoutController = new AbortController();
272
+ const signal = AbortSignal.any([controller.signal, timeoutController.signal, ...stats.abortSignals]);
273
+ const abort = (err) => controller.abort(err);
274
+ ctx.timeline.push({ action: "interceptor handling: before", content: stats.interceptors.before });
275
+ for (const func of stats.interceptors.before) {
276
+ await func(ctx, { throwError, breakRetry, abort });
215
277
  }
216
- ctx.runtime.result = await Promise.race([
217
- ctx.target(ctx, { abort, signal: ctx.runtime.signal }),
218
- ctx.runtime.abortPromise
219
- ]);
220
- const setResult = (result) => ctx.runtime.result = result;
221
- for (const func of ctx.interceptors.after) {
222
- await func(ctx, { setAttempt, setResult, throwError });
223
- if (ctx.runtime.signal.aborted)
224
- normalizeError(ctx.runtime.signal.reason);
278
+ const timeoutTimer = setTimeout(() => {
279
+ clearTimeout(timeoutTimer);
280
+ timeoutController.abort(new VigorRetryError("TIMED_OUT", {
281
+ method: "request",
282
+ data: {
283
+ limit: stats.settings.timeout,
284
+ attempt: ctx.attempt
285
+ },
286
+ }));
287
+ }, stats.settings.timeout);
288
+ signal.throwIfAborted();
289
+ let onAbort;
290
+ try {
291
+ ctx.result = await Promise.race([
292
+ stats.target(ctx, { abort, signal }),
293
+ new Promise((_, rej) => {
294
+ onAbort = () => rej(signal.reason);
295
+ signal.addEventListener("abort", onAbort);
296
+ })
297
+ ]);
225
298
  }
226
- return ctx.runtime.result;
227
- }
228
- catch (error) {
229
- if (ctx.runtime.aborted)
230
- normalizeError(ctx.runtime.signal.reason);
231
- ctx.runtime.retry = true;
232
- ctx.runtime.error = error;
233
- const proceedRetry = () => ctx.runtime.retry = true;
234
- const cancelRetry = (error) => { ctx.runtime.error = error; return (ctx.runtime.retry = false); };
235
- for (const func of ctx.interceptors.retryIf) {
236
- await func(ctx, { throwError, proceedRetry, cancelRetry });
299
+ finally {
300
+ clearTimeout(timeoutTimer);
301
+ if (onAbort)
302
+ signal.removeEventListener("abort", onAbort);
237
303
  }
238
- if (!ctx.runtime.retry) {
239
- throw ctx.runtime.error;
304
+ const setResult = (unk) => {
305
+ ctx.timeline.push({ action: "setResult called", content: unk });
306
+ ctx.result = unk;
307
+ return unk;
308
+ };
309
+ ctx.timeline.push({ action: "interceptor handling: after", content: stats.interceptors.after });
310
+ for (const func of stats.interceptors.after) {
311
+ await func(ctx, { setResult, throwError, breakRetry });
240
312
  }
241
- const { initialDelay, baseDelay, factor, jitter } = ctx.backoff;
242
- ctx.runtime.delay = this._calculateDelay(initialDelay, baseDelay, factor, ctx.runtime.attempt, jitter, ctx.setting.maxDelay);
243
- const setDelay = (delay) => ctx.runtime.delay = delay;
244
- for (const func of ctx.interceptors.onRetry) {
245
- await func(ctx, { setAttempt, throwError, setDelay });
313
+ ctx.timeline.push({ action: "interceptor handling: result", content: stats.interceptors.result });
314
+ for (const func of stats.interceptors.result) {
315
+ await func(ctx, { setResult, throwError });
246
316
  }
247
- await new Promise((resolve, reject) => {
248
- const timer = setTimeout(resolve, ctx.runtime.delay);
249
- const abortHandler = () => {
250
- clearTimeout(timer);
251
- reject(ctx.controller.signal.reason);
252
- };
253
- if (ctx.controller.signal.aborted)
254
- return abortHandler();
255
- ctx.controller.signal.addEventListener("abort", abortHandler, { once: true });
256
- });
317
+ return ctx.result;
257
318
  }
258
- finally {
259
- clearTimeout(timerId);
260
- if (listener)
261
- ctx.runtime.signal.removeEventListener("abort", listener);
319
+ catch (error) {
320
+ ctx.error = error;
321
+ ctx.timeline.push({ action: "process error_once handling", content: error });
322
+ if (broke)
323
+ throw error;
324
+ let proceed = true;
325
+ const proceedRetry = () => {
326
+ ctx.timeline.push({ action: "proceedRetry called", content: true });
327
+ return proceed = true;
328
+ };
329
+ const cancelRetry = () => {
330
+ ctx.timeline.push({ action: "cancelRetry called", content: false });
331
+ return proceed = false;
332
+ };
333
+ ctx.timeline.push({ action: "interceptor handling: retryIf", content: stats.interceptors.result });
334
+ for (const func of stats.interceptors.retryIf) {
335
+ await func(ctx, { proceedRetry, cancelRetry });
336
+ }
337
+ if (!proceed)
338
+ throw error;
339
+ ctx.delay = VigorDefault;
340
+ const setDelay = (num) => {
341
+ ctx.timeline.push({ action: "setDelay called", content: num });
342
+ return ctx.delay = num;
343
+ };
344
+ const setAttempt = (num) => {
345
+ ctx.timeline.push({ action: "setAttempt called", content: num });
346
+ return ctx.attempt = num;
347
+ };
348
+ ctx.timeline.push({ action: "interceptor handling: onRetry", content: stats.interceptors.onRetry });
349
+ for (const func of stats.interceptors.onRetry) {
350
+ await func(ctx, { throwError, setDelay, setAttempt });
351
+ }
352
+ if (typeof ctx.delay !== 'number')
353
+ ctx.delay = stats.algorithm(ctx.attempt) + Math.random() * stats.settings.jitter;
354
+ const delay = ctx.delay;
355
+ await new Promise(r => setTimeout(r, delay));
262
356
  }
263
- ctx.runtime.attempt++;
264
357
  }
265
358
  throw new VigorRetryError("EXHAUSTED", {
266
359
  method: "request",
267
- type: "retry",
268
360
  data: {
269
- maxAttempts: ctx.setting.count,
270
- }
361
+ maxAttempts: stats.settings.attempt,
362
+ },
363
+ context: ctx
271
364
  });
272
365
  }
273
366
  catch (error) {
274
- ctx.runtime.error = error;
275
- let overrided = false;
276
- const setResult = (result) => { overrided = true; return (ctx.runtime.result = result); };
277
- for (const func of ctx.interceptors.onError) {
278
- await func(ctx, { setResult, throwError });
367
+ ctx.error = error;
368
+ let overwritten = false;
369
+ const setResult = (unk) => {
370
+ ctx.timeline.push({ action: "setResult called", content: unk });
371
+ ctx.result = unk;
372
+ overwritten = true;
373
+ return unk;
374
+ };
375
+ let restarted = false;
376
+ const restart = () => {
377
+ ctx.timeline.push({ action: "restart called" });
378
+ restarted = true;
379
+ };
380
+ ctx.timeline.push({ action: "interceptor handling: onError", content: stats.interceptors.onError });
381
+ for (const func of stats.interceptors.onError) {
382
+ await func(ctx, { setResult, throwError, restart });
383
+ }
384
+ if (restarted) {
385
+ return await this.request(stats, ctx.timeline);
279
386
  }
280
- if (overrided && ctx.runtime.result !== EMPTY)
281
- return ctx.runtime.result;
282
- if (ctx.setting.default !== EMPTY)
283
- return ctx.setting.default;
387
+ if (overwritten)
388
+ return ctx.result;
389
+ if (stats.settings.default !== VigorDefault)
390
+ return stats.settings.default;
284
391
  throw error;
285
392
  }
286
393
  }
287
394
  }
288
- class VigorParse extends VigorStatus {
289
- constructor(config = {}) {
290
- super(config, {
291
- original: false
292
- });
395
+ class VigorParseSettings extends VigorStatus {
396
+ constructor(config) {
397
+ const base = {
398
+ raw: false,
399
+ default: VigorDefault
400
+ };
401
+ super(config, base, (c) => new VigorParseSettings(c));
293
402
  }
294
- static stategy = [
295
- { key: /text/, parse: (res) => res.text(), type: "text" },
296
- { key: /json/, parse: (res) => res.json(), type: "json" },
297
- { key: /multipart\/form-data/, parse: (res) => res.formData(), type: "formData" },
298
- { key: /octet-stream/, parse: (res) => res.arrayBuffer(), type: "arrayBuffer" },
299
- { key: /(image|video|audio|pdf)/, parse: (res) => res.blob(), type: "blob" },
403
+ original(bool) { return this._next({ raw: bool }); }
404
+ default(unk) { return this._next({ default: unk }); }
405
+ }
406
+ class VigorParseStrategies extends VigorStatus {
407
+ constructor(config) {
408
+ const base = {
409
+ funcs: []
410
+ };
411
+ super(config, base, (c) => new VigorParseStrategies(c));
412
+ this._config.funcs.push(this.ParseAutoAlgorithms.contentType);
413
+ }
414
+ ParseAutoHeaders = [
415
+ { header: "application/json", regExp: /application\/(.+\+)?json(.+\+)?/i, method: (res) => res.json() },
416
+ { header: "application/xml", regExp: /application\/(.+\+)?xml(.+\+)?/i, method: (res) => res.text() },
417
+ { header: "application/x-www-form-urlencoded", regExp: /application\/(.+\+)?x-www-form-urlencoded(.+\+)?/i, method: (res) => res.formData() },
418
+ { header: "application/octet-stream", regExp: /application\/(.+\+)?octet-stream(.+\+)?/i, method: (res) => res.arrayBuffer() },
419
+ { header: "image/*", regExp: /^image\/.+/i, method: (res) => res.blob() },
420
+ { header: "audio/*", regExp: /^audio\/.+/i, method: (res) => res.blob() },
421
+ { header: "video/*", regExp: /^video\/.+/i, method: (res) => res.blob() },
422
+ { header: "multipart/form-data", regExp: /multipart\/(.+\+)?form-data(.+\+)?/i, method: (res) => res.formData() },
423
+ { header: "text/*", regExp: /^text\/.+/i, method: (res) => res.text() },
300
424
  ];
301
- static supported = this.stategy.map(i => i.type);
302
- _transfer(config) { return new VigorParse({ ...this._config, ...config }); }
303
- target(res) { return this._next({ target: res }); }
304
- original(bool) { return this._transfer({ ...this._config, original: bool }); }
305
- type(type) { return this._transfer({ ...this._config, result: undefined, type }); }
306
- async request() {
307
- const config = this._config;
308
- if (!(config.target instanceof Response)) {
309
- throw new VigorParseError("TARGET_MISSING", {
310
- method: "request",
311
- type: "args_missing",
312
- data: undefined
425
+ ParseAutoMethods = [
426
+ { title: "json", method: (res) => res.json() },
427
+ { title: "formData", method: (res) => res.formData() },
428
+ { title: "text", method: (res) => res.text() },
429
+ { title: "blob", method: (res) => res.blob() },
430
+ ];
431
+ ParseAutoAlgorithms = {
432
+ contentType: async (response) => {
433
+ const parsers = this.ParseAutoHeaders;
434
+ const contentTypeHeader = response.headers.get("content-type");
435
+ if (!contentTypeHeader)
436
+ throw new VigorParseError("INVALID_CONTENT_TYPE", {
437
+ method: "ParseAutoAlgorithms.contentType",
438
+ data: {
439
+ expected: ["string"],
440
+ received: contentTypeHeader,
441
+ response: response
442
+ }
443
+ });
444
+ const toDo = parsers.find(parser => parser.regExp.test(contentTypeHeader));
445
+ if (!toDo)
446
+ throw new VigorParseError("PARSER_NOT_FOUND", {
447
+ method: "ParseAutoAlgorithms.contentType",
448
+ data: {
449
+ expected: parsers.map(parser => parser.header),
450
+ received: contentTypeHeader,
451
+ response: response
452
+ }
453
+ });
454
+ return await toDo.method(response);
455
+ },
456
+ sniff: async (response) => {
457
+ const parsers = this.ParseAutoMethods;
458
+ for (const [i, parser] of parsers.entries()) {
459
+ const cloned = (i === parsers.length - 1)
460
+ ? response
461
+ : response.clone();
462
+ try {
463
+ const data = await parser.method(cloned);
464
+ return data;
465
+ }
466
+ catch { }
467
+ }
468
+ throw new VigorParseError("PARSER_ALL_FAILED", {
469
+ method: "ParseAutoAlgorithms.sniff",
470
+ data: {
471
+ tried: parsers.map(parser => parser.title),
472
+ response: response
473
+ }
313
474
  });
314
475
  }
315
- if (config.original) {
316
- return config.target;
476
+ };
477
+ contentType() { return this._next({ funcs: [this.ParseAutoAlgorithms.contentType] }); }
478
+ sniff() { return this._next({ funcs: [this.ParseAutoAlgorithms.sniff] }); }
479
+ json() { return this._next({ funcs: [(res) => res.json()] }); }
480
+ text() { return this._next({ funcs: [(res) => res.text()] }); }
481
+ arrayBuffer() { return this._next({ funcs: [(res) => res.arrayBuffer()] }); }
482
+ blob() { return this._next({ funcs: [(res) => res.blob()] }); }
483
+ bytes() { return this._next({ funcs: [(res) => res.arrayBuffer().then(r => new Uint8Array(r))] }); }
484
+ formData() { return this._next({ funcs: [(res) => res.formData()] }); }
485
+ }
486
+ class VigorParseInterceptors extends VigorStatus {
487
+ constructor(config) {
488
+ const base = {
489
+ before: [],
490
+ after: [],
491
+ result: [],
492
+ onError: []
493
+ };
494
+ super(config, base, (c) => new VigorParseInterceptors(c));
495
+ }
496
+ before(...funcs) { return this._next({ before: funcs.flat() }); }
497
+ after(...funcs) { return this._next({ after: funcs.flat() }); }
498
+ result(...funcs) { return this._next({ result: funcs.flat() }); }
499
+ onError(...funcs) { return this._next({ onError: funcs.flat() }); }
500
+ }
501
+ class VigorParse extends VigorStatus {
502
+ constructor(config) {
503
+ const base = {
504
+ target: VigorDefault,
505
+ settings: new VigorParseSettings()._getBase(),
506
+ strategies: new VigorParseStrategies()._getBase(),
507
+ interceptors: new VigorParseInterceptors()._getBase()
508
+ };
509
+ super(config, base, (c) => new VigorParse(c));
510
+ }
511
+ target(response) { return this._next({ target: response }); }
512
+ settings(func) {
513
+ if (typeof func === 'function') {
514
+ return this._next({ settings: func(new VigorParseSettings(this._config.settings))._getConfig() });
515
+ }
516
+ return this._next({ settings: func });
517
+ }
518
+ strategies(func) {
519
+ if (typeof func === 'function') {
520
+ return this._next({ strategies: func(new VigorParseStrategies(this._config.strategies))._getConfig() });
521
+ }
522
+ return this._next({ strategies: func });
523
+ }
524
+ interceptors(func) {
525
+ if (typeof func === 'function') {
526
+ return this._next({ interceptors: func(new VigorParseInterceptors(this._config.interceptors))._getConfig() });
317
527
  }
318
- const contentType = config.target.headers.get("Content-Type") || "";
319
- let strategy;
528
+ return this._next({ interceptors: func });
529
+ }
530
+ async request(config, timeline = []) {
531
+ const stats = this._mergeConfig(this._config, config);
532
+ const target = stats.target;
533
+ let ctx = {
534
+ timeline: timeline,
535
+ stats,
536
+ response: target,
537
+ result: VigorDefault,
538
+ error: VigorDefault,
539
+ };
540
+ const throwError = (err) => {
541
+ ctx.timeline.push({ action: "throwError called", content: err });
542
+ throw err;
543
+ };
320
544
  try {
321
- if (config.type) {
322
- strategy = { type: config.type };
323
- const parserRaw = config.target[config.type];
324
- if (typeof parserRaw !== 'function')
325
- throw new VigorParseError("INVALID_TYPE", {
326
- method: "request",
327
- type: "invalid_method",
328
- data: {
329
- received: config.type,
330
- expected: strategy?.type ?? "unknown"
331
- }
332
- });
333
- const parser = parserRaw.bind(config.target);
334
- if (!parser || typeof parser !== 'function')
335
- throw new VigorParseError("PARSE_FAILED", {
545
+ if (target === VigorDefault)
546
+ throw new VigorParseError("INVALID_TARGET", {
547
+ method: "request",
548
+ data: {
549
+ expected: ["Response"],
550
+ received: target
551
+ },
552
+ context: ctx
553
+ });
554
+ ctx.timeline.push({ action: "interceptor handling: before", content: stats.interceptors.before });
555
+ for (const func of stats.interceptors.before) {
556
+ await func(ctx, { throwError });
557
+ }
558
+ if (stats.settings.raw) {
559
+ ctx.result = ctx.response;
560
+ }
561
+ else {
562
+ let parsed = false;
563
+ for (const [i, func] of stats.strategies.funcs.length > 0
564
+ ? stats.strategies.funcs.entries()
565
+ : new VigorParseStrategies().contentType()._getConfig().funcs.entries()) {
566
+ const cloned = (i === stats.strategies.funcs.length - 1)
567
+ ? ctx.response
568
+ : ctx.response.clone();
569
+ try {
570
+ ctx.result = await func(cloned);
571
+ parsed = true;
572
+ break;
573
+ }
574
+ catch { }
575
+ }
576
+ if (!parsed)
577
+ throw new VigorParseError("PARSER_ALL_FAILED", {
336
578
  method: "request",
337
- type: "parse_failed",
338
579
  data: {
339
- expected: strategy?.type ?? "unknown"
340
- }
580
+ tried: stats.strategies.funcs,
581
+ response: ctx.response
582
+ },
583
+ context: ctx
341
584
  });
342
- return await parser();
343
585
  }
344
- strategy = VigorParse.stategy.find(i => i.key.test(contentType)) ?? VigorParse.stategy[0];
345
- return await strategy.parse(config.target);
586
+ const setResult = (unk) => {
587
+ ctx.timeline.push({ action: "setResult called", content: unk });
588
+ ctx.result = unk;
589
+ return unk;
590
+ };
591
+ ctx.timeline.push({ action: "interceptor handling: after", content: stats.interceptors.after });
592
+ for (const func of stats.interceptors.after) {
593
+ await func(ctx, { setResult, throwError });
594
+ }
595
+ ctx.timeline.push({ action: "interceptor handling: result", content: stats.interceptors.result });
596
+ for (const func of stats.interceptors.result) {
597
+ await func(ctx, { setResult, throwError });
598
+ }
599
+ return ctx.result;
346
600
  }
347
601
  catch (error) {
348
- if (error instanceof VigorParseError)
349
- throw error;
350
- throw new VigorParseError("PARSE_FAILED", {
351
- method: "request",
352
- type: "parse_failed",
353
- data: {
354
- expected: strategy?.type ?? "unknown"
355
- }
356
- });
602
+ ctx.error = error;
603
+ let overwritten = false;
604
+ const setResult = (unk) => {
605
+ ctx.timeline.push({ action: "setResult called", content: unk });
606
+ ctx.result = unk;
607
+ overwritten = true;
608
+ return unk;
609
+ };
610
+ ctx.timeline.push({ action: "interceptor handling: onError", content: stats.interceptors.onError });
611
+ for (const func of stats.interceptors.onError) {
612
+ await func(ctx, { setResult, throwError });
613
+ }
614
+ if (overwritten)
615
+ return ctx.result;
616
+ if (stats.settings.default !== VigorDefault)
617
+ return stats.settings.default;
618
+ throw error;
357
619
  }
358
620
  }
359
621
  }
360
622
  class VigorFetchSettings extends VigorStatus {
361
- constructor(config = {}) {
362
- super(config, {
363
- origin: "",
364
- path: [],
365
- query: {},
366
- unretry: [400, 401, 403, 404, 405, 413, 422],
623
+ constructor(config) {
624
+ const base = {
367
625
  retryHeaders: ["retry-after", "ratelimit-reset", "x-ratelimit-reset", "x-retry-after", "x-amz-retry-after", "chrome-proxy-next-link"],
368
- default: EMPTY
369
- });
626
+ unretryStatus: [400, 401, 403, 404, 405, 413, 422],
627
+ default: VigorDefault
628
+ };
629
+ super(config, base, (c) => new VigorFetchSettings(c));
370
630
  }
371
- origin(str) { return this._next({ origin: str }); }
372
- path(...strs) { return this._next({ path: [...this._config.path, ...strs.flat()] }); }
373
- query(obj) { return this._next({ query: { ...this._config.query, ...obj } }); }
374
- unretry(...numbers) { return this._next({ unretry: numbers.flat() }); }
375
- retryHeaders(...strs) { return this._next({ retryHeaders: [...this._config.retryHeaders, ...strs.flat()] }); }
376
- method(str) { return this._next({ method: str }); }
377
- headers(obj) { return this._next({ headers: obj }); }
378
- body(obj) { return this._next({ body: obj }); }
379
- options(obj) { return this._next({ options: obj }); }
380
- default(obj) { return this._next({ default: obj }); }
631
+ retryHeaders(...strs) { return this._next({ retryHeaders: strs.flat() }); }
632
+ unretryStatus(...nums) { return this._next({ unretryStatus: nums.flat() }); }
633
+ default(unk) { return this._next({ default: unk }); }
381
634
  }
382
635
  class VigorFetchInterceptors extends VigorStatus {
383
- constructor(config = {}) {
384
- super(config, {
636
+ constructor(config) {
637
+ const base = {
385
638
  before: [],
386
639
  after: [],
387
- onError: [],
388
- result: []
389
- });
640
+ result: [],
641
+ onError: []
642
+ };
643
+ super(config, base, (c) => new VigorFetchInterceptors(c));
390
644
  }
391
- before(...funcs) { return this._next({ before: [...this.getConfig().before, ...funcs.flat()] }); }
392
- after(...funcs) { return this._next({ after: [...this.getConfig().after, ...funcs.flat()] }); }
393
- onError(...funcs) { return this._next({ onError: [...this.getConfig().onError, ...funcs.flat()] }); }
394
- result(...funcs) { return this._next({ result: [...this.getConfig().result, ...funcs.flat()] }); }
645
+ before(...funcs) { return this._next({ before: funcs.flat() }); }
646
+ after(...funcs) { return this._next({ after: funcs.flat() }); }
647
+ result(...funcs) { return this._next({ result: funcs.flat() }); }
648
+ onError(...funcs) { return this._next({ onError: funcs.flat() }); }
395
649
  }
396
650
  class VigorFetch extends VigorStatus {
397
- constructor(config = {}) {
398
- super(config, {
399
- setting: new VigorFetchSettings().getBase(),
400
- retryConfig: new VigorRetry().getBase(),
401
- parseConfig: new VigorParse().getBase(),
402
- interceptors: new VigorFetchInterceptors().getBase(),
651
+ constructor(config) {
652
+ const base = {
653
+ origin: [],
654
+ path: [],
655
+ query: [],
656
+ hash: "",
657
+ options: {
658
+ headers: {},
659
+ body: VigorDefault
660
+ },
661
+ settings: new VigorFetchSettings()._getBase(),
662
+ interceptors: new VigorFetchInterceptors()._getBase(),
663
+ retryConfig: new VigorRetry()._getBase(),
664
+ parseConfig: new VigorParse()._getBase()
665
+ };
666
+ super(config, base, (c) => new VigorFetch(c));
667
+ }
668
+ _stringifyList(unkList) {
669
+ return unkList
670
+ .filter(unk => unk !== null && unk !== undefined)
671
+ .map(unk => {
672
+ if (unk instanceof Date)
673
+ return unk.toISOString();
674
+ return String(unk);
403
675
  });
404
676
  }
405
- origin(str) { return this._next({ setting: { ...this._config.setting, origin: str } }); }
406
- path(...strs) { return this._next({ setting: { ...this._config.setting, path: [...this._config.setting.path, ...strs.map(s => String(s)).flat()] } }); }
407
- query(obj) { return this._next({ setting: { ...this._config.setting, query: { ...this._config.setting.query, ...obj } } }); }
408
- method(str) { return this._next({ setting: { ...this._config.setting, method: str } }); }
409
- headers(obj) { return this._next({ setting: { ...this._config.setting, headers: obj } }); }
410
- body(obj) { return this._next({ setting: { ...this._config.setting, body: obj } }); }
411
- options(obj) { return this._next({ setting: { ...this._config.setting, options: obj } }); }
412
- setting(func) {
413
- return this._next({ setting: this._pipsub(this._config.setting, func, VigorFetchSettings) });
677
+ origin(...strs) { return this._next({ origin: this._stringifyList(strs.flat()) }); }
678
+ path(...strs) { return this._next({ path: this._stringifyList(strs.flat()) }); }
679
+ query(...strs) { return this._next({ query: strs.flat() }); }
680
+ hash(str) { return this._next({ hash: str }); }
681
+ options(obj) { return this._next({ options: obj }); }
682
+ headers(obj) { return this._next({ options: { headers: obj } }); }
683
+ body(obj) { return this._next({ options: { headers: this._config.options.headers, body: obj } }); }
684
+ _buildUrl(origin, path, query, hash) {
685
+ const originObj = new URL(origin[0]);
686
+ const baseStr = originObj.origin;
687
+ const pathObj = [originObj.pathname.replace(/^\/+|\/+$/g, '')];
688
+ for (const str of path) {
689
+ pathObj.push(str.replace(/^\/+|\/+$/g, ''));
690
+ }
691
+ const pathStr = pathObj.join('/');
692
+ const mainObj = new URL(pathStr, baseStr);
693
+ const parseVal = (val) => {
694
+ if (val instanceof Date)
695
+ return val.toISOString();
696
+ return String(val);
697
+ };
698
+ const queryObj = [...Array.from(originObj.searchParams.entries()), ...query.flatMap(qu => Object.entries(qu))];
699
+ for (const [key, val] of queryObj) {
700
+ if (val === undefined || val === null)
701
+ continue;
702
+ if (Array.isArray(val))
703
+ for (const e of val) {
704
+ mainObj.searchParams.append(key, parseVal(e));
705
+ }
706
+ else {
707
+ mainObj.searchParams.append(key, parseVal(val));
708
+ }
709
+ }
710
+ mainObj.hash = hash ?? originObj.hash;
711
+ return mainObj.href;
712
+ }
713
+ _normalizeOptions(body) {
714
+ if (body == null)
715
+ return { isJson: false, headers: {}, body };
716
+ if (typeof body === "string")
717
+ return { isJson: false, headers: {
718
+ "Content-Type": "text/plain;charset=UTF-8"
719
+ }, body };
720
+ if (body instanceof Blob)
721
+ return { isJson: false, headers: {
722
+ ...(body.type && { "Content-Type": body.type })
723
+ }, body };
724
+ if (body instanceof ArrayBuffer)
725
+ return { isJson: false, headers: {
726
+ "Content-Type": "application/octet-stream"
727
+ }, body };
728
+ if (body instanceof URLSearchParams)
729
+ return { isJson: false, headers: {
730
+ "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
731
+ }, body };
732
+ if (body instanceof FormData)
733
+ return { isJson: false, headers: {}, body };
734
+ if (typeof body === "object") {
735
+ return { isJson: true, headers: {
736
+ "Content-Type": "application/json"
737
+ }, body: JSON.stringify(body) };
738
+ }
739
+ throw new VigorFetchError("INVALID_BODY", {
740
+ method: "_normalizeBody",
741
+ data: {
742
+ expected: ["string", "Blob", "ArrayBuffer", "URLSearchParams", "FormData"],
743
+ received: body
744
+ }
745
+ });
746
+ }
747
+ settings(func) {
748
+ if (typeof func === 'function') {
749
+ return this._next({ settings: func(new VigorFetchSettings(this._config.settings))._getConfig() });
750
+ }
751
+ return this._next({ settings: func });
414
752
  }
415
753
  interceptors(func) {
416
- return this._next({ interceptors: this._pipsub(this._config.interceptors, func, VigorFetchInterceptors) });
754
+ if (typeof func === 'function') {
755
+ return this._next({ interceptors: func(new VigorFetchInterceptors(this._config.interceptors))._getConfig() });
756
+ }
757
+ return this._next({ interceptors: func });
417
758
  }
418
759
  retryConfig(func) {
419
- return this._next({ retryConfig: this._pipsub(this._config.retryConfig, func, VigorRetry) });
760
+ if (typeof func === 'function') {
761
+ return this._next({ retryConfig: func(new VigorRetry(this._config.retryConfig))._getConfig() });
762
+ }
763
+ return this._next({ retryConfig: func });
420
764
  }
421
765
  parseConfig(func) {
422
- return this._next({ parseConfig: this._pipsub(this._config.parseConfig, func, VigorParse) });
423
- }
424
- buildUrl(origin, path, query) {
425
- if (!origin)
426
- throw new VigorFetchError("INVALID_URL", {
427
- method: "buildUrl",
428
- data: {
429
- received: origin
430
- }
431
- });
432
- const url = new URL(origin);
433
- const segments = [
434
- url.pathname,
435
- ...path
436
- ]
437
- .flat()
438
- .filter(Boolean)
439
- .flatMap(p => p.split('/'))
440
- .filter(Boolean);
441
- url.pathname = '/' + segments.join('/');
442
- const params = new URLSearchParams(url.search);
443
- for (const [k, v] of Object.entries(query ?? {})) {
444
- if (v == null)
445
- continue;
446
- if (Array.isArray(v)) {
447
- v.forEach(i => params.append(k, String(i)));
448
- }
449
- else {
450
- params.set(k, String(v));
451
- }
766
+ if (typeof func === 'function') {
767
+ return this._next({ parseConfig: func(new VigorParse(this._config.parseConfig))._getConfig() });
452
768
  }
453
- url.search = params.toString();
454
- return url.toString();
769
+ return this._next({ parseConfig: func });
455
770
  }
456
- async request() {
457
- const config = this._config;
771
+ async request(config, timeline = []) {
772
+ const stats = this._mergeConfig(this._config, config);
458
773
  let ctx = {
459
- setting: { ...config.setting },
460
- retryConfig: {
461
- ...config.retryConfig,
462
- interceptors: {
463
- before: [...config.retryConfig.interceptors.before],
464
- after: [...config.retryConfig.interceptors.after],
465
- onError: [...config.retryConfig.interceptors.onError],
466
- onRetry: [...config.retryConfig.interceptors.onRetry],
467
- retryIf: [...config.retryConfig.interceptors.retryIf],
468
- }
774
+ href: "",
775
+ result: VigorDefault,
776
+ response: VigorDefault,
777
+ options: {
778
+ headers: VigorDefault,
779
+ body: VigorDefault
469
780
  },
470
- parseConfig: {
471
- ...config.parseConfig
472
- },
473
- interceptors: {
474
- before: [...config.interceptors.before],
475
- after: [...config.interceptors.after],
476
- onError: [...config.interceptors.onError],
477
- result: [...config.interceptors.result]
478
- },
479
- runtime: {
480
- result: EMPTY
481
- }
781
+ error: VigorDefault,
782
+ timeline: timeline,
783
+ stats,
784
+ };
785
+ const throwError = (err) => {
786
+ ctx.timeline.push({ action: "throwError called", content: err });
787
+ throw err;
482
788
  };
483
- const throwError = (error) => { throw error; };
484
789
  try {
485
- ctx.runtime.unretrySet = new Set(ctx.setting.unretry);
486
- if (!/^(https?|data|blob|file|about):\/\//.test(ctx.setting.origin))
790
+ try {
791
+ new URL(stats.origin[0]);
792
+ }
793
+ catch {
487
794
  throw new VigorFetchError("INVALID_PROTOCOL", {
488
795
  method: "request",
489
796
  data: {
490
- expected: ["http", "https", "data", "blob", "file", "about"],
491
- received: ctx.setting.origin
797
+ expected: ["valid URL protocol"],
798
+ received: stats.origin
492
799
  }
493
800
  });
494
- ctx.runtime.url = this.buildUrl(config.setting.origin, config.setting.path, config.setting.query);
495
- const isJson = Array.isArray(ctx.setting.body) || (!!ctx.setting.body && Object.getPrototypeOf(ctx.setting.body) === Object.prototype);
496
- ctx.runtime.baseOptions = {
497
- method: ctx.setting.method || (ctx.setting.body ? "POST" : "GET"),
498
- headers: { ...(isJson && { "Content-Type": "application/json" }), ...ctx.setting.headers },
499
- ...(ctx.setting.body && { body: isJson ? JSON.stringify(ctx.setting.body) : ctx.setting.body }),
500
- ...ctx.setting.options,
501
- signal: null
801
+ }
802
+ ctx.href = this._buildUrl(stats.origin, stats.path, stats.query, stats.hash);
803
+ const { headers, body, ...others } = stats.options;
804
+ ctx.options = {
805
+ ...others,
806
+ headers: {}
502
807
  };
503
- const target = async (ctx2, { signal }) => {
504
- ctx.runtime.options = {
505
- ...ctx.runtime.baseOptions,
506
- signal
507
- };
508
- const response = await fetch(ctx.runtime.url, ctx.runtime.options);
509
- return response;
808
+ const hasBody = body !== VigorDefault &&
809
+ body !== undefined;
810
+ if (hasBody) {
811
+ const normalized = this._normalizeOptions(body);
812
+ if (normalized.body !== undefined) {
813
+ ctx.options.body = normalized.body;
814
+ }
815
+ Object.assign(ctx.options.headers, normalized.headers);
816
+ }
817
+ Object.assign(ctx.options.headers, headers);
818
+ ctx.timeline.push({ action: "options set", content: ctx.options });
819
+ const setOptions = (unk) => {
820
+ ctx.timeline.push({ action: "setOptions called", content: unk });
821
+ return ctx.options = unk;
822
+ };
823
+ const setHeaders = (unk) => {
824
+ ctx.timeline.push({ action: "setHeaders called", content: unk });
825
+ return ctx.options.headers = unk;
826
+ };
827
+ const setBody = (unk) => {
828
+ ctx.timeline.push({ action: "setBody called", content: unk });
829
+ return ctx.options.body = unk;
510
830
  };
511
- const checkOk = async (ctx2, { throwError }) => {
512
- const result = ctx2.runtime.result;
513
- if (!result.ok)
514
- return throwError?.(new VigorFetchError("FETCH_ERROR", {
831
+ const fetchTask = async (ctx2, { abort, signal }) => {
832
+ ctx.options.signal = signal;
833
+ const result = await fetch(ctx.href, ctx.options);
834
+ return result;
835
+ };
836
+ const throwStatus = async (ctx2, api) => {
837
+ const response = ctx2.result;
838
+ if (!response.ok) {
839
+ api.throwError(new VigorFetchError("FETCH_FAILED", {
515
840
  method: "request",
516
- type: "fetch_error",
517
841
  data: {
518
- status: result.status,
519
- statusText: result.statusText,
520
- url: result.url
842
+ status: response.status,
843
+ response: response,
844
+ url: response.url,
845
+ headers: response.headers,
846
+ body: response.body,
847
+ statusText: response.statusText
521
848
  }
522
849
  }));
850
+ }
523
851
  };
524
- const handleBlacklist = (ctx2, { cancelRetry }) => {
525
- const result = ctx2.runtime.result;
526
- if (!result?.status || ctx.runtime.unretrySet.has(result.status))
527
- cancelRetry?.();
852
+ const handleBlacklist = async (ctx2, api) => {
853
+ const response = ctx2.result;
854
+ ctx.error = ctx2.error;
855
+ if (response instanceof Response) {
856
+ if (stats.settings.unretryStatus.includes(response.status))
857
+ api.cancelRetry();
858
+ else
859
+ api.proceedRetry();
860
+ }
528
861
  };
529
- const handle429 = (ctx2, { setDelay }) => {
530
- const result = ctx2.runtime.result;
531
- if (result?.status === 429) {
532
- let rHeader = null;
533
- ctx.setting.retryHeaders.some(h => (rHeader = result.headers.get(h)));
534
- if (rHeader) {
535
- setDelay?.(isNaN(Number(rHeader)) ? new Date(rHeader).getTime() - Date.now() : Number(rHeader) * 1000) + VigorRetryBackoff.randomJitter(ctx.retryConfig.backoff.jitter);
862
+ const handleRatelimit = async (ctx2, api) => {
863
+ const response = ctx2.result;
864
+ ctx.error = ctx2.error;
865
+ if (response instanceof Response) {
866
+ if (response.status === 429) {
867
+ let retryHeader = null;
868
+ for (const header of stats.settings.retryHeaders) {
869
+ retryHeader = response.headers.get(header);
870
+ if (retryHeader)
871
+ break;
872
+ }
873
+ if (retryHeader) {
874
+ const toNumber = Number(retryHeader);
875
+ const delay = !isNaN(toNumber)
876
+ ? toNumber * 1000
877
+ : (() => {
878
+ const toDate = new Date(retryHeader).getTime();
879
+ return !isNaN(toDate)
880
+ ? toDate - Date.now()
881
+ : null;
882
+ })();
883
+ if (delay !== null && delay > 0)
884
+ api.setDelay(delay + Math.random() * ctx2.stats.settings.jitter);
885
+ }
536
886
  }
537
887
  }
538
888
  };
539
- ctx.retryConfig.target = target;
540
- ctx.retryConfig.interceptors.after.unshift(checkOk);
541
- ctx.retryConfig.interceptors.retryIf.unshift(handleBlacklist);
542
- ctx.retryConfig.interceptors.onRetry.unshift(handle429);
543
- ctx.runtime.retryEngine = new VigorRetry(ctx.retryConfig);
544
- ctx.runtime.parseEngine = new VigorParse(ctx.parseConfig);
545
- const setOptions = (obj) => ctx.runtime.baseOptions = obj;
546
- for (const func of ctx.interceptors.before) {
547
- await func(ctx, { setOptions, throwError });
889
+ stats.retryConfig.interceptors.after.unshift(throwStatus);
890
+ stats.retryConfig.interceptors.retryIf.unshift(handleBlacklist);
891
+ stats.retryConfig.interceptors.onRetry.unshift(handleRatelimit);
892
+ const retryEngine = new VigorRetry(stats.retryConfig)
893
+ .target(fetchTask);
894
+ const parseEngine = new VigorParse(stats.parseConfig);
895
+ ctx.timeline.push({ action: "interceptor handling: before", content: stats.interceptors.before });
896
+ for (const func of stats.interceptors.before) {
897
+ await func(ctx, { throwError, setOptions, setHeaders, setBody });
548
898
  }
549
- ctx.runtime.response = await ctx.runtime.retryEngine.request();
550
- for (const func of ctx.interceptors.after) {
551
- await func(ctx, { throwError });
899
+ ctx.response = await retryEngine.request(undefined, timeline);
900
+ ctx.result = await parseEngine.target(ctx.response).request(undefined, timeline);
901
+ const setResult = (unk) => {
902
+ ctx.timeline.push({ action: "setResult called", content: unk });
903
+ ctx.result = unk;
904
+ return unk;
905
+ };
906
+ ctx.timeline.push({ action: "interceptor handling: after", content: stats.interceptors.after });
907
+ for (const func of stats.interceptors.after) {
908
+ await func(ctx, { setResult, throwError });
552
909
  }
553
- ctx.runtime.result = await ctx.runtime.parseEngine?.target(ctx.runtime.response).request();
554
- const setResult = (result) => ctx.runtime.result = result;
555
- for (const func of ctx.interceptors.result) {
910
+ ctx.timeline.push({ action: "interceptor handling: result", content: stats.interceptors.result });
911
+ for (const func of stats.interceptors.result) {
556
912
  await func(ctx, { setResult, throwError });
557
913
  }
558
- return ctx.runtime.result;
914
+ return ctx.result;
559
915
  }
560
916
  catch (error) {
561
- ctx.runtime.error = error;
562
- let overrided = false;
563
- const setResult = (result) => { overrided = true; return (ctx.runtime.result = result); };
564
- for (const func of ctx.interceptors.onError) {
565
- await func(ctx, { setResult, throwError });
917
+ ctx.error = error;
918
+ let overwritten = false;
919
+ const setResult = (unk) => {
920
+ ctx.timeline.push({ action: "setResult called", content: unk });
921
+ ctx.result = unk;
922
+ overwritten = true;
923
+ return unk;
924
+ };
925
+ let restarted = false;
926
+ const restart = () => {
927
+ ctx.timeline.push({ action: "restart called" });
928
+ restarted = true;
929
+ };
930
+ ctx.timeline.push({ action: "interceptor handling: onError", content: stats.interceptors.onError });
931
+ for (const func of stats.interceptors.onError) {
932
+ await func(ctx, { setResult, throwError, restart });
566
933
  }
567
- if (overrided && ctx.runtime.result !== EMPTY)
568
- return ctx.runtime.result;
569
- if (ctx.setting.default !== EMPTY)
570
- return ctx.setting.default;
934
+ if (restarted) {
935
+ return await this.request(stats, timeline);
936
+ }
937
+ if (overwritten)
938
+ return ctx.result;
939
+ if (stats.settings.default !== VigorDefault)
940
+ return stats.settings.default;
571
941
  throw error;
572
942
  }
573
943
  }
574
944
  }
575
945
  class VigorAllSettings extends VigorStatus {
576
- constructor(config = {}) {
577
- super(config, {
946
+ constructor(config) {
947
+ const base = {
578
948
  concurrency: 5,
579
- jitter: 1000,
580
949
  onlySuccess: false
581
- });
950
+ };
951
+ super(config, base, (c) => new VigorAllSettings(c));
582
952
  }
583
953
  concurrency(num) { return this._next({ concurrency: num }); }
584
- jitter(num) { return this._next({ jitter: num }); }
585
- onlySuccess(bool) { return this._next({ onlySuccess: bool }); }
954
+ onlySuccess(num) { return this._next({ onlySuccess: num }); }
586
955
  }
587
956
  class VigorAllInterceptors extends VigorStatus {
588
- constructor(config = {}) {
589
- super(config, {
957
+ constructor(config) {
958
+ const base = {
590
959
  before: [],
591
960
  after: [],
592
- onError: [],
593
- result: []
594
- });
961
+ result: [],
962
+ onError: []
963
+ };
964
+ super(config, base, (c) => new VigorAllInterceptors(c));
595
965
  }
596
- before(...funcs) { return this._next({ before: [...this.getConfig().before, ...funcs.flat()] }); }
597
- after(...funcs) { return this._next({ after: [...this.getConfig().after, ...funcs.flat()] }); }
598
- onError(...funcs) { return this._next({ onError: [...this.getConfig().onError, ...funcs.flat()] }); }
599
- result(...funcs) { return this._next({ result: [...this.getConfig().result, ...funcs.flat()] }); }
966
+ before(...funcs) { return this._next({ before: funcs.flat() }); }
967
+ after(...funcs) { return this._next({ after: funcs.flat() }); }
968
+ result(...funcs) { return this._next({ result: funcs.flat() }); }
969
+ onError(...funcs) { return this._next({ onError: funcs.flat() }); }
600
970
  }
601
971
  class VigorAll extends VigorStatus {
602
- constructor(config = {}) {
603
- super(config, {
972
+ constructor(config) {
973
+ const base = {
604
974
  target: [],
605
- setting: new VigorAllSettings().getBase(),
606
- interceptors: new VigorAllInterceptors().getBase()
607
- });
608
- }
609
- _transfer(config) {
610
- return new VigorAll({
611
- ...this._config,
612
- ...config
613
- });
614
- }
615
- target(...args) {
616
- const flat = args.flat();
617
- return this._transfer({ target: flat });
975
+ settings: new VigorAllSettings()._getBase(),
976
+ interceptors: new VigorAllInterceptors()._getBase()
977
+ };
978
+ super(config, base, (c) => new VigorAll(c));
618
979
  }
619
- setting(func) {
620
- return this._next({
621
- setting: this._pipsub(this._config.setting, func, VigorAllSettings)
622
- });
980
+ target(...funcs) { return this._next({ target: funcs.flat() }); }
981
+ settings(func) {
982
+ if (typeof func === 'function') {
983
+ return this._next({ settings: func(new VigorAllSettings(this._config.settings))._getConfig() });
984
+ }
985
+ return this._next({ settings: func });
623
986
  }
624
987
  interceptors(func) {
625
- return this._next({
626
- interceptors: this._pipsub(this._config.interceptors, func, VigorAllInterceptors)
627
- });
988
+ if (typeof func === 'function') {
989
+ return this._next({ interceptors: func(new VigorAllInterceptors(this._config.interceptors))._getConfig() });
990
+ }
991
+ return this._next({ interceptors: func });
628
992
  }
629
- async request() {
630
- const config = this._config;
993
+ async runTask(task, { stats, root }, semaphore) {
631
994
  let ctx = {
632
- setting: { ...config.setting },
633
- target: [...config.target],
634
- interceptors: {
635
- before: [...config.interceptors.before],
636
- after: [...config.interceptors.after],
637
- onError: [...config.interceptors.onError],
638
- result: [...config.interceptors.result],
639
- },
640
- runtime: {
641
- tasks: [],
642
- result: [],
643
- }
995
+ result: VigorDefault,
996
+ error: VigorDefault,
997
+ timeline: [],
998
+ stats,
999
+ root,
1000
+ target: task,
1001
+ semaphore
644
1002
  };
645
- if (ctx.target.length == 0)
646
- throw new VigorAllError("TARGET_MISSING", {
647
- method: "request",
648
- data: undefined
649
- });
650
- let active = 0;
651
- const queue = [];
652
- const runTask = async (task) => {
653
- await new Promise(resolve => {
654
- if (active < config.setting.concurrency) {
655
- active++;
656
- resolve();
657
- }
658
- else {
659
- queue.push(() => {
660
- active++;
661
- resolve();
662
- });
663
- }
664
- });
665
- const throwError = (error) => { throw error; };
666
- let ctxTask = {
667
- target: task,
668
- runtime: {
669
- result: EMPTY,
670
- error: null,
671
- jitter: VigorRetryBackoff.randomJitter(config.setting.jitter)
672
- }
673
- };
1003
+ const throwError = (err) => {
1004
+ ctx.timeline.push({ action: "throwError called", content: err });
1005
+ throw err;
1006
+ };
1007
+ try {
674
1008
  try {
675
- await new Promise(resolve => setTimeout(resolve, ctxTask.runtime.jitter));
676
- for (const func of config.interceptors.before) {
677
- await func(ctxTask, { throwError });
1009
+ await semaphore.acquire();
1010
+ ctx.timeline.push({ action: "task acquired", content: ctx.target });
1011
+ ctx.timeline.push({ action: "interceptor handling: before", content: stats.interceptors.before });
1012
+ for (const func of stats.interceptors.before) {
1013
+ await func(ctx, { throwError });
678
1014
  }
679
- ctxTask.runtime.result = await task(ctxTask, {});
680
- const setResult = (result) => ctxTask.runtime.result = result;
681
- for (const func of config.interceptors.after) {
682
- await func(ctxTask, { setResult, throwError });
683
- }
684
- if (ctxTask.runtime.result === EMPTY) {
685
- throw new VigorAllError("RESULT_NOT_SET", {
686
- method: "request",
687
- data: undefined
688
- });
689
- }
690
- return ctxTask.runtime.result;
1015
+ ctx.timeline.push({ action: "task started", content: ctx.target });
1016
+ ctx.result = await task(ctx);
691
1017
  }
692
- catch (error) {
693
- ctxTask.runtime.error = error;
694
- let overrided = false;
695
- const setResult = (result) => {
696
- overrided = true;
697
- return (ctxTask.runtime.result = result);
1018
+ finally {
1019
+ ctx.timeline.push({ action: "task ended", content: ctx.target });
1020
+ const setResult = (unk) => {
1021
+ ctx.timeline.push({ action: "setResult called", content: unk });
1022
+ ctx.result = unk;
1023
+ return unk;
698
1024
  };
699
- for (const func of config.interceptors.onError) {
700
- await func(ctxTask, { setResult, throwError });
1025
+ ctx.timeline.push({ action: "interceptor handling: after", content: stats.interceptors.after });
1026
+ for (const func of stats.interceptors.after) {
1027
+ await func(ctx, { setResult, throwError });
701
1028
  }
702
- if (overrided && ctxTask.runtime.result !== EMPTY)
703
- return ctxTask.runtime.result;
704
- throw ctxTask.runtime.error;
1029
+ semaphore.release();
1030
+ ctx.timeline.push({ action: "task released", content: ctx.target });
1031
+ return ctx.result;
705
1032
  }
706
- finally {
707
- active--;
708
- const next = queue.shift();
709
- if (next)
710
- next();
1033
+ }
1034
+ catch (error) {
1035
+ ctx.error = error;
1036
+ let overwritten = false;
1037
+ const setResult = (unk) => {
1038
+ ctx.timeline.push({ action: "setResult called", content: unk });
1039
+ ctx.result = unk;
1040
+ overwritten = true;
1041
+ return unk;
1042
+ };
1043
+ ctx.timeline.push({ action: "interceptor handling: onError", content: stats.interceptors.onError });
1044
+ for (const func of stats.interceptors.onError) {
1045
+ await func(ctx, { setResult, throwError });
711
1046
  }
1047
+ if (overwritten)
1048
+ return ctx.result;
1049
+ throw error;
1050
+ }
1051
+ }
1052
+ async request(config, timeline = []) {
1053
+ const stats = this._mergeConfig(this._config, config);
1054
+ let ctx = {
1055
+ result: VigorDefault,
1056
+ timeline,
1057
+ stats,
1058
+ queue: new Set()
712
1059
  };
713
- ctx.runtime.tasks = ctx.target.map(task => runTask(task));
714
- const settled = await Promise.allSettled(ctx.runtime.tasks);
715
- const isFailed = Symbol("FAILED");
716
- ctx.runtime.result = settled.map((res, idx) => {
717
- if (res.status === "fulfilled")
718
- return res.value;
719
- if (ctx.setting.onlySuccess)
720
- return isFailed;
721
- return new VigorAllError("REQUEST_FAILED", {
1060
+ if (stats.target.length === 0)
1061
+ throw new VigorAllError("EMPTY_TARGET", {
722
1062
  method: "request",
723
- data: {
724
- index: idx,
725
- error: normalizeError(res?.reason || "unknown")
726
- }
1063
+ data: {}
727
1064
  });
728
- }).filter(i => i !== isFailed);
729
- const setResult = (result) => ctx.runtime.result = result;
730
- const throwError = (error) => { throw error; };
731
- for (const func of config.interceptors.result) {
1065
+ const waitQueue = [];
1066
+ for (const task of stats.target) {
1067
+ const acquire = () => {
1068
+ if (ctx.queue.size < stats.settings.concurrency) {
1069
+ return Promise.resolve();
1070
+ }
1071
+ return new Promise((res) => waitQueue.push(res));
1072
+ };
1073
+ const release = () => {
1074
+ if (waitQueue.length > 0) {
1075
+ const next = waitQueue.shift();
1076
+ if (next)
1077
+ next();
1078
+ }
1079
+ };
1080
+ acquire();
1081
+ let promise;
1082
+ promise = this.runTask(task, { stats, root: ctx }, { acquire, release }).then(res => {
1083
+ ctx.queue.delete(promise);
1084
+ return { success: true, value: res };
1085
+ }).catch(err => ({ success: false, value: err }));
1086
+ ctx.queue.add(promise);
1087
+ }
1088
+ const raw = await Promise.all(ctx.queue);
1089
+ ctx.result = stats.settings.onlySuccess
1090
+ ? raw.filter(r => r.success).map(r => r.value)
1091
+ : raw.map(r => r.value);
1092
+ const setResult = (unk) => {
1093
+ ctx.timeline.push({ action: "setResult called", content: unk });
1094
+ ctx.result = unk;
1095
+ return unk;
1096
+ };
1097
+ const throwError = (err) => {
1098
+ ctx.timeline.push({ action: "throwError called", content: err });
1099
+ throw err;
1100
+ };
1101
+ ctx.timeline.push({ action: "interceptor handling: result", content: stats.interceptors.result });
1102
+ for (const func of stats.interceptors.result) {
732
1103
  await func(ctx, { setResult, throwError });
733
1104
  }
734
- return ctx.runtime.result;
1105
+ return ctx.result;
735
1106
  }
736
1107
  }
737
- class Vigor {
738
- registry;
739
- constructor(config) {
740
- const defaultRegistry = {
741
- VigorRetry: {
742
- main: () => new VigorRetry(),
743
- error: VigorRetryError,
744
- setting: VigorRetrySettings,
745
- interceptors: VigorRetryInterceptors,
746
- backoff: VigorRetryBackoff,
747
- },
748
- VigorFetch: {
749
- main: () => new VigorFetch(),
750
- error: VigorFetchError,
751
- setting: VigorFetchSettings,
752
- interceptors: VigorFetchInterceptors,
753
- },
754
- VigorAll: {
755
- main: () => new VigorAll(),
756
- error: VigorAllError,
757
- setting: VigorAllSettings,
758
- interceptors: VigorAllInterceptors,
759
- },
760
- VigorParse: {
761
- main: () => new VigorParse(),
762
- error: VigorParseError,
763
- }
764
- };
765
- this.registry = config?.registry ?? defaultRegistry;
766
- }
767
- fetch(origin) {
768
- return this.registry.VigorFetch.main().origin(origin);
769
- }
770
- all(...tasks) {
771
- return this.registry.VigorAll
772
- .main()
773
- .target(...tasks);
774
- }
775
- parse(response) {
776
- return this.registry.VigorParse.main().target(response);
777
- }
778
- retry(fn) {
779
- return this.registry.VigorRetry.main().target(fn);
1108
+ const VigorEntry = {
1109
+ retry: {
1110
+ main: VigorRetry,
1111
+ settings: VigorRetrySettings,
1112
+ interceptors: VigorRetryInterceptors,
1113
+ error: VigorRetryError,
1114
+ algorithms: {
1115
+ constant: VigorRetryAlgorithmsConstant,
1116
+ linear: VigorRetryAlgorithmsLinear,
1117
+ backoff: VigorRetryAlgorithmsBackoff,
1118
+ custom: VigorRetryAlgorithmsCustom
1119
+ }
1120
+ },
1121
+ parse: {
1122
+ main: VigorParse,
1123
+ settings: VigorParseSettings,
1124
+ interceptors: VigorParseInterceptors,
1125
+ error: VigorParseError,
1126
+ strategies: VigorParseStrategies
1127
+ },
1128
+ fetch: {
1129
+ main: VigorFetch,
1130
+ settings: VigorFetchSettings,
1131
+ interceptors: VigorFetchInterceptors,
1132
+ error: VigorFetchError,
1133
+ },
1134
+ all: {
1135
+ main: VigorAll,
1136
+ settings: VigorAllSettings,
1137
+ interceptors: VigorAllInterceptors,
1138
+ error: VigorAllError
780
1139
  }
781
- use(plugin, options) {
782
- const nextRegistry = {
783
- ...this.registry,
784
- VigorFetch: {
785
- ...this.registry.VigorFetch
786
- },
787
- VigorRetry: {
788
- ...this.registry.VigorRetry
789
- },
790
- VigorAll: {
791
- ...this.registry.VigorAll
792
- },
793
- VigorParse: {
794
- ...this.registry.VigorParse
795
- }
796
- };
797
- plugin(nextRegistry, options);
798
- return new Vigor({
799
- registry: nextRegistry
800
- });
1140
+ };
1141
+ const vigor = {
1142
+ use: async (func, config) => {
1143
+ return await func(VigorEntry, config);
1144
+ },
1145
+ fetch: (...strs) => {
1146
+ return new VigorFetch().origin(...strs);
1147
+ },
1148
+ retry: (target) => {
1149
+ return new VigorRetry().target(target);
1150
+ },
1151
+ parse: (response) => {
1152
+ return new VigorParse().target(response);
1153
+ },
1154
+ all: (...funcs) => {
1155
+ return new VigorAll().target(...funcs);
1156
+ },
1157
+ builder: {
1158
+ fetch: {
1159
+ settings: (c) => new VigorFetchSettings(c),
1160
+ interceptors: (c) => new VigorFetchInterceptors(c),
1161
+ },
1162
+ retry: {
1163
+ settings: (c) => new VigorRetrySettings(c),
1164
+ interceptors: (c) => new VigorRetryInterceptors(c),
1165
+ },
1166
+ parse: {
1167
+ settings: (c) => new VigorParseSettings(c),
1168
+ interceptors: (c) => new VigorParseInterceptors(c),
1169
+ },
1170
+ all: {
1171
+ settings: (c) => new VigorAllSettings(c),
1172
+ interceptors: (c) => new VigorAllInterceptors(c),
1173
+ }
801
1174
  }
802
- }
803
- const vigor = new Vigor();
1175
+ };
804
1176
 
805
- exports.Vigor = Vigor;
806
- exports.VigorAll = VigorAll;
807
- exports.VigorAllError = VigorAllError;
808
- exports.VigorAllInterceptors = VigorAllInterceptors;
809
- exports.VigorAllSettings = VigorAllSettings;
810
- exports.VigorFetch = VigorFetch;
811
- exports.VigorFetchError = VigorFetchError;
812
- exports.VigorFetchInterceptors = VigorFetchInterceptors;
813
- exports.VigorFetchSettings = VigorFetchSettings;
814
- exports.VigorParse = VigorParse;
815
- exports.VigorParseError = VigorParseError;
816
- exports.VigorRetry = VigorRetry;
817
- exports.VigorRetryBackoff = VigorRetryBackoff;
818
- exports.VigorRetryError = VigorRetryError;
819
- exports.VigorRetryInterceptors = VigorRetryInterceptors;
820
- exports.VigorRetrySettings = VigorRetrySettings;
1177
+ exports.VigorEntry = VigorEntry;
821
1178
  exports.default = vigor;
822
1179
  exports.vigor = vigor;