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