vigor-fetch 4.0.3 → 4.0.5
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.cjs +1963 -0
- package/dist/index.d.cts +4208 -0
- package/dist/index.d.ts +487 -1596
- package/dist/index.js +1790 -1892
- package/package.json +11 -16
- package/dist/index.mjs +0 -1927
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1963 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
VigorAll: () => VigorAll,
|
|
24
|
+
VigorAllBase: () => VigorAllBase,
|
|
25
|
+
VigorAllError: () => VigorAllError,
|
|
26
|
+
VigorAllErrorMessageFuncs: () => VigorAllErrorMessageFuncs,
|
|
27
|
+
VigorAllPolicyBase: () => VigorAllPolicyBase,
|
|
28
|
+
VigorAllPolicyMiddlewares: () => VigorAllPolicyMiddlewares,
|
|
29
|
+
VigorAllPolicyMiddlewaresBase: () => VigorAllPolicyMiddlewaresBase,
|
|
30
|
+
VigorAllPolicySettings: () => VigorAllPolicySettings,
|
|
31
|
+
VigorAllPolicySettingsBase: () => VigorAllPolicySettingsBase,
|
|
32
|
+
VigorError: () => VigorError,
|
|
33
|
+
VigorFetch: () => VigorFetch,
|
|
34
|
+
VigorFetchBase: () => VigorFetchBase,
|
|
35
|
+
VigorFetchError: () => VigorFetchError,
|
|
36
|
+
VigorFetchErrorMessageFuncs: () => VigorFetchErrorMessageFuncs,
|
|
37
|
+
VigorFetchPolicyBase: () => VigorFetchPolicyBase,
|
|
38
|
+
VigorFetchPolicyMiddlewares: () => VigorFetchPolicyMiddlewares,
|
|
39
|
+
VigorFetchPolicyMiddlewaresBase: () => VigorFetchPolicyMiddlewaresBase,
|
|
40
|
+
VigorFetchPolicySettings: () => VigorFetchPolicySettings,
|
|
41
|
+
VigorFetchPolicySettingsBase: () => VigorFetchPolicySettingsBase,
|
|
42
|
+
VigorJitter: () => VigorJitter,
|
|
43
|
+
VigorParse: () => VigorParse,
|
|
44
|
+
VigorParseBase: () => VigorParseBase,
|
|
45
|
+
VigorParseContentTypeStrategy: () => VigorParseContentTypeStrategy,
|
|
46
|
+
VigorParseError: () => VigorParseError,
|
|
47
|
+
VigorParseErrorMessageFuncs: () => VigorParseErrorMessageFuncs,
|
|
48
|
+
VigorParsePolicyBase: () => VigorParsePolicyBase,
|
|
49
|
+
VigorParsePolicyMiddlewares: () => VigorParsePolicyMiddlewares,
|
|
50
|
+
VigorParsePolicyMiddlewaresBase: () => VigorParsePolicyMiddlewaresBase,
|
|
51
|
+
VigorParsePolicySettings: () => VigorParsePolicySettings,
|
|
52
|
+
VigorParsePolicySettingsBase: () => VigorParsePolicySettingsBase,
|
|
53
|
+
VigorParsePolicyStrategies: () => VigorParsePolicyStrategies,
|
|
54
|
+
VigorParsePolicyStrategiesBase: () => VigorParsePolicyStrategiesBase,
|
|
55
|
+
VigorParseSniffStrategy: () => VigorParseSniffStrategy,
|
|
56
|
+
VigorRetry: () => VigorRetry,
|
|
57
|
+
VigorRetryBase: () => VigorRetryBase,
|
|
58
|
+
VigorRetryError: () => VigorRetryError,
|
|
59
|
+
VigorRetryErrorMessageFuncs: () => VigorRetryErrorMessageFuncs,
|
|
60
|
+
VigorRetryPolicyAlgorithms: () => VigorRetryPolicyAlgorithms,
|
|
61
|
+
VigorRetryPolicyAlgorithmsBackoff: () => VigorRetryPolicyAlgorithmsBackoff,
|
|
62
|
+
VigorRetryPolicyAlgorithmsBackoffBase: () => VigorRetryPolicyAlgorithmsBackoffBase,
|
|
63
|
+
VigorRetryPolicyAlgorithmsBase: () => VigorRetryPolicyAlgorithmsBase,
|
|
64
|
+
VigorRetryPolicyAlgorithmsConstant: () => VigorRetryPolicyAlgorithmsConstant,
|
|
65
|
+
VigorRetryPolicyAlgorithmsConstantBase: () => VigorRetryPolicyAlgorithmsConstantBase,
|
|
66
|
+
VigorRetryPolicyAlgorithmsCustom: () => VigorRetryPolicyAlgorithmsCustom,
|
|
67
|
+
VigorRetryPolicyAlgorithmsCustomBase: () => VigorRetryPolicyAlgorithmsCustomBase,
|
|
68
|
+
VigorRetryPolicyAlgorithmsLinear: () => VigorRetryPolicyAlgorithmsLinear,
|
|
69
|
+
VigorRetryPolicyAlgorithmsLinearBase: () => VigorRetryPolicyAlgorithmsLinearBase,
|
|
70
|
+
VigorRetryPolicyBase: () => VigorRetryPolicyBase,
|
|
71
|
+
VigorRetryPolicyMiddlewares: () => VigorRetryPolicyMiddlewares,
|
|
72
|
+
VigorRetryPolicyMiddlewaresBase: () => VigorRetryPolicyMiddlewaresBase,
|
|
73
|
+
VigorRetryPolicySettings: () => VigorRetryPolicySettings,
|
|
74
|
+
VigorRetryPolicySettingsBase: () => VigorRetryPolicySettingsBase,
|
|
75
|
+
VigorStatus: () => VigorStatus,
|
|
76
|
+
default: () => index_default,
|
|
77
|
+
vigor: () => vigor
|
|
78
|
+
});
|
|
79
|
+
module.exports = __toCommonJS(index_exports);
|
|
80
|
+
|
|
81
|
+
// src/core/symbol.ts
|
|
82
|
+
function createBrand(b, n) {
|
|
83
|
+
return `@vigor-fetch:::${b} <- ${n}`;
|
|
84
|
+
}
|
|
85
|
+
var VigorDefault = /* @__PURE__ */ Symbol("VigorDefault");
|
|
86
|
+
var isVigorDefault = (v) => v === VigorDefault;
|
|
87
|
+
var VigorEmpty = /* @__PURE__ */ Symbol("VigorEmpty");
|
|
88
|
+
var isVigorEmpty = (v) => v === VigorEmpty;
|
|
89
|
+
|
|
90
|
+
// src/core/status.ts
|
|
91
|
+
var VigorStatus = class {
|
|
92
|
+
_base;
|
|
93
|
+
_config;
|
|
94
|
+
/**
|
|
95
|
+
* @param base - The default/base config for this builder.
|
|
96
|
+
* @param config - The (possibly partial) config to merge onto `base`.
|
|
97
|
+
*/
|
|
98
|
+
constructor(base, config) {
|
|
99
|
+
this._base = base;
|
|
100
|
+
this._config = this._merge(base, config);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Derives a new instance by merging `patch` onto the current config.
|
|
104
|
+
*
|
|
105
|
+
* @param patch - Values to overwrite/merge in for this step.
|
|
106
|
+
* @param strategy - Optional tree mirroring the shape of `patch`, whose
|
|
107
|
+
* leaves may be `"replace" | "concat" | "merge"` to force the merge
|
|
108
|
+
* behavior at that path. Paths without a strategy fall back to the
|
|
109
|
+
* default behavior (deep merge for objects, concat for arrays).
|
|
110
|
+
*/
|
|
111
|
+
_next(patch, strategy) {
|
|
112
|
+
const merged = this._merge(this._config, patch, strategy);
|
|
113
|
+
return this._create(merged);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Deep-merges `target` onto `source`, honoring an optional per-path
|
|
117
|
+
* `strategy` tree. Objects merge key by key, arrays concatenate (unless
|
|
118
|
+
* `"replace"` is specified), and any other value is overwritten.
|
|
119
|
+
*/
|
|
120
|
+
_merge(source, target, strategy) {
|
|
121
|
+
const isObj = (v) => v !== null && typeof v === "object" && Object.getPrototypeOf(v) === Object.prototype;
|
|
122
|
+
const merge = (a, b, s) => {
|
|
123
|
+
if (b === void 0 || b === null) return a;
|
|
124
|
+
if (s === "replace") return b;
|
|
125
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
126
|
+
return s === "replace" ? b : [...a, ...b];
|
|
127
|
+
}
|
|
128
|
+
if (isObj(a) && isObj(b)) {
|
|
129
|
+
const r = { ...a };
|
|
130
|
+
const sObj = isObj(s) ? s : void 0;
|
|
131
|
+
for (const k of Object.keys(b)) {
|
|
132
|
+
r[k] = merge(a[k], b[k], sObj?.[k]);
|
|
133
|
+
}
|
|
134
|
+
return r;
|
|
135
|
+
}
|
|
136
|
+
return b;
|
|
137
|
+
};
|
|
138
|
+
return merge(source, target, strategy);
|
|
139
|
+
}
|
|
140
|
+
/** The default/base config this builder was constructed with. */
|
|
141
|
+
get base() {
|
|
142
|
+
return this._base;
|
|
143
|
+
}
|
|
144
|
+
/** The current, merged config for this builder instance. */
|
|
145
|
+
get config() {
|
|
146
|
+
return this._config;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// src/all/settings.ts
|
|
151
|
+
var VigorAllPolicySettingsBase = {
|
|
152
|
+
__brand: createBrand("All", "Policy<Settings<Schema"),
|
|
153
|
+
concurrency: 5,
|
|
154
|
+
onlySuccess: false
|
|
155
|
+
};
|
|
156
|
+
var VigorAllPolicySettings = class _VigorAllPolicySettings extends VigorStatus {
|
|
157
|
+
constructor(config = VigorAllBase) {
|
|
158
|
+
super(VigorAllBase, config);
|
|
159
|
+
}
|
|
160
|
+
_create(config) {
|
|
161
|
+
return new _VigorAllPolicySettings(config);
|
|
162
|
+
}
|
|
163
|
+
/** Sets the maximum number of tasks run concurrently. */
|
|
164
|
+
concurrency(num) {
|
|
165
|
+
return this._next({ policy: { settings: { concurrency: num } } });
|
|
166
|
+
}
|
|
167
|
+
/** When enabled, filters the final result down to only the tasks that succeeded. */
|
|
168
|
+
onlySuccess(bool) {
|
|
169
|
+
return this._next({ policy: { settings: { onlySuccess: bool } } });
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// src/all/middlewares.ts
|
|
174
|
+
var VigorAllPolicyMiddlewaresBase = {
|
|
175
|
+
__brand: createBrand("All", "Policy<Middlewares<Schema"),
|
|
176
|
+
before: [],
|
|
177
|
+
after: [],
|
|
178
|
+
onError: []
|
|
179
|
+
};
|
|
180
|
+
var VigorAllPolicyMiddlewares = class _VigorAllPolicyMiddlewares extends VigorStatus {
|
|
181
|
+
constructor(config = VigorAllBase) {
|
|
182
|
+
super(VigorAllBase, config);
|
|
183
|
+
}
|
|
184
|
+
_create(config) {
|
|
185
|
+
return new _VigorAllPolicyMiddlewares(config);
|
|
186
|
+
}
|
|
187
|
+
/** Registers a middleware that runs before each task is invoked. */
|
|
188
|
+
before(func) {
|
|
189
|
+
return this._next({ policy: { middlewares: { before: [func] } } });
|
|
190
|
+
}
|
|
191
|
+
/** Registers a middleware that runs after each task settles successfully. */
|
|
192
|
+
after(func) {
|
|
193
|
+
return this._next({ policy: { middlewares: { after: [func] } } });
|
|
194
|
+
}
|
|
195
|
+
/** Registers a middleware that runs when an individual task fails. */
|
|
196
|
+
onError(func) {
|
|
197
|
+
return this._next({ policy: { middlewares: { onError: [func] } } });
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// src/all/policy.ts
|
|
202
|
+
var VigorAllPolicyBase = {
|
|
203
|
+
__brand: createBrand("All", "Policy<Schema"),
|
|
204
|
+
target: [],
|
|
205
|
+
settings: VigorAllPolicySettingsBase,
|
|
206
|
+
middlewares: VigorAllPolicyMiddlewaresBase
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// src/all/context.ts
|
|
210
|
+
var VigorAllContextBase = {
|
|
211
|
+
__brand: createBrand("All", "Context<Schema"),
|
|
212
|
+
result: VigorDefault,
|
|
213
|
+
policy: VigorAllPolicyBase,
|
|
214
|
+
record: {}
|
|
215
|
+
};
|
|
216
|
+
var VigorAllEachContextBase = {
|
|
217
|
+
__brand: createBrand("All", "EachContext<Schema"),
|
|
218
|
+
result: VigorDefault,
|
|
219
|
+
error: VigorDefault,
|
|
220
|
+
flags: { overrided: false },
|
|
221
|
+
record: {}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// src/core/error.ts
|
|
225
|
+
var VigorError = class extends Error {
|
|
226
|
+
timestamp = /* @__PURE__ */ new Date();
|
|
227
|
+
cause;
|
|
228
|
+
code;
|
|
229
|
+
data;
|
|
230
|
+
method;
|
|
231
|
+
context;
|
|
232
|
+
/**
|
|
233
|
+
* @param code - Machine-readable error code.
|
|
234
|
+
* @param message - Human-readable message (rendered after the `[code]` prefix).
|
|
235
|
+
* @param options - Additional error metadata (cause, data, method, context).
|
|
236
|
+
*/
|
|
237
|
+
constructor(code, message, options) {
|
|
238
|
+
super(`[${code}] ${message}`);
|
|
239
|
+
this.name = new.target.name;
|
|
240
|
+
this.code = code;
|
|
241
|
+
this.cause = options.cause;
|
|
242
|
+
this.data = options.data;
|
|
243
|
+
this.method = options.method;
|
|
244
|
+
this.context = options.context;
|
|
245
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
246
|
+
Error.captureStackTrace?.(this, new.target);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
// src/all/error.ts
|
|
251
|
+
var VigorAllErrorMessageFuncs = {
|
|
252
|
+
EMPTY_TARGET: (_) => `Empty target list`
|
|
253
|
+
};
|
|
254
|
+
var VigorAllError = class extends VigorError {
|
|
255
|
+
/**
|
|
256
|
+
* @param code - One of the all module's error codes.
|
|
257
|
+
* @param options - Error metadata, including the `data` payload for `code`.
|
|
258
|
+
*/
|
|
259
|
+
constructor(code, options) {
|
|
260
|
+
const messageFn = VigorAllErrorMessageFuncs[code];
|
|
261
|
+
super(code, messageFn(options.data), options);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// src/all/main.ts
|
|
266
|
+
var VigorAllBase = {
|
|
267
|
+
__brand: createBrand("All", "Schema"),
|
|
268
|
+
policy: VigorAllPolicyBase,
|
|
269
|
+
context: VigorAllContextBase
|
|
270
|
+
};
|
|
271
|
+
var VigorAll = class _VigorAll extends VigorStatus {
|
|
272
|
+
constructor(config = VigorAllBase) {
|
|
273
|
+
super(VigorAllBase, config);
|
|
274
|
+
}
|
|
275
|
+
_create(config) {
|
|
276
|
+
return new _VigorAll(config);
|
|
277
|
+
}
|
|
278
|
+
/** Sets the list of tasks to run. */
|
|
279
|
+
target(...funcs) {
|
|
280
|
+
return this._next({ policy: { target: funcs } });
|
|
281
|
+
}
|
|
282
|
+
/** Configures the all-policy's general settings (concurrency, onlySuccess). */
|
|
283
|
+
settings(input) {
|
|
284
|
+
if (typeof input === "function" || input instanceof VigorAllPolicySettings) {
|
|
285
|
+
const result = typeof input === "function" ? input(new VigorAllPolicySettings()) : input;
|
|
286
|
+
return this._next({
|
|
287
|
+
policy: { settings: result.config.policy.settings }
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
return this._next({ policy: { settings: input } });
|
|
291
|
+
}
|
|
292
|
+
/** Configures the all-policy's per-task middleware pipeline. */
|
|
293
|
+
middlewares(input) {
|
|
294
|
+
if (typeof input === "function" || input instanceof VigorAllPolicyMiddlewares) {
|
|
295
|
+
const result = typeof input === "function" ? input(new VigorAllPolicyMiddlewares()) : input;
|
|
296
|
+
return this._next({
|
|
297
|
+
policy: { middlewares: result.config.policy.middlewares }
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return this._next({ policy: { middlewares: input } });
|
|
301
|
+
}
|
|
302
|
+
/** Runs a single task through the before/after/onError middleware pipeline. */
|
|
303
|
+
async _runTask(task, policy) {
|
|
304
|
+
let ctx = { ...VigorAllEachContextBase };
|
|
305
|
+
try {
|
|
306
|
+
for (const before of policy.middlewares.before) await before(ctx);
|
|
307
|
+
ctx.result = await task();
|
|
308
|
+
for (const after of policy.middlewares.after) await after(ctx);
|
|
309
|
+
return { success: true, value: ctx.result };
|
|
310
|
+
} catch (error) {
|
|
311
|
+
ctx.error = error;
|
|
312
|
+
const setResult = (r) => {
|
|
313
|
+
ctx.flags.overrided = true;
|
|
314
|
+
ctx.result = r;
|
|
315
|
+
};
|
|
316
|
+
for (const onError of policy.middlewares.onError) await onError(ctx, { setResult });
|
|
317
|
+
if (ctx.flags.overrided) return { success: true, value: ctx.result };
|
|
318
|
+
return { success: false, value: error };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/** Runs all tasks and returns the results array directly, throwing on final failure. */
|
|
322
|
+
async request() {
|
|
323
|
+
const res = await this.requestVerbose();
|
|
324
|
+
if (res.success) return res.data;
|
|
325
|
+
throw res.error;
|
|
326
|
+
}
|
|
327
|
+
/** Runs all tasks and returns a result/error envelope instead of throwing. */
|
|
328
|
+
async requestVerbose() {
|
|
329
|
+
return await this.requestRuntime();
|
|
330
|
+
}
|
|
331
|
+
/** Internal execution loop implementing the bounded-concurrency worker pool. */
|
|
332
|
+
async requestRuntime(restartAttempt = 1) {
|
|
333
|
+
const config = this._merge(this.config, {});
|
|
334
|
+
const policy = config.policy;
|
|
335
|
+
try {
|
|
336
|
+
if (policy.target.length === 0) throw new VigorAllError("EMPTY_TARGET", {
|
|
337
|
+
method: "request",
|
|
338
|
+
data: {}
|
|
339
|
+
});
|
|
340
|
+
const concurrency = Math.max(1, policy.settings.concurrency);
|
|
341
|
+
const results = new Array(policy.target.length);
|
|
342
|
+
let cursor = 0;
|
|
343
|
+
const worker = async () => {
|
|
344
|
+
while (true) {
|
|
345
|
+
const i = cursor++;
|
|
346
|
+
if (i >= policy.target.length) return;
|
|
347
|
+
results[i] = await this._runTask(policy.target[i], policy);
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
await Promise.all(
|
|
351
|
+
Array.from({ length: Math.min(concurrency, policy.target.length) }, () => worker())
|
|
352
|
+
);
|
|
353
|
+
const result = policy.settings.onlySuccess ? results.filter((r) => r.success).map((r) => r.value) : results.map((r) => r.value);
|
|
354
|
+
return {
|
|
355
|
+
success: true,
|
|
356
|
+
data: result,
|
|
357
|
+
error: null
|
|
358
|
+
};
|
|
359
|
+
} catch (error) {
|
|
360
|
+
return {
|
|
361
|
+
success: false,
|
|
362
|
+
data: null,
|
|
363
|
+
error
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
// src/fetch/settings.ts
|
|
370
|
+
var VigorFetchPolicySettingsBase = {
|
|
371
|
+
__brand: createBrand("Fetch", "Policy<Settings<Schema"),
|
|
372
|
+
retryHeaders: ["retry-after", "ratelimit-reset", "x-ratelimit-reset", "x-retry-after", "x-amz-retry-after", "chrome-proxy-next-link"],
|
|
373
|
+
unretryStatus: [400, 401, 403, 404, 405, 413, 422],
|
|
374
|
+
maxRestarts: 3,
|
|
375
|
+
default: VigorEmpty
|
|
376
|
+
};
|
|
377
|
+
var VigorFetchPolicySettings = class _VigorFetchPolicySettings extends VigorStatus {
|
|
378
|
+
constructor(config = VigorFetchBase) {
|
|
379
|
+
super(VigorFetchBase, config);
|
|
380
|
+
}
|
|
381
|
+
_create(config) {
|
|
382
|
+
return new _VigorFetchPolicySettings(config);
|
|
383
|
+
}
|
|
384
|
+
/** Sets response headers consulted to compute a server-suggested retry delay. */
|
|
385
|
+
retryHeaders(...strs) {
|
|
386
|
+
return this._next({ policy: { settings: { retryHeaders: strs } } });
|
|
387
|
+
}
|
|
388
|
+
/** Sets HTTP status codes that should never be retried. */
|
|
389
|
+
unretryStatus(...nums) {
|
|
390
|
+
return this._next({ policy: { settings: { unretryStatus: nums } } });
|
|
391
|
+
}
|
|
392
|
+
/** Sets the maximum number of full restarts allowed. */
|
|
393
|
+
maxRestarts(num) {
|
|
394
|
+
return this._next({ policy: { settings: { maxRestarts: num } } });
|
|
395
|
+
}
|
|
396
|
+
/** Sets the fallback value/factory used when the request ultimately fails. */
|
|
397
|
+
default(func) {
|
|
398
|
+
return this._next({ policy: { settings: { default: func } } });
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
// src/fetch/middlewares.ts
|
|
403
|
+
var VigorFetchPolicyMiddlewaresBase = {
|
|
404
|
+
__brand: createBrand("Fetch", "Policy<Middlewares<Schema"),
|
|
405
|
+
before: [],
|
|
406
|
+
after: [],
|
|
407
|
+
onResult: [],
|
|
408
|
+
onError: []
|
|
409
|
+
};
|
|
410
|
+
var VigorFetchPolicyMiddlewares = class _VigorFetchPolicyMiddlewares extends VigorStatus {
|
|
411
|
+
constructor(config = VigorFetchBase) {
|
|
412
|
+
super(VigorFetchBase, config);
|
|
413
|
+
}
|
|
414
|
+
_create(config) {
|
|
415
|
+
return new _VigorFetchPolicyMiddlewares(config);
|
|
416
|
+
}
|
|
417
|
+
before(type, func) {
|
|
418
|
+
return this._next({ policy: { middlewares: { before: [{ _mode: type, func }] } } });
|
|
419
|
+
}
|
|
420
|
+
after(type, func) {
|
|
421
|
+
return this._next({ policy: { middlewares: { after: [{ _mode: type, func }] } } });
|
|
422
|
+
}
|
|
423
|
+
onResult(type, func) {
|
|
424
|
+
return this._next({ policy: { middlewares: { onResult: [{ _mode: type, func }] } } });
|
|
425
|
+
}
|
|
426
|
+
onError(type, func) {
|
|
427
|
+
return this._next({ policy: { middlewares: { onError: [{ _mode: type, func }] } } });
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
// src/retry/settings.ts
|
|
432
|
+
var VigorRetryPolicySettingsBase = {
|
|
433
|
+
__brand: createBrand("Retry", "Policy<Settings<Schema"),
|
|
434
|
+
default: VigorEmpty,
|
|
435
|
+
maxAttempts: 5,
|
|
436
|
+
maxRestarts: 3,
|
|
437
|
+
timeout: 2e4
|
|
438
|
+
};
|
|
439
|
+
var VigorRetryPolicySettings = class _VigorRetryPolicySettings extends VigorStatus {
|
|
440
|
+
constructor(config = VigorRetryBase) {
|
|
441
|
+
super(VigorRetryBase, config);
|
|
442
|
+
}
|
|
443
|
+
_create(config) {
|
|
444
|
+
return new _VigorRetryPolicySettings(config);
|
|
445
|
+
}
|
|
446
|
+
/** Sets the fallback value/factory used when the target ultimately fails. */
|
|
447
|
+
default(func) {
|
|
448
|
+
return this._next({
|
|
449
|
+
policy: { settings: { default: func } }
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
/** Sets the maximum number of retry attempts before giving up. */
|
|
453
|
+
maxAttempts(num) {
|
|
454
|
+
return this._next({
|
|
455
|
+
policy: { settings: { maxAttempts: num } }
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
/** Sets the maximum number of full restarts allowed. */
|
|
459
|
+
maxRestarts(num) {
|
|
460
|
+
return this._next({
|
|
461
|
+
policy: { settings: { maxRestarts: num } }
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
/** Sets the timeout, in milliseconds, for a single attempt. */
|
|
465
|
+
timeout(num) {
|
|
466
|
+
return this._next({
|
|
467
|
+
policy: { settings: { timeout: num } }
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// src/retry/middlewares.ts
|
|
473
|
+
var VigorRetryPolicyMiddlewaresBase = {
|
|
474
|
+
__brand: createBrand("Retry", "Policy<Middlewares<Schema"),
|
|
475
|
+
before: [],
|
|
476
|
+
after: [],
|
|
477
|
+
onResult: [],
|
|
478
|
+
retryIf: [],
|
|
479
|
+
onRetry: [],
|
|
480
|
+
onError: []
|
|
481
|
+
};
|
|
482
|
+
var VigorRetryPolicyMiddlewares = class _VigorRetryPolicyMiddlewares extends VigorStatus {
|
|
483
|
+
constructor(config = VigorRetryBase) {
|
|
484
|
+
super(VigorRetryBase, config);
|
|
485
|
+
}
|
|
486
|
+
_create(config) {
|
|
487
|
+
return new _VigorRetryPolicyMiddlewares(config);
|
|
488
|
+
}
|
|
489
|
+
before(type, func) {
|
|
490
|
+
return this._next({
|
|
491
|
+
policy: { middlewares: { before: [{ _mode: type, func }] } }
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
after(type, func) {
|
|
495
|
+
return this._next({
|
|
496
|
+
policy: { middlewares: { after: [{ _mode: type, func }] } }
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
onResult(type, func) {
|
|
500
|
+
return this._next({
|
|
501
|
+
policy: { middlewares: { onResult: [{ _mode: type, func }] } }
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
retryIf(type, func) {
|
|
505
|
+
return this._next({
|
|
506
|
+
policy: { middlewares: { retryIf: [{ _mode: type, func }] } }
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
onRetry(type, func) {
|
|
510
|
+
return this._next({
|
|
511
|
+
policy: { middlewares: { onRetry: [{ _mode: type, func }] } }
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
onError(type, func) {
|
|
515
|
+
return this._next({
|
|
516
|
+
policy: { middlewares: { onError: [{ _mode: type, func }] } }
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
// src/retry/error.ts
|
|
522
|
+
var VigorRetryErrorMessageFuncs = {
|
|
523
|
+
VALUE_REQUIRED: ({ key }) => `Value Required (missing ${key})`,
|
|
524
|
+
RETRY_EXHAUSTED: ({ maxAttempts }) => `Retry exhausted, (max ${maxAttempts})`,
|
|
525
|
+
RESTART_EXHAUSTED: ({ maxAttempts }) => `Restart exhausted, (max ${maxAttempts})`,
|
|
526
|
+
TIMED_OUT: ({ limit }) => `Timeout: exceeded ${limit}ms`
|
|
527
|
+
};
|
|
528
|
+
var VigorRetryError = class extends VigorError {
|
|
529
|
+
/**
|
|
530
|
+
* @param code - One of the retry module's error codes.
|
|
531
|
+
* @param options - Error metadata, including the `data` payload for `code`.
|
|
532
|
+
*/
|
|
533
|
+
constructor(code, options) {
|
|
534
|
+
const messageFn = VigorRetryErrorMessageFuncs[code];
|
|
535
|
+
super(code, messageFn(options.data), options);
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// src/retry/algorithms.ts
|
|
540
|
+
function VigorJitter(jitter) {
|
|
541
|
+
return (Math.random() * 2 - 1) * jitter;
|
|
542
|
+
}
|
|
543
|
+
var VigorRetryPolicyAlgorithmsConstantBase = {
|
|
544
|
+
__brand: createBrand("Retry", "Policy<Algorithms<Constant<Schema"),
|
|
545
|
+
_tag: "constant",
|
|
546
|
+
jitter: 1e3,
|
|
547
|
+
interval: 2e3,
|
|
548
|
+
_calculateDelay: (att, config) => {
|
|
549
|
+
const { interval, jitter } = config;
|
|
550
|
+
const min = jitter;
|
|
551
|
+
let delay = Math.max(min, interval);
|
|
552
|
+
delay += VigorJitter(jitter);
|
|
553
|
+
return delay;
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
var VigorRetryPolicyAlgorithmsConstant = class _VigorRetryPolicyAlgorithmsConstant extends VigorStatus {
|
|
557
|
+
constructor(config = VigorRetryPolicyAlgorithmsConstantBase) {
|
|
558
|
+
super(VigorRetryPolicyAlgorithmsConstantBase, config);
|
|
559
|
+
}
|
|
560
|
+
_create(config) {
|
|
561
|
+
return new _VigorRetryPolicyAlgorithmsConstant(config);
|
|
562
|
+
}
|
|
563
|
+
/** Sets the amount of random jitter added to the computed delay. */
|
|
564
|
+
jitter(num) {
|
|
565
|
+
return this._next({ jitter: num });
|
|
566
|
+
}
|
|
567
|
+
/** Sets the fixed delay interval, in milliseconds. */
|
|
568
|
+
interval(num) {
|
|
569
|
+
return this._next({ interval: num });
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
var VigorRetryPolicyAlgorithmsLinearBase = {
|
|
573
|
+
__brand: createBrand("Retry", "Policy<Algorithms<Linear<Schema"),
|
|
574
|
+
_tag: "linear",
|
|
575
|
+
jitter: 1e3,
|
|
576
|
+
initial: 500,
|
|
577
|
+
increment: 1e3,
|
|
578
|
+
minDelay: 0,
|
|
579
|
+
maxDelay: 1e4,
|
|
580
|
+
_calculateDelay: (att, config) => {
|
|
581
|
+
const { initial, jitter, increment, minDelay, maxDelay } = config;
|
|
582
|
+
const range = maxDelay - minDelay;
|
|
583
|
+
const j = Math.min(jitter, range / 2);
|
|
584
|
+
const min = minDelay + j;
|
|
585
|
+
const max = maxDelay - j;
|
|
586
|
+
let delay = initial + increment * att;
|
|
587
|
+
delay = Math.max(min, Math.min(max, delay));
|
|
588
|
+
delay += VigorJitter(j);
|
|
589
|
+
return delay;
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
var VigorRetryPolicyAlgorithmsLinear = class _VigorRetryPolicyAlgorithmsLinear extends VigorStatus {
|
|
593
|
+
constructor(config = VigorRetryPolicyAlgorithmsLinearBase) {
|
|
594
|
+
super(VigorRetryPolicyAlgorithmsLinearBase, config);
|
|
595
|
+
}
|
|
596
|
+
_create(config) {
|
|
597
|
+
return new _VigorRetryPolicyAlgorithmsLinear(config);
|
|
598
|
+
}
|
|
599
|
+
/** Sets the amount of random jitter added to the computed delay. */
|
|
600
|
+
jitter(num) {
|
|
601
|
+
return this._next({ jitter: num });
|
|
602
|
+
}
|
|
603
|
+
/** Sets the initial delay, in milliseconds, before the first retry. */
|
|
604
|
+
initial(num) {
|
|
605
|
+
return this._next({ initial: num });
|
|
606
|
+
}
|
|
607
|
+
/** Sets how much the delay grows, in milliseconds, per attempt. */
|
|
608
|
+
increment(num) {
|
|
609
|
+
return this._next({ increment: num });
|
|
610
|
+
}
|
|
611
|
+
/** Sets the minimum allowed delay, in milliseconds. */
|
|
612
|
+
minDelay(num) {
|
|
613
|
+
return this._next({ minDelay: num });
|
|
614
|
+
}
|
|
615
|
+
/** Sets the maximum allowed delay, in milliseconds. */
|
|
616
|
+
maxDelay(num) {
|
|
617
|
+
return this._next({ maxDelay: num });
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
var VigorRetryPolicyAlgorithmsBackoffBase = {
|
|
621
|
+
__brand: createBrand("Retry", "Policy<Algorithms<Backoff<Schema"),
|
|
622
|
+
_tag: "backoff",
|
|
623
|
+
jitter: 800,
|
|
624
|
+
initial: 0,
|
|
625
|
+
multiplier: 1.7,
|
|
626
|
+
unit: 1e3,
|
|
627
|
+
minDelay: 500,
|
|
628
|
+
maxDelay: 1e4,
|
|
629
|
+
_calculateDelay: (att, config) => {
|
|
630
|
+
const { jitter, initial, multiplier, unit, minDelay, maxDelay } = config;
|
|
631
|
+
const range = maxDelay - minDelay;
|
|
632
|
+
const j = Math.min(jitter, range / 2);
|
|
633
|
+
const min = minDelay + j;
|
|
634
|
+
const max = maxDelay - j;
|
|
635
|
+
let delay = initial + unit * Math.pow(multiplier, att);
|
|
636
|
+
delay = Math.max(min, Math.min(max, delay));
|
|
637
|
+
delay += VigorJitter(j);
|
|
638
|
+
return delay;
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
var VigorRetryPolicyAlgorithmsBackoff = class _VigorRetryPolicyAlgorithmsBackoff extends VigorStatus {
|
|
642
|
+
constructor(config = VigorRetryPolicyAlgorithmsBackoffBase) {
|
|
643
|
+
super(VigorRetryPolicyAlgorithmsBackoffBase, config);
|
|
644
|
+
}
|
|
645
|
+
_create(config) {
|
|
646
|
+
return new _VigorRetryPolicyAlgorithmsBackoff(config);
|
|
647
|
+
}
|
|
648
|
+
/** Sets the amount of random jitter added to the computed delay. */
|
|
649
|
+
jitter(num) {
|
|
650
|
+
return this._next({ jitter: num });
|
|
651
|
+
}
|
|
652
|
+
/** Sets the initial delay, in milliseconds, before backoff growth is applied. */
|
|
653
|
+
initial(num) {
|
|
654
|
+
return this._next({ initial: num });
|
|
655
|
+
}
|
|
656
|
+
/** Sets the exponential growth factor applied per attempt. */
|
|
657
|
+
multiplier(num) {
|
|
658
|
+
return this._next({ multiplier: num });
|
|
659
|
+
}
|
|
660
|
+
/** Sets the base unit, in milliseconds, the multiplier is scaled by. */
|
|
661
|
+
unit(num) {
|
|
662
|
+
return this._next({ unit: num });
|
|
663
|
+
}
|
|
664
|
+
/** Sets the minimum allowed delay, in milliseconds. */
|
|
665
|
+
minDelay(num) {
|
|
666
|
+
return this._next({ minDelay: num });
|
|
667
|
+
}
|
|
668
|
+
/** Sets the maximum allowed delay, in milliseconds. */
|
|
669
|
+
maxDelay(num) {
|
|
670
|
+
return this._next({ maxDelay: num });
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
var VigorRetryPolicyAlgorithmsCustomBase = {
|
|
674
|
+
__brand: createBrand("Retry", "Policy<Algorithms<Custom<Schema"),
|
|
675
|
+
_tag: "custom",
|
|
676
|
+
jitter: 800,
|
|
677
|
+
minDelay: 500,
|
|
678
|
+
maxDelay: 1e4,
|
|
679
|
+
target: VigorEmpty,
|
|
680
|
+
_calculateDelay: (att, config) => {
|
|
681
|
+
const { jitter, minDelay, maxDelay, target } = config;
|
|
682
|
+
if (isVigorEmpty(target)) throw new VigorRetryError("VALUE_REQUIRED", {
|
|
683
|
+
method: "_calculateDelay",
|
|
684
|
+
data: {
|
|
685
|
+
key: "target"
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
const range = maxDelay - minDelay;
|
|
689
|
+
const j = Math.min(jitter, range / 2);
|
|
690
|
+
const min = minDelay + j;
|
|
691
|
+
const max = maxDelay - j;
|
|
692
|
+
let delay = target(att);
|
|
693
|
+
delay = Math.max(min, Math.min(max, delay));
|
|
694
|
+
delay += VigorJitter(j);
|
|
695
|
+
return delay;
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
var VigorRetryPolicyAlgorithmsCustom = class _VigorRetryPolicyAlgorithmsCustom extends VigorStatus {
|
|
699
|
+
constructor(config = VigorRetryPolicyAlgorithmsCustomBase) {
|
|
700
|
+
super(VigorRetryPolicyAlgorithmsCustomBase, config);
|
|
701
|
+
}
|
|
702
|
+
_create(config) {
|
|
703
|
+
return new _VigorRetryPolicyAlgorithmsCustom(config);
|
|
704
|
+
}
|
|
705
|
+
/** Sets the amount of random jitter added to the computed delay. */
|
|
706
|
+
jitter(num) {
|
|
707
|
+
return this._next({ jitter: num });
|
|
708
|
+
}
|
|
709
|
+
/** Sets the minimum allowed delay, in milliseconds. */
|
|
710
|
+
minDelay(num) {
|
|
711
|
+
return this._next({ minDelay: num });
|
|
712
|
+
}
|
|
713
|
+
/** Sets the maximum allowed delay, in milliseconds. */
|
|
714
|
+
maxDelay(num) {
|
|
715
|
+
return this._next({ maxDelay: num });
|
|
716
|
+
}
|
|
717
|
+
/** Sets the user-supplied function computing the raw delay for an attempt. */
|
|
718
|
+
target(func) {
|
|
719
|
+
return this._next({ target: func });
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
var VigorRetryPolicyAlgorithmsBase = VigorRetryPolicyAlgorithmsConstantBase;
|
|
723
|
+
var VigorRetryPolicyAlgorithms = class _VigorRetryPolicyAlgorithms extends VigorStatus {
|
|
724
|
+
constructor(config = VigorRetryBase) {
|
|
725
|
+
super(VigorRetryBase, config);
|
|
726
|
+
}
|
|
727
|
+
_create(config) {
|
|
728
|
+
return new _VigorRetryPolicyAlgorithms(config);
|
|
729
|
+
}
|
|
730
|
+
/** Switches to the constant-interval delay algorithm. */
|
|
731
|
+
constant(input) {
|
|
732
|
+
const leaf = this._merge(VigorRetryPolicyAlgorithmsConstantBase, input ?? {});
|
|
733
|
+
return this._next({
|
|
734
|
+
policy: { algorithms: leaf }
|
|
735
|
+
}, { policy: { algorithms: "replace" } });
|
|
736
|
+
}
|
|
737
|
+
/** Switches to the linearly-increasing delay algorithm. */
|
|
738
|
+
linear(input) {
|
|
739
|
+
const leaf = this._merge(VigorRetryPolicyAlgorithmsLinearBase, input ?? {});
|
|
740
|
+
return this._next({
|
|
741
|
+
policy: { algorithms: leaf }
|
|
742
|
+
}, { policy: { algorithms: "replace" } });
|
|
743
|
+
}
|
|
744
|
+
/** Switches to the exponential-backoff delay algorithm. */
|
|
745
|
+
backoff(input) {
|
|
746
|
+
const leaf = this._merge(VigorRetryPolicyAlgorithmsBackoffBase, input ?? {});
|
|
747
|
+
return this._next({
|
|
748
|
+
policy: { algorithms: leaf }
|
|
749
|
+
}, { policy: { algorithms: "replace" } });
|
|
750
|
+
}
|
|
751
|
+
/** Switches to a user-supplied custom delay algorithm. */
|
|
752
|
+
custom(input) {
|
|
753
|
+
const leaf = this._merge(VigorRetryPolicyAlgorithmsCustomBase, input ?? {});
|
|
754
|
+
return this._next({
|
|
755
|
+
policy: { algorithms: leaf }
|
|
756
|
+
}, { policy: { algorithms: "replace" } });
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
|
|
760
|
+
// src/retry/policy.ts
|
|
761
|
+
var VigorRetryPolicyBase = {
|
|
762
|
+
__brand: createBrand("Retry", "Policy<Schema"),
|
|
763
|
+
target: VigorEmpty,
|
|
764
|
+
abortSignals: [],
|
|
765
|
+
settings: VigorRetryPolicySettingsBase,
|
|
766
|
+
middlewares: VigorRetryPolicyMiddlewaresBase,
|
|
767
|
+
algorithms: VigorRetryPolicyAlgorithmsBase
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
// src/retry/context.ts
|
|
771
|
+
var VigorRetryContextBase = {
|
|
772
|
+
__brand: createBrand("Retry", "Context<Schema"),
|
|
773
|
+
result: VigorDefault,
|
|
774
|
+
error: VigorDefault,
|
|
775
|
+
system: {
|
|
776
|
+
delay: VigorDefault,
|
|
777
|
+
attempt: 0
|
|
778
|
+
},
|
|
779
|
+
flags: {
|
|
780
|
+
doRetry: true,
|
|
781
|
+
doRestart: false,
|
|
782
|
+
brokeRetry: false,
|
|
783
|
+
overridden: false
|
|
784
|
+
},
|
|
785
|
+
record: {},
|
|
786
|
+
policy: VigorRetryPolicyBase
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
// src/retry/main.ts
|
|
790
|
+
var VigorRetryBase = {
|
|
791
|
+
__brand: createBrand("Retry", "Schema"),
|
|
792
|
+
policy: VigorRetryPolicyBase,
|
|
793
|
+
context: VigorRetryContextBase
|
|
794
|
+
};
|
|
795
|
+
var VigorRetry = class _VigorRetry extends VigorStatus {
|
|
796
|
+
constructor(config = VigorRetryBase) {
|
|
797
|
+
super(VigorRetryBase, config);
|
|
798
|
+
}
|
|
799
|
+
_create(config) {
|
|
800
|
+
return new _VigorRetry(config);
|
|
801
|
+
}
|
|
802
|
+
/** Sets the target function to invoke, with retry/timeout applied. */
|
|
803
|
+
target(func) {
|
|
804
|
+
return this._next({
|
|
805
|
+
policy: { target: func }
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
/** Sets external abort signals that, when aborted, stop retrying. */
|
|
809
|
+
abortSignals(...sig) {
|
|
810
|
+
return this._next({
|
|
811
|
+
policy: { abortSignals: sig }
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
/** Configures the retry policy's general settings (max attempts, timeout, etc). */
|
|
815
|
+
settings(input) {
|
|
816
|
+
if (typeof input === "function" || input instanceof VigorRetryPolicySettings) {
|
|
817
|
+
const result = typeof input === "function" ? input(new VigorRetryPolicySettings()) : input;
|
|
818
|
+
return this._next({
|
|
819
|
+
policy: { settings: result.config.policy.settings }
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
return this._next({
|
|
823
|
+
policy: { settings: input }
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
/** Configures the retry policy's middleware pipeline. */
|
|
827
|
+
middlewares(input) {
|
|
828
|
+
if (typeof input === "function" || input instanceof VigorRetryPolicyMiddlewares) {
|
|
829
|
+
const result = typeof input === "function" ? input(new VigorRetryPolicyMiddlewares()) : input;
|
|
830
|
+
return this._next({
|
|
831
|
+
policy: { middlewares: result.config.policy.middlewares }
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
return this._next({
|
|
835
|
+
policy: { middlewares: input }
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
/** Configures the retry policy's delay algorithm. */
|
|
839
|
+
algorithms(input) {
|
|
840
|
+
if (typeof input === "function") {
|
|
841
|
+
const result = input(new VigorRetryPolicyAlgorithms());
|
|
842
|
+
const algoSlice = result.config.policy.algorithms;
|
|
843
|
+
return this._next({
|
|
844
|
+
policy: { algorithms: algoSlice }
|
|
845
|
+
}, { policy: { algorithms: "replace" } });
|
|
846
|
+
}
|
|
847
|
+
return this._next({
|
|
848
|
+
policy: { algorithms: input }
|
|
849
|
+
}, { policy: { algorithms: "replace" } });
|
|
850
|
+
}
|
|
851
|
+
/** Runs the target and returns its result directly, throwing on final failure. */
|
|
852
|
+
async request() {
|
|
853
|
+
const res = await this.requestVerbose();
|
|
854
|
+
if (res.success) return res.data;
|
|
855
|
+
throw res.error;
|
|
856
|
+
}
|
|
857
|
+
/** Runs the target and returns a result/error envelope instead of throwing. */
|
|
858
|
+
async requestVerbose() {
|
|
859
|
+
return await this.requestRuntime();
|
|
860
|
+
}
|
|
861
|
+
/** Internal execution loop implementing the attempt/retry/restart lifecycle. */
|
|
862
|
+
async requestRuntime(restartAttempt = 1) {
|
|
863
|
+
const config = this._merge(this.config, {});
|
|
864
|
+
let ctx = {
|
|
865
|
+
...config.context,
|
|
866
|
+
policy: config.policy
|
|
867
|
+
};
|
|
868
|
+
if (isVigorEmpty(ctx.policy.target)) throw new VigorRetryError("VALUE_REQUIRED", {
|
|
869
|
+
method: "request",
|
|
870
|
+
data: {
|
|
871
|
+
key: "target"
|
|
872
|
+
},
|
|
873
|
+
context: ctx
|
|
874
|
+
});
|
|
875
|
+
const target = ctx.policy.target;
|
|
876
|
+
const throwError = (err) => {
|
|
877
|
+
throw err;
|
|
878
|
+
};
|
|
879
|
+
try {
|
|
880
|
+
while (ctx.system.attempt < ctx.policy.settings.maxAttempts) {
|
|
881
|
+
ctx.system.attempt++;
|
|
882
|
+
try {
|
|
883
|
+
const breakRetry = (err) => {
|
|
884
|
+
ctx.flags.brokeRetry = true;
|
|
885
|
+
throw err;
|
|
886
|
+
};
|
|
887
|
+
const userController = new AbortController();
|
|
888
|
+
const timeoutController = new AbortController();
|
|
889
|
+
const innerSignals = AbortSignal.any([
|
|
890
|
+
userController.signal,
|
|
891
|
+
timeoutController.signal
|
|
892
|
+
]);
|
|
893
|
+
const outerSignals = AbortSignal.any(ctx.policy.abortSignals);
|
|
894
|
+
const autoBreak = () => {
|
|
895
|
+
ctx.flags.brokeRetry = true;
|
|
896
|
+
};
|
|
897
|
+
outerSignals.addEventListener("abort", autoBreak);
|
|
898
|
+
const mergedSignals = AbortSignal.any([
|
|
899
|
+
innerSignals,
|
|
900
|
+
outerSignals
|
|
901
|
+
]);
|
|
902
|
+
let onAbort;
|
|
903
|
+
let timeoutId;
|
|
904
|
+
try {
|
|
905
|
+
for (const middleware of ctx.policy.middlewares.before) {
|
|
906
|
+
if (middleware._mode === "fluent") {
|
|
907
|
+
await middleware.func(ctx);
|
|
908
|
+
} else {
|
|
909
|
+
ctx = await middleware.func(ctx, {
|
|
910
|
+
abort: (reason) => userController.abort(reason),
|
|
911
|
+
throwError,
|
|
912
|
+
breakRetry
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
mergedSignals.throwIfAborted();
|
|
917
|
+
timeoutId = setTimeout(() => timeoutController.abort(new VigorRetryError("TIMED_OUT", {
|
|
918
|
+
method: "request",
|
|
919
|
+
data: {
|
|
920
|
+
limit: ctx.policy.settings.timeout
|
|
921
|
+
}
|
|
922
|
+
})), ctx.policy.settings.timeout);
|
|
923
|
+
ctx.result = await Promise.race([
|
|
924
|
+
target(mergedSignals),
|
|
925
|
+
new Promise((_, rej) => {
|
|
926
|
+
onAbort = () => rej(mergedSignals.reason);
|
|
927
|
+
mergedSignals.addEventListener("abort", onAbort);
|
|
928
|
+
})
|
|
929
|
+
]);
|
|
930
|
+
for (const middleware of ctx.policy.middlewares.after) {
|
|
931
|
+
if (middleware._mode === "fluent") {
|
|
932
|
+
await middleware.func(ctx);
|
|
933
|
+
} else {
|
|
934
|
+
ctx = await middleware.func(ctx, {
|
|
935
|
+
throwError
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
const setResult = (res) => {
|
|
940
|
+
ctx.result = res;
|
|
941
|
+
};
|
|
942
|
+
for (const middleware of ctx.policy.middlewares.onResult) {
|
|
943
|
+
if (middleware._mode === "fluent") {
|
|
944
|
+
ctx.result = await middleware.func(ctx.result);
|
|
945
|
+
} else {
|
|
946
|
+
ctx = await middleware.func(ctx, {
|
|
947
|
+
setResult,
|
|
948
|
+
throwError
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
return {
|
|
953
|
+
success: true,
|
|
954
|
+
data: ctx.result,
|
|
955
|
+
error: null
|
|
956
|
+
};
|
|
957
|
+
} finally {
|
|
958
|
+
clearTimeout(timeoutId);
|
|
959
|
+
outerSignals.removeEventListener("abort", autoBreak);
|
|
960
|
+
if (onAbort) mergedSignals.removeEventListener("abort", onAbort);
|
|
961
|
+
}
|
|
962
|
+
} catch (error) {
|
|
963
|
+
ctx.error = error;
|
|
964
|
+
if (ctx.flags.brokeRetry) throw ctx.error;
|
|
965
|
+
ctx.flags.doRetry = true;
|
|
966
|
+
const proceedRetry = () => ctx.flags.doRetry = true;
|
|
967
|
+
const cancelRetry = () => ctx.flags.doRetry = false;
|
|
968
|
+
for (const middleware of ctx.policy.middlewares.retryIf) {
|
|
969
|
+
if (middleware._mode === "fluent") {
|
|
970
|
+
ctx.flags.doRetry = await middleware.func(ctx.error);
|
|
971
|
+
} else {
|
|
972
|
+
ctx = await middleware.func(ctx, {
|
|
973
|
+
proceedRetry,
|
|
974
|
+
cancelRetry
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
if (!ctx.flags.doRetry) throw ctx.error;
|
|
979
|
+
ctx.system.delay = ctx.policy.algorithms._calculateDelay(ctx.system.attempt, ctx.policy.algorithms);
|
|
980
|
+
const setDelay = (num) => {
|
|
981
|
+
ctx.system.delay = num;
|
|
982
|
+
};
|
|
983
|
+
for (const middleware of ctx.policy.middlewares.onRetry) {
|
|
984
|
+
if (middleware._mode === "fluent") {
|
|
985
|
+
await middleware.func(ctx.error);
|
|
986
|
+
} else {
|
|
987
|
+
ctx = await middleware.func(ctx, {
|
|
988
|
+
throwError,
|
|
989
|
+
setDelay
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
const delay = ctx.system.delay;
|
|
994
|
+
await new Promise((res) => setTimeout(res, delay));
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
throw new VigorRetryError("RETRY_EXHAUSTED", {
|
|
998
|
+
method: "request",
|
|
999
|
+
cause: ctx.error,
|
|
1000
|
+
data: {
|
|
1001
|
+
maxAttempts: ctx.policy.settings.maxAttempts,
|
|
1002
|
+
error: ctx.error
|
|
1003
|
+
}
|
|
1004
|
+
});
|
|
1005
|
+
} catch (error) {
|
|
1006
|
+
ctx.error = error;
|
|
1007
|
+
ctx.flags.doRestart = false;
|
|
1008
|
+
ctx.flags.overridden = false;
|
|
1009
|
+
const setResult = (res) => {
|
|
1010
|
+
ctx.flags.overridden = true;
|
|
1011
|
+
ctx.result = res;
|
|
1012
|
+
};
|
|
1013
|
+
const proceedRestart = () => ctx.flags.doRestart = true;
|
|
1014
|
+
const cancelRestart = () => ctx.flags.doRestart = false;
|
|
1015
|
+
for (const middleware of ctx.policy.middlewares.onError) {
|
|
1016
|
+
if (middleware._mode === "fluent") {
|
|
1017
|
+
await middleware.func(ctx.error);
|
|
1018
|
+
} else {
|
|
1019
|
+
ctx = await middleware.func(ctx, {
|
|
1020
|
+
setResult,
|
|
1021
|
+
throwError,
|
|
1022
|
+
proceedRestart,
|
|
1023
|
+
cancelRestart
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
if (ctx.flags.doRestart) {
|
|
1028
|
+
if (restartAttempt + 1 > ctx.policy.settings.maxRestarts) throw new VigorRetryError("RESTART_EXHAUSTED", {
|
|
1029
|
+
method: "request",
|
|
1030
|
+
cause: ctx.error,
|
|
1031
|
+
data: {
|
|
1032
|
+
maxAttempts: ctx.policy.settings.maxRestarts,
|
|
1033
|
+
error: ctx.error
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
return await this.requestRuntime(restartAttempt + 1);
|
|
1037
|
+
}
|
|
1038
|
+
if (ctx.flags.overridden) return {
|
|
1039
|
+
success: true,
|
|
1040
|
+
data: ctx.result,
|
|
1041
|
+
error: null
|
|
1042
|
+
};
|
|
1043
|
+
if (!isVigorEmpty(ctx.policy.settings.default)) {
|
|
1044
|
+
const data = await ctx.policy.settings.default(ctx);
|
|
1045
|
+
return {
|
|
1046
|
+
success: true,
|
|
1047
|
+
data,
|
|
1048
|
+
error: null
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
return {
|
|
1052
|
+
success: false,
|
|
1053
|
+
data: null,
|
|
1054
|
+
error: ctx.error
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
};
|
|
1059
|
+
|
|
1060
|
+
// src/parse/settings.ts
|
|
1061
|
+
var VigorParsePolicySettingsBase = {
|
|
1062
|
+
__brand: createBrand("Parse", "Policy<Settings<Schema"),
|
|
1063
|
+
raw: false,
|
|
1064
|
+
default: VigorEmpty,
|
|
1065
|
+
maxRestarts: 3
|
|
1066
|
+
};
|
|
1067
|
+
var VigorParsePolicySettings = class _VigorParsePolicySettings extends VigorStatus {
|
|
1068
|
+
constructor(config = VigorParseBase) {
|
|
1069
|
+
super(VigorParseBase, config);
|
|
1070
|
+
}
|
|
1071
|
+
_create(config) {
|
|
1072
|
+
return new _VigorParsePolicySettings(config);
|
|
1073
|
+
}
|
|
1074
|
+
/** When enabled, skips content-type based parsing and returns the raw response. */
|
|
1075
|
+
raw(bool) {
|
|
1076
|
+
return this._next({
|
|
1077
|
+
policy: { settings: { raw: bool } }
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
/** Sets the fallback value/factory used when parsing ultimately fails. */
|
|
1081
|
+
default(func) {
|
|
1082
|
+
return this._next({
|
|
1083
|
+
policy: { settings: { default: func } }
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
/** Sets the maximum number of full restarts allowed. */
|
|
1087
|
+
maxRestarts(num) {
|
|
1088
|
+
return this._next({
|
|
1089
|
+
policy: { settings: { maxRestarts: num } }
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
|
|
1094
|
+
// src/parse/middlewares.ts
|
|
1095
|
+
var VigorParsePolicyMiddlewaresBase = {
|
|
1096
|
+
__brand: createBrand("Parse", "Policy<Middlewares<Schema"),
|
|
1097
|
+
before: [],
|
|
1098
|
+
after: [],
|
|
1099
|
+
onResult: [],
|
|
1100
|
+
onError: []
|
|
1101
|
+
};
|
|
1102
|
+
var VigorParsePolicyMiddlewares = class _VigorParsePolicyMiddlewares extends VigorStatus {
|
|
1103
|
+
constructor(config = VigorParseBase) {
|
|
1104
|
+
super(VigorParseBase, config);
|
|
1105
|
+
}
|
|
1106
|
+
_create(config) {
|
|
1107
|
+
return new _VigorParsePolicyMiddlewares(config);
|
|
1108
|
+
}
|
|
1109
|
+
before(type, func) {
|
|
1110
|
+
return this._next({ policy: { middlewares: { before: [{ _mode: type, func }] } } });
|
|
1111
|
+
}
|
|
1112
|
+
after(type, func) {
|
|
1113
|
+
return this._next({ policy: { middlewares: { after: [{ _mode: type, func }] } } });
|
|
1114
|
+
}
|
|
1115
|
+
onResult(type, func) {
|
|
1116
|
+
return this._next({ policy: { middlewares: { onResult: [{ _mode: type, func }] } } });
|
|
1117
|
+
}
|
|
1118
|
+
onError(type, func) {
|
|
1119
|
+
return this._next({ policy: { middlewares: { onError: [{ _mode: type, func }] } } });
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
|
|
1123
|
+
// src/parse/error.ts
|
|
1124
|
+
var VigorParseErrorMessageFuncs = {
|
|
1125
|
+
VALUE_REQUIRED: ({ key }) => `Value Required (missing ${key})`,
|
|
1126
|
+
INVALID_CONTENT_TYPE: ({ received }) => `Invalid Content-Type header: ${String(received)}`,
|
|
1127
|
+
PARSER_NOT_FOUND: ({ received, expected }) => `Parser not found for Content-Type "${String(received)}" (known: ${expected.join(", ")})`,
|
|
1128
|
+
PARSER_ALL_FAILED: ({ tried }) => `All parsers failed, tried: ${tried.join(", ")}`,
|
|
1129
|
+
RESTART_EXHAUSTED: ({ maxAttempts }) => `Restart exhausted, (max ${maxAttempts})`
|
|
1130
|
+
};
|
|
1131
|
+
var VigorParseError = class extends VigorError {
|
|
1132
|
+
/**
|
|
1133
|
+
* @param code - One of the parse module's error codes.
|
|
1134
|
+
* @param options - Error metadata, including the `data` payload for `code`.
|
|
1135
|
+
*/
|
|
1136
|
+
constructor(code, options) {
|
|
1137
|
+
const messageFn = VigorParseErrorMessageFuncs[code];
|
|
1138
|
+
super(code, messageFn(options.data), options);
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
|
|
1142
|
+
// src/parse/strategies.ts
|
|
1143
|
+
var VigorParsePolicyStrategiesBase = {
|
|
1144
|
+
__brand: createBrand("Parse", "Policy<Strategies<Schema"),
|
|
1145
|
+
funcs: []
|
|
1146
|
+
};
|
|
1147
|
+
var ContentTypeParsers = [
|
|
1148
|
+
{ header: "application/json", regExp: /application\/(.+\+)?json(.+\+)?/i, method: (res) => res.json() },
|
|
1149
|
+
{ header: "application/xml", regExp: /application\/(.+\+)?xml(.+\+)?/i, method: (res) => res.text() },
|
|
1150
|
+
{ header: "application/x-www-form-urlencoded", regExp: /application\/(.+\+)?x-www-form-urlencoded(.+\+)?/i, method: (res) => res.formData() },
|
|
1151
|
+
{ header: "application/octet-stream", regExp: /application\/(.+\+)?octet-stream(.+\+)?/i, method: (res) => res.arrayBuffer() },
|
|
1152
|
+
{ header: "image/*", regExp: /^image\/.+/i, method: (res) => res.blob() },
|
|
1153
|
+
{ header: "audio/*", regExp: /^audio\/.+/i, method: (res) => res.blob() },
|
|
1154
|
+
{ header: "video/*", regExp: /^video\/.+/i, method: (res) => res.blob() },
|
|
1155
|
+
{ header: "multipart/form-data", regExp: /multipart\/(.+\+)?form-data(.+\+)?/i, method: (res) => res.formData() },
|
|
1156
|
+
{ header: "text/*", regExp: /^text\/.+/i, method: (res) => res.text() }
|
|
1157
|
+
];
|
|
1158
|
+
var SniffMethods = [
|
|
1159
|
+
{ title: "json", method: (res) => res.json() },
|
|
1160
|
+
{ title: "formData", method: (res) => res.formData() },
|
|
1161
|
+
{ title: "text", method: (res) => res.text() },
|
|
1162
|
+
{ title: "blob", method: (res) => res.blob() }
|
|
1163
|
+
];
|
|
1164
|
+
var VigorParseContentTypeStrategy = async (response) => {
|
|
1165
|
+
const contentTypeHeader = response.headers.get("content-type");
|
|
1166
|
+
if (!contentTypeHeader) throw new VigorParseError("INVALID_CONTENT_TYPE", {
|
|
1167
|
+
method: "VigorParseContentTypeStrategy",
|
|
1168
|
+
data: { received: contentTypeHeader }
|
|
1169
|
+
});
|
|
1170
|
+
const toDo = ContentTypeParsers.find((parser) => parser.regExp.test(contentTypeHeader));
|
|
1171
|
+
if (!toDo) throw new VigorParseError("PARSER_NOT_FOUND", {
|
|
1172
|
+
method: "VigorParseContentTypeStrategy",
|
|
1173
|
+
data: {
|
|
1174
|
+
expected: ContentTypeParsers.map((p) => p.header),
|
|
1175
|
+
received: contentTypeHeader
|
|
1176
|
+
}
|
|
1177
|
+
});
|
|
1178
|
+
return await toDo.method(response);
|
|
1179
|
+
};
|
|
1180
|
+
var VigorParseSniffStrategy = async (response) => {
|
|
1181
|
+
for (const [i, parser] of SniffMethods.entries()) {
|
|
1182
|
+
const cloned = i === SniffMethods.length - 1 ? response : response.clone();
|
|
1183
|
+
try {
|
|
1184
|
+
return await parser.method(cloned);
|
|
1185
|
+
} catch {
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
throw new VigorParseError("PARSER_ALL_FAILED", {
|
|
1189
|
+
method: "VigorParseSniffStrategy",
|
|
1190
|
+
data: { tried: SniffMethods.map((p) => p.title) }
|
|
1191
|
+
});
|
|
1192
|
+
};
|
|
1193
|
+
var VigorParsePolicyStrategies = class _VigorParsePolicyStrategies extends VigorStatus {
|
|
1194
|
+
constructor(config = VigorParseBase) {
|
|
1195
|
+
super(VigorParseBase, config);
|
|
1196
|
+
}
|
|
1197
|
+
_create(config) {
|
|
1198
|
+
return new _VigorParsePolicyStrategies(config);
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* Adds strategy functions to the fallback chain.
|
|
1202
|
+
*
|
|
1203
|
+
* @param replace - When `true`, replaces the existing chain instead of
|
|
1204
|
+
* appending to it (the default is to concat, since strategies are
|
|
1205
|
+
* tried in sequence as a fallback chain).
|
|
1206
|
+
*/
|
|
1207
|
+
_set(funcs, replace) {
|
|
1208
|
+
return this._next(
|
|
1209
|
+
{ policy: { strategies: { funcs } } },
|
|
1210
|
+
replace ? { policy: { strategies: { funcs: "replace" } } } : void 0
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
/** Adds the content-type based parsing strategy. */
|
|
1214
|
+
contentType(replace) {
|
|
1215
|
+
return this._set([VigorParseContentTypeStrategy], replace);
|
|
1216
|
+
}
|
|
1217
|
+
/** Adds the sniffing (try-each-method) parsing strategy. */
|
|
1218
|
+
sniff(replace) {
|
|
1219
|
+
return this._set([VigorParseSniffStrategy], replace);
|
|
1220
|
+
}
|
|
1221
|
+
/** Adds a strategy that always parses the response as JSON. */
|
|
1222
|
+
json(replace) {
|
|
1223
|
+
return this._set([(res) => res.json()], replace);
|
|
1224
|
+
}
|
|
1225
|
+
/** Adds a strategy that always parses the response as text. */
|
|
1226
|
+
text(replace) {
|
|
1227
|
+
return this._set([(res) => res.text()], replace);
|
|
1228
|
+
}
|
|
1229
|
+
/** Adds a strategy that always parses the response as an `ArrayBuffer`. */
|
|
1230
|
+
arrayBuffer(replace) {
|
|
1231
|
+
return this._set([(res) => res.arrayBuffer()], replace);
|
|
1232
|
+
}
|
|
1233
|
+
/** Adds a strategy that always parses the response as a `Blob`. */
|
|
1234
|
+
blob(replace) {
|
|
1235
|
+
return this._set([(res) => res.blob()], replace);
|
|
1236
|
+
}
|
|
1237
|
+
/** Adds a strategy that always parses the response as a `Uint8Array`. */
|
|
1238
|
+
bytes(replace) {
|
|
1239
|
+
return this._set([(res) => res.arrayBuffer().then((b) => new Uint8Array(b))], replace);
|
|
1240
|
+
}
|
|
1241
|
+
/** Adds a strategy that always parses the response as `FormData`. */
|
|
1242
|
+
formData(replace) {
|
|
1243
|
+
return this._set([(res) => res.formData()], replace);
|
|
1244
|
+
}
|
|
1245
|
+
/** Adds a user-supplied custom parsing strategy. */
|
|
1246
|
+
custom(func, replace) {
|
|
1247
|
+
return this._set([func], replace);
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
|
|
1251
|
+
// src/parse/policy.ts
|
|
1252
|
+
var VigorParsePolicyBase = {
|
|
1253
|
+
__brand: createBrand("Parse", "Policy<Schema"),
|
|
1254
|
+
target: VigorDefault,
|
|
1255
|
+
settings: VigorParsePolicySettingsBase,
|
|
1256
|
+
middlewares: VigorParsePolicyMiddlewaresBase,
|
|
1257
|
+
strategies: VigorParsePolicyStrategiesBase
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
// src/parse/context.ts
|
|
1261
|
+
var VigorParseContextBase = {
|
|
1262
|
+
__brand: createBrand("Parse", "Context<Schema"),
|
|
1263
|
+
result: VigorDefault,
|
|
1264
|
+
error: VigorDefault,
|
|
1265
|
+
response: VigorDefault,
|
|
1266
|
+
flags: {
|
|
1267
|
+
overrided: false,
|
|
1268
|
+
restarted: false
|
|
1269
|
+
},
|
|
1270
|
+
record: {},
|
|
1271
|
+
policy: VigorParsePolicyBase
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
// src/parse/main.ts
|
|
1275
|
+
var VigorParseBase = {
|
|
1276
|
+
__brand: createBrand("Parse", "Schema"),
|
|
1277
|
+
policy: VigorParsePolicyBase,
|
|
1278
|
+
context: VigorParseContextBase
|
|
1279
|
+
};
|
|
1280
|
+
var VigorParse = class _VigorParse extends VigorStatus {
|
|
1281
|
+
constructor(config = VigorParseBase) {
|
|
1282
|
+
super(VigorParseBase, config);
|
|
1283
|
+
}
|
|
1284
|
+
_create(config) {
|
|
1285
|
+
return new _VigorParse(config);
|
|
1286
|
+
}
|
|
1287
|
+
/** Sets the `Response` object to parse. */
|
|
1288
|
+
target(response) {
|
|
1289
|
+
return this._next({ policy: { target: response } });
|
|
1290
|
+
}
|
|
1291
|
+
/** Configures the parse policy's general settings. */
|
|
1292
|
+
settings(input) {
|
|
1293
|
+
if (typeof input === "function" || input instanceof VigorParsePolicySettings) {
|
|
1294
|
+
const result = typeof input === "function" ? input(new VigorParsePolicySettings()) : input;
|
|
1295
|
+
return this._next({
|
|
1296
|
+
policy: { settings: result.config.policy.settings }
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
return this._next({ policy: { settings: input } });
|
|
1300
|
+
}
|
|
1301
|
+
/** Configures the parse policy's middleware pipeline. */
|
|
1302
|
+
middlewares(input) {
|
|
1303
|
+
if (typeof input === "function" || input instanceof VigorParsePolicyMiddlewares) {
|
|
1304
|
+
const result = typeof input === "function" ? input(new VigorParsePolicyMiddlewares()) : input;
|
|
1305
|
+
return this._next({
|
|
1306
|
+
policy: { middlewares: result.config.policy.middlewares }
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1309
|
+
return this._next({ policy: { middlewares: input } });
|
|
1310
|
+
}
|
|
1311
|
+
/** Configures the parse policy's fallback chain of parsing strategies. */
|
|
1312
|
+
strategies(input) {
|
|
1313
|
+
if (typeof input === "function" || input instanceof VigorParsePolicyStrategies) {
|
|
1314
|
+
const result = typeof input === "function" ? input(new VigorParsePolicyStrategies()) : input;
|
|
1315
|
+
return this._next({
|
|
1316
|
+
policy: { strategies: result.config.policy.strategies }
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
return this._next({ policy: { strategies: input } });
|
|
1320
|
+
}
|
|
1321
|
+
/** Runs parsing and returns the result directly, throwing on final failure. */
|
|
1322
|
+
async request() {
|
|
1323
|
+
const res = await this.requestVerbose();
|
|
1324
|
+
if (res.success) return res.data;
|
|
1325
|
+
throw res.error;
|
|
1326
|
+
}
|
|
1327
|
+
/** Runs parsing and returns a result/error envelope instead of throwing. */
|
|
1328
|
+
async requestVerbose() {
|
|
1329
|
+
return await this.requestRuntime();
|
|
1330
|
+
}
|
|
1331
|
+
/** Internal execution loop implementing the strategy fallback and restart handling. */
|
|
1332
|
+
async requestRuntime(restartAttempt = 1) {
|
|
1333
|
+
const config = this._merge(this.config, {});
|
|
1334
|
+
let ctx = {
|
|
1335
|
+
...config.context,
|
|
1336
|
+
policy: config.policy
|
|
1337
|
+
};
|
|
1338
|
+
if (isVigorDefault(ctx.policy.target)) throw new VigorParseError("VALUE_REQUIRED", {
|
|
1339
|
+
method: "request",
|
|
1340
|
+
data: { key: "target" },
|
|
1341
|
+
context: ctx
|
|
1342
|
+
});
|
|
1343
|
+
ctx.response = ctx.policy.target;
|
|
1344
|
+
const throwError = (err) => {
|
|
1345
|
+
throw err;
|
|
1346
|
+
};
|
|
1347
|
+
try {
|
|
1348
|
+
for (const middleware of ctx.policy.middlewares.before) {
|
|
1349
|
+
if (middleware._mode === "fluent") {
|
|
1350
|
+
await middleware.func(ctx);
|
|
1351
|
+
} else {
|
|
1352
|
+
ctx = await middleware.func(ctx, { throwError });
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
const response = ctx.response;
|
|
1356
|
+
if (ctx.policy.settings.raw) {
|
|
1357
|
+
ctx.result = response;
|
|
1358
|
+
} else {
|
|
1359
|
+
const funcs = ctx.policy.strategies.funcs.length > 0 ? ctx.policy.strategies.funcs : [VigorParseContentTypeStrategy];
|
|
1360
|
+
let parsed = false;
|
|
1361
|
+
for (const [i, func] of funcs.entries()) {
|
|
1362
|
+
const cloned = i === funcs.length - 1 ? response : response.clone();
|
|
1363
|
+
try {
|
|
1364
|
+
ctx.result = await func(cloned);
|
|
1365
|
+
parsed = true;
|
|
1366
|
+
break;
|
|
1367
|
+
} catch {
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
if (!parsed) throw new VigorParseError("PARSER_ALL_FAILED", {
|
|
1371
|
+
method: "request",
|
|
1372
|
+
data: { tried: funcs.map((_, i) => `strategy#${i}`) },
|
|
1373
|
+
context: ctx
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
const setResult = (res) => {
|
|
1377
|
+
ctx.result = res;
|
|
1378
|
+
};
|
|
1379
|
+
for (const middleware of ctx.policy.middlewares.after) {
|
|
1380
|
+
if (middleware._mode === "fluent") {
|
|
1381
|
+
await middleware.func(ctx);
|
|
1382
|
+
} else {
|
|
1383
|
+
ctx = await middleware.func(ctx, { setResult, throwError });
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
for (const middleware of ctx.policy.middlewares.onResult) {
|
|
1387
|
+
if (middleware._mode === "fluent") {
|
|
1388
|
+
ctx.result = await middleware.func(ctx.result);
|
|
1389
|
+
} else {
|
|
1390
|
+
ctx = await middleware.func(ctx, { setResult, throwError });
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
return {
|
|
1394
|
+
success: true,
|
|
1395
|
+
data: ctx.result,
|
|
1396
|
+
error: null
|
|
1397
|
+
};
|
|
1398
|
+
} catch (error) {
|
|
1399
|
+
ctx.error = error;
|
|
1400
|
+
ctx.flags.overrided = false;
|
|
1401
|
+
ctx.flags.restarted = false;
|
|
1402
|
+
const setResult = (res) => {
|
|
1403
|
+
ctx.flags.overrided = true;
|
|
1404
|
+
ctx.result = res;
|
|
1405
|
+
};
|
|
1406
|
+
const proceedRestart = () => ctx.flags.restarted = true;
|
|
1407
|
+
const cancelRestart = () => ctx.flags.restarted = false;
|
|
1408
|
+
for (const middleware of ctx.policy.middlewares.onError) {
|
|
1409
|
+
if (middleware._mode === "fluent") {
|
|
1410
|
+
await middleware.func(ctx.error);
|
|
1411
|
+
} else {
|
|
1412
|
+
ctx = await middleware.func(ctx, { setResult, throwError, proceedRestart, cancelRestart });
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
if (ctx.flags.restarted) {
|
|
1416
|
+
if (restartAttempt + 1 > ctx.policy.settings.maxRestarts) throw new VigorParseError("RESTART_EXHAUSTED", {
|
|
1417
|
+
method: "request",
|
|
1418
|
+
cause: ctx.error,
|
|
1419
|
+
data: {
|
|
1420
|
+
maxAttempts: ctx.policy.settings.maxRestarts,
|
|
1421
|
+
error: ctx.error
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
return await this.requestRuntime(restartAttempt + 1);
|
|
1425
|
+
}
|
|
1426
|
+
if (ctx.flags.overrided) return {
|
|
1427
|
+
success: true,
|
|
1428
|
+
data: ctx.result,
|
|
1429
|
+
error: null
|
|
1430
|
+
};
|
|
1431
|
+
if (!isVigorEmpty(ctx.policy.settings.default)) {
|
|
1432
|
+
const data = await ctx.policy.settings.default(ctx);
|
|
1433
|
+
return {
|
|
1434
|
+
success: true,
|
|
1435
|
+
data,
|
|
1436
|
+
error: null
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
return {
|
|
1440
|
+
success: false,
|
|
1441
|
+
data: null,
|
|
1442
|
+
error: ctx.error
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
|
|
1448
|
+
// src/fetch/policy.ts
|
|
1449
|
+
var VigorFetchPolicyBase = {
|
|
1450
|
+
__brand: createBrand("Fetch", "Policy<Schema"),
|
|
1451
|
+
method: VigorEmpty,
|
|
1452
|
+
origin: VigorEmpty,
|
|
1453
|
+
path: [],
|
|
1454
|
+
query: [],
|
|
1455
|
+
hash: "",
|
|
1456
|
+
headers: {},
|
|
1457
|
+
body: VigorEmpty,
|
|
1458
|
+
extra: {},
|
|
1459
|
+
settings: VigorFetchPolicySettingsBase,
|
|
1460
|
+
middlewares: VigorFetchPolicyMiddlewaresBase,
|
|
1461
|
+
retry: VigorRetryBase,
|
|
1462
|
+
parse: VigorParseBase
|
|
1463
|
+
};
|
|
1464
|
+
|
|
1465
|
+
// src/fetch/context.ts
|
|
1466
|
+
var VigorFetchContextBase = {
|
|
1467
|
+
__brand: createBrand("Fetch", "Context<Schema"),
|
|
1468
|
+
href: "",
|
|
1469
|
+
response: VigorDefault,
|
|
1470
|
+
result: VigorDefault,
|
|
1471
|
+
error: VigorDefault,
|
|
1472
|
+
options: VigorDefault,
|
|
1473
|
+
flags: {
|
|
1474
|
+
overrided: false,
|
|
1475
|
+
restarted: false
|
|
1476
|
+
},
|
|
1477
|
+
record: {},
|
|
1478
|
+
policy: VigorFetchPolicyBase
|
|
1479
|
+
};
|
|
1480
|
+
|
|
1481
|
+
// src/fetch/error.ts
|
|
1482
|
+
var VigorFetchErrorMessageFuncs = {
|
|
1483
|
+
VALUE_REQUIRED: ({ key }) => `Value Required (missing ${key})`,
|
|
1484
|
+
INVALID_BODY: ({ received }) => `Invalid Body type: ${typeof received}`,
|
|
1485
|
+
INVALID_PROTOCOL: ({ origin, base }) => base ? `Invalid URL: could not resolve "${origin}" against base "${base}"` : `Invalid URL: "${origin}" is not an absolute URL, and no base (window.location) is available to resolve it against \u2014 pass an absolute origin (e.g. "https://api.example.com") when running outside a browser`,
|
|
1486
|
+
FETCH_FAILED: ({ status, statusText }) => `Fetch Failed: ${status} ${statusText}`,
|
|
1487
|
+
RESTART_EXHAUSTED: ({ maxAttempts }) => `Restart exhausted, (max ${maxAttempts})`
|
|
1488
|
+
};
|
|
1489
|
+
var VigorFetchError = class extends VigorError {
|
|
1490
|
+
/**
|
|
1491
|
+
* @param code - One of the fetch module's error codes.
|
|
1492
|
+
* @param options - Error metadata, including the `data` payload for `code`.
|
|
1493
|
+
*/
|
|
1494
|
+
constructor(code, options) {
|
|
1495
|
+
const messageFn = VigorFetchErrorMessageFuncs[code];
|
|
1496
|
+
super(code, messageFn(options.data), options);
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
|
|
1500
|
+
// src/fetch/main.ts
|
|
1501
|
+
var VigorFetchBase = {
|
|
1502
|
+
__brand: createBrand("Fetch", "Schema"),
|
|
1503
|
+
policy: VigorFetchPolicyBase,
|
|
1504
|
+
context: VigorFetchContextBase
|
|
1505
|
+
};
|
|
1506
|
+
var VigorFetch = class _VigorFetch extends VigorStatus {
|
|
1507
|
+
constructor(config = VigorFetchBase) {
|
|
1508
|
+
super(VigorFetchBase, config);
|
|
1509
|
+
}
|
|
1510
|
+
_create(config) {
|
|
1511
|
+
return new _VigorFetch(config);
|
|
1512
|
+
}
|
|
1513
|
+
/** Sets the HTTP method. Defaults to `POST` when a body is set, otherwise `GET`. */
|
|
1514
|
+
method(str) {
|
|
1515
|
+
return this._next({ policy: { method: str } });
|
|
1516
|
+
}
|
|
1517
|
+
/** Sets the request origin, either an absolute URL or a path relative to the current page. */
|
|
1518
|
+
origin(str) {
|
|
1519
|
+
return this._next({ policy: { origin: str } });
|
|
1520
|
+
}
|
|
1521
|
+
/** Appends path segments to the request URL. */
|
|
1522
|
+
path(...strs) {
|
|
1523
|
+
return this._next({ policy: { path: this._stringifyList(strs) } });
|
|
1524
|
+
}
|
|
1525
|
+
/** Adds query-string parameter objects to the request URL. */
|
|
1526
|
+
query(...objs) {
|
|
1527
|
+
return this._next({ policy: { query: objs } });
|
|
1528
|
+
}
|
|
1529
|
+
/** Sets the URL fragment ("hash"), replacing any previous value. */
|
|
1530
|
+
hash(str) {
|
|
1531
|
+
return this._next({ policy: { hash: str } }, { policy: { hash: "replace" } });
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1534
|
+
* Sets request headers.
|
|
1535
|
+
*
|
|
1536
|
+
* @param mode - `"overwrite"` discards all previously configured headers
|
|
1537
|
+
* and keeps only the ones passed here. `"merge"` behaves like
|
|
1538
|
+
* `Object.assign`, overwriting only the keys that overlap and keeping
|
|
1539
|
+
* the rest.
|
|
1540
|
+
*/
|
|
1541
|
+
headers(mode, obj) {
|
|
1542
|
+
if (mode === "overwrite") return this._next({ policy: { headers: obj } }, { policy: { headers: "replace" } });
|
|
1543
|
+
return this._next({ policy: { headers: obj } });
|
|
1544
|
+
}
|
|
1545
|
+
/**
|
|
1546
|
+
* Sets the request body.
|
|
1547
|
+
*
|
|
1548
|
+
* @param mode - `"overwrite"` discards the previous body and fully
|
|
1549
|
+
* replaces it with this value. `"merge"` shallow-merges (via
|
|
1550
|
+
* `Object.assign`) when both the previous and new body are plain
|
|
1551
|
+
* objects; for any other body type (string/Blob/FormData/etc) it is
|
|
1552
|
+
* simply replaced.
|
|
1553
|
+
*/
|
|
1554
|
+
body(mode, obj) {
|
|
1555
|
+
if (mode === "overwrite") return this._next({ policy: { body: obj } }, { policy: { body: "replace" } });
|
|
1556
|
+
return this._next({ policy: { body: obj } });
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Sets additional `RequestInit` options other than headers/body/method/signal
|
|
1560
|
+
* (e.g. `credentials`, `mode`, `cache`, `redirect`, `referrer`,
|
|
1561
|
+
* `referrerPolicy`, `keepalive`, `integrity`).
|
|
1562
|
+
*
|
|
1563
|
+
* @param mode - `"overwrite"` discards all previously configured options
|
|
1564
|
+
* and replaces them with this value. `"merge"` shallow-merges this
|
|
1565
|
+
* value onto the previous options.
|
|
1566
|
+
*/
|
|
1567
|
+
options(mode, obj) {
|
|
1568
|
+
if (mode === "overwrite") return this._next({ policy: { extra: obj } }, { policy: { extra: "replace" } });
|
|
1569
|
+
return this._next({ policy: { extra: obj } });
|
|
1570
|
+
}
|
|
1571
|
+
/** Configures the fetch policy's general settings. */
|
|
1572
|
+
settings(input) {
|
|
1573
|
+
if (typeof input === "function" || input instanceof VigorFetchPolicySettings) {
|
|
1574
|
+
const result = typeof input === "function" ? input(new VigorFetchPolicySettings()) : input;
|
|
1575
|
+
return this._next(
|
|
1576
|
+
{ policy: { settings: result.config.policy.settings } }
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
return this._next({ policy: { settings: input } });
|
|
1580
|
+
}
|
|
1581
|
+
/** Configures the fetch policy's middleware pipeline. */
|
|
1582
|
+
middlewares(input) {
|
|
1583
|
+
if (typeof input === "function" || input instanceof VigorFetchPolicyMiddlewares) {
|
|
1584
|
+
const result = typeof input === "function" ? input(new VigorFetchPolicyMiddlewares()) : input;
|
|
1585
|
+
return this._next(
|
|
1586
|
+
{ policy: { middlewares: result.config.policy.middlewares } }
|
|
1587
|
+
);
|
|
1588
|
+
}
|
|
1589
|
+
return this._next({ policy: { middlewares: input } });
|
|
1590
|
+
}
|
|
1591
|
+
/** Configures the retry engine used to send the underlying request. */
|
|
1592
|
+
retry(input) {
|
|
1593
|
+
if (typeof input === "function" || input instanceof VigorRetry) {
|
|
1594
|
+
const result = typeof input === "function" ? input(new VigorRetry()) : input;
|
|
1595
|
+
return this._next({ policy: { retry: result.config } }, { policy: { retry: "replace" } });
|
|
1596
|
+
}
|
|
1597
|
+
return this._next({ policy: { retry: input } }, { policy: { retry: "replace" } });
|
|
1598
|
+
}
|
|
1599
|
+
/** Configures the parse engine used to interpret the response. */
|
|
1600
|
+
parse(input) {
|
|
1601
|
+
if (typeof input === "function" || input instanceof VigorParse) {
|
|
1602
|
+
const result = typeof input === "function" ? input(new VigorParse()) : input;
|
|
1603
|
+
return this._next({ policy: { parse: result.config } }, { policy: { parse: "replace" } });
|
|
1604
|
+
}
|
|
1605
|
+
return this._next({ policy: { parse: input } }, { policy: { parse: "replace" } });
|
|
1606
|
+
}
|
|
1607
|
+
/** Converts a list of stringable values into strings, dropping `null`/`undefined` entries. */
|
|
1608
|
+
_stringifyList(unkList) {
|
|
1609
|
+
return unkList.filter((unk) => unk !== null && unk !== void 0).map((unk) => unk instanceof Date ? unk.toISOString() : String(unk));
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Resolves the base URL used to interpret a relative `origin`. In a
|
|
1613
|
+
* browser environment this is the current page location; in
|
|
1614
|
+
* environments without `location` (e.g. Node), no base is available and
|
|
1615
|
+
* `origin` must be an absolute URL.
|
|
1616
|
+
*/
|
|
1617
|
+
_resolveBase() {
|
|
1618
|
+
if (typeof globalThis !== "undefined" && globalThis.location?.href) {
|
|
1619
|
+
return globalThis.location.href;
|
|
1620
|
+
}
|
|
1621
|
+
return void 0;
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Builds the final request URL from the configured origin, path
|
|
1625
|
+
* segments, query parameters, and hash. An absolute `origin` ignores
|
|
1626
|
+
* the resolved base (per the `URL` spec); a relative `origin` is
|
|
1627
|
+
* resolved against it. Throws `INVALID_PROTOCOL` if neither is possible.
|
|
1628
|
+
*/
|
|
1629
|
+
_buildUrl(origin, path, query, hash) {
|
|
1630
|
+
const base = this._resolveBase();
|
|
1631
|
+
let originObj;
|
|
1632
|
+
try {
|
|
1633
|
+
originObj = new URL(origin, base);
|
|
1634
|
+
} catch {
|
|
1635
|
+
throw new VigorFetchError("INVALID_PROTOCOL", {
|
|
1636
|
+
method: "_buildUrl",
|
|
1637
|
+
data: { origin, base }
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
const baseStr = originObj.origin;
|
|
1641
|
+
const pathParts = [originObj.pathname.replace(/^\/+|\/+$/g, "")];
|
|
1642
|
+
for (const p of path) pathParts.push(p.replace(/^\/+|\/+$/g, ""));
|
|
1643
|
+
const pathStr = pathParts.filter(Boolean).join("/");
|
|
1644
|
+
const mainObj = new URL(pathStr, baseStr);
|
|
1645
|
+
const parseVal = (val) => val instanceof Date ? val.toISOString() : String(val);
|
|
1646
|
+
const queryEntries = [...originObj.searchParams.entries(), ...query.flatMap((q) => Object.entries(q))];
|
|
1647
|
+
for (const [key, val] of queryEntries) {
|
|
1648
|
+
if (val === void 0 || val === null) continue;
|
|
1649
|
+
if (Array.isArray(val)) {
|
|
1650
|
+
for (const e of val) mainObj.searchParams.append(key, parseVal(e));
|
|
1651
|
+
} else {
|
|
1652
|
+
mainObj.searchParams.append(key, parseVal(val));
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
mainObj.hash = hash || originObj.hash;
|
|
1656
|
+
return mainObj.href;
|
|
1657
|
+
}
|
|
1658
|
+
/** Infers the `Content-Type` header and serializes `body` into a `BodyInit`. */
|
|
1659
|
+
_normalizeBody(body) {
|
|
1660
|
+
if (body == null) return { headers: {}, body };
|
|
1661
|
+
if (typeof body === "string") return { headers: { "Content-Type": "text/plain;charset=UTF-8" }, body };
|
|
1662
|
+
if (body instanceof Blob) return { headers: body.type ? { "Content-Type": body.type } : {}, body };
|
|
1663
|
+
if (body instanceof ArrayBuffer) return { headers: { "Content-Type": "application/octet-stream" }, body };
|
|
1664
|
+
if (body instanceof URLSearchParams) return { headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" }, body };
|
|
1665
|
+
if (body instanceof FormData) return { headers: {}, body };
|
|
1666
|
+
if (typeof body === "object") return { headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) };
|
|
1667
|
+
throw new VigorFetchError("INVALID_BODY", {
|
|
1668
|
+
method: "_normalizeBody",
|
|
1669
|
+
data: { received: body }
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
/** Runs the request and returns its parsed result directly, throwing on final failure. */
|
|
1673
|
+
async request() {
|
|
1674
|
+
const res = await this.requestVerbose();
|
|
1675
|
+
if (res.success) return res.data;
|
|
1676
|
+
throw res.error;
|
|
1677
|
+
}
|
|
1678
|
+
/** Runs the request and returns a result/error envelope instead of throwing. */
|
|
1679
|
+
async requestVerbose() {
|
|
1680
|
+
return await this.requestRuntime();
|
|
1681
|
+
}
|
|
1682
|
+
/** Internal execution loop implementing URL building, retry, parsing, and restart handling. */
|
|
1683
|
+
async requestRuntime(restartAttempt = 1) {
|
|
1684
|
+
const config = this._merge(this.config, {});
|
|
1685
|
+
let ctx = {
|
|
1686
|
+
...config.context,
|
|
1687
|
+
policy: config.policy
|
|
1688
|
+
};
|
|
1689
|
+
const throwError = (err) => {
|
|
1690
|
+
throw err;
|
|
1691
|
+
};
|
|
1692
|
+
try {
|
|
1693
|
+
if (isVigorEmpty(ctx.policy.origin)) throw new VigorFetchError("VALUE_REQUIRED", {
|
|
1694
|
+
method: "request",
|
|
1695
|
+
data: { key: "origin" }
|
|
1696
|
+
});
|
|
1697
|
+
ctx.href = this._buildUrl(ctx.policy.origin, ctx.policy.path, ctx.policy.query, ctx.policy.hash);
|
|
1698
|
+
const hasBody = !isVigorEmpty(ctx.policy.body) && ctx.policy.body !== void 0;
|
|
1699
|
+
const method = isVigorEmpty(ctx.policy.method) ? hasBody ? "POST" : "GET" : ctx.policy.method;
|
|
1700
|
+
let options = {
|
|
1701
|
+
...ctx.policy.extra,
|
|
1702
|
+
method,
|
|
1703
|
+
headers: {}
|
|
1704
|
+
};
|
|
1705
|
+
if (hasBody) {
|
|
1706
|
+
const normalized = this._normalizeBody(ctx.policy.body);
|
|
1707
|
+
if (normalized.body !== void 0) options.body = normalized.body;
|
|
1708
|
+
Object.assign(options.headers, normalized.headers);
|
|
1709
|
+
}
|
|
1710
|
+
Object.assign(options.headers, ctx.policy.headers);
|
|
1711
|
+
for (const middleware of ctx.policy.middlewares.before) {
|
|
1712
|
+
if (middleware._mode === "fluent") {
|
|
1713
|
+
await middleware.func(ctx);
|
|
1714
|
+
} else {
|
|
1715
|
+
ctx = await middleware.func(ctx, {
|
|
1716
|
+
throwError,
|
|
1717
|
+
setOptions: (o) => {
|
|
1718
|
+
options = o;
|
|
1719
|
+
},
|
|
1720
|
+
setHeaders: (h) => {
|
|
1721
|
+
options.headers = h;
|
|
1722
|
+
},
|
|
1723
|
+
setBody: (b) => {
|
|
1724
|
+
options.body = b;
|
|
1725
|
+
}
|
|
1726
|
+
});
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
ctx.options = options;
|
|
1730
|
+
const retryEngine = new VigorRetry(ctx.policy.retry).target(async (signal) => {
|
|
1731
|
+
return await fetch(ctx.href, { ...options, signal });
|
|
1732
|
+
}).middlewares(
|
|
1733
|
+
(m) => m.after("intercept", async (rctx, api) => {
|
|
1734
|
+
const response = rctx.result;
|
|
1735
|
+
if (!response.ok) {
|
|
1736
|
+
let parsed = void 0;
|
|
1737
|
+
try {
|
|
1738
|
+
parsed = await new VigorParse(ctx.policy.parse).target(response.clone()).request();
|
|
1739
|
+
} catch {
|
|
1740
|
+
}
|
|
1741
|
+
api.throwError(new VigorFetchError("FETCH_FAILED", {
|
|
1742
|
+
method: "request",
|
|
1743
|
+
data: {
|
|
1744
|
+
status: response.status,
|
|
1745
|
+
statusText: response.statusText,
|
|
1746
|
+
response,
|
|
1747
|
+
url: response.url,
|
|
1748
|
+
parsed
|
|
1749
|
+
}
|
|
1750
|
+
}));
|
|
1751
|
+
}
|
|
1752
|
+
return rctx;
|
|
1753
|
+
}).retryIf("intercept", async (rctx, api) => {
|
|
1754
|
+
const response = rctx.error instanceof VigorFetchError ? rctx.error.data?.response : void 0;
|
|
1755
|
+
if (response && ctx.policy.settings.unretryStatus.includes(response.status)) api.cancelRetry();
|
|
1756
|
+
else api.proceedRetry();
|
|
1757
|
+
return rctx;
|
|
1758
|
+
}).onRetry("intercept", async (rctx, api) => {
|
|
1759
|
+
const response = rctx.error instanceof VigorFetchError ? rctx.error.data?.response : void 0;
|
|
1760
|
+
if (response?.status === 429) {
|
|
1761
|
+
let retryHeader = null;
|
|
1762
|
+
for (const header of ctx.policy.settings.retryHeaders) {
|
|
1763
|
+
retryHeader = response.headers.get(header);
|
|
1764
|
+
if (retryHeader) break;
|
|
1765
|
+
}
|
|
1766
|
+
if (retryHeader) {
|
|
1767
|
+
const toNumber = Number(retryHeader);
|
|
1768
|
+
const delay = !isNaN(toNumber) ? toNumber * 1e3 : (() => {
|
|
1769
|
+
const toDate = new Date(retryHeader).getTime();
|
|
1770
|
+
return !isNaN(toDate) ? toDate - Date.now() : null;
|
|
1771
|
+
})();
|
|
1772
|
+
if (delay !== null && delay > 0) api.setDelay(delay);
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
return rctx;
|
|
1776
|
+
})
|
|
1777
|
+
);
|
|
1778
|
+
ctx.response = await retryEngine.request();
|
|
1779
|
+
const parseEngine = new VigorParse(ctx.policy.parse).target(ctx.response);
|
|
1780
|
+
ctx.result = await parseEngine.request();
|
|
1781
|
+
for (const middleware of ctx.policy.middlewares.after) {
|
|
1782
|
+
if (middleware._mode === "fluent") {
|
|
1783
|
+
await middleware.func(ctx);
|
|
1784
|
+
} else {
|
|
1785
|
+
ctx = await middleware.func(ctx, { throwError, setResult: (r) => {
|
|
1786
|
+
ctx.result = r;
|
|
1787
|
+
} });
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
const setResult = (r) => {
|
|
1791
|
+
ctx.result = r;
|
|
1792
|
+
};
|
|
1793
|
+
for (const middleware of ctx.policy.middlewares.onResult) {
|
|
1794
|
+
if (middleware._mode === "fluent") {
|
|
1795
|
+
ctx.result = await middleware.func(ctx.result);
|
|
1796
|
+
} else {
|
|
1797
|
+
ctx = await middleware.func(ctx, { setResult, throwError });
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
return {
|
|
1801
|
+
success: true,
|
|
1802
|
+
data: ctx.result,
|
|
1803
|
+
error: null
|
|
1804
|
+
};
|
|
1805
|
+
} catch (error) {
|
|
1806
|
+
ctx.error = error;
|
|
1807
|
+
ctx.flags.overrided = false;
|
|
1808
|
+
ctx.flags.restarted = false;
|
|
1809
|
+
const setResult = (r) => {
|
|
1810
|
+
ctx.flags.overrided = true;
|
|
1811
|
+
ctx.result = r;
|
|
1812
|
+
};
|
|
1813
|
+
const proceedRestart = () => ctx.flags.restarted = true;
|
|
1814
|
+
const cancelRestart = () => ctx.flags.restarted = false;
|
|
1815
|
+
for (const middleware of ctx.policy.middlewares.onError) {
|
|
1816
|
+
if (middleware._mode === "fluent") {
|
|
1817
|
+
await middleware.func(ctx.error);
|
|
1818
|
+
} else {
|
|
1819
|
+
ctx = await middleware.func(ctx, { setResult, throwError, proceedRestart, cancelRestart });
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
if (ctx.flags.restarted) {
|
|
1823
|
+
if (restartAttempt + 1 > ctx.policy.settings.maxRestarts) throw new VigorFetchError("RESTART_EXHAUSTED", {
|
|
1824
|
+
method: "request",
|
|
1825
|
+
cause: ctx.error,
|
|
1826
|
+
data: {
|
|
1827
|
+
maxAttempts: ctx.policy.settings.maxRestarts,
|
|
1828
|
+
error: ctx.error
|
|
1829
|
+
}
|
|
1830
|
+
});
|
|
1831
|
+
return await this.requestRuntime(restartAttempt + 1);
|
|
1832
|
+
}
|
|
1833
|
+
if (ctx.flags.overrided) return {
|
|
1834
|
+
success: true,
|
|
1835
|
+
data: ctx.result,
|
|
1836
|
+
error: null
|
|
1837
|
+
};
|
|
1838
|
+
if (!isVigorEmpty(ctx.policy.settings.default)) {
|
|
1839
|
+
const data = await ctx.policy.settings.default(ctx);
|
|
1840
|
+
return {
|
|
1841
|
+
success: true,
|
|
1842
|
+
data,
|
|
1843
|
+
error: null
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
return {
|
|
1847
|
+
success: false,
|
|
1848
|
+
data: null,
|
|
1849
|
+
error
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
};
|
|
1854
|
+
|
|
1855
|
+
// src/entry/main.ts
|
|
1856
|
+
var vigorBase = {
|
|
1857
|
+
retry: (...task) => task[0] !== void 0 ? new VigorRetry().target(task[0]) : new VigorRetry(),
|
|
1858
|
+
parse: (...response) => response[0] !== void 0 ? new VigorParse().target(response[0]) : new VigorParse(),
|
|
1859
|
+
fetch: (...origin) => origin[0] !== void 0 ? new VigorFetch().origin(origin[0]) : new VigorFetch(),
|
|
1860
|
+
all: (...tasks) => tasks.length > 0 ? new VigorAll().target(...tasks) : new VigorAll(),
|
|
1861
|
+
builders: {
|
|
1862
|
+
fetch: {
|
|
1863
|
+
settings: () => new VigorFetchPolicySettings(),
|
|
1864
|
+
middlewares: () => new VigorFetchPolicyMiddlewares()
|
|
1865
|
+
},
|
|
1866
|
+
retry: {
|
|
1867
|
+
settings: () => new VigorRetryPolicySettings(),
|
|
1868
|
+
middlewares: () => new VigorRetryPolicyMiddlewares(),
|
|
1869
|
+
algorithms: () => new VigorRetryPolicyAlgorithms(),
|
|
1870
|
+
algorithm: {
|
|
1871
|
+
constant: () => new VigorRetryPolicyAlgorithmsConstant(),
|
|
1872
|
+
linear: () => new VigorRetryPolicyAlgorithmsLinear(),
|
|
1873
|
+
backoff: () => new VigorRetryPolicyAlgorithmsBackoff(),
|
|
1874
|
+
custom: () => new VigorRetryPolicyAlgorithmsCustom()
|
|
1875
|
+
}
|
|
1876
|
+
},
|
|
1877
|
+
parse: {
|
|
1878
|
+
settings: () => new VigorParsePolicySettings(),
|
|
1879
|
+
middlewares: () => new VigorParsePolicyMiddlewares(),
|
|
1880
|
+
strategies: () => new VigorParsePolicyStrategies()
|
|
1881
|
+
},
|
|
1882
|
+
all: {
|
|
1883
|
+
settings: () => new VigorAllPolicySettings(),
|
|
1884
|
+
middlewares: () => new VigorAllPolicyMiddlewares()
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
};
|
|
1888
|
+
var cloneVigor = (v) => ({
|
|
1889
|
+
...v,
|
|
1890
|
+
builders: {
|
|
1891
|
+
fetch: { ...v.builders.fetch },
|
|
1892
|
+
retry: { ...v.builders.retry, algorithm: { ...v.builders.retry.algorithm } },
|
|
1893
|
+
parse: { ...v.builders.parse },
|
|
1894
|
+
all: { ...v.builders.all }
|
|
1895
|
+
}
|
|
1896
|
+
});
|
|
1897
|
+
var vigor = {
|
|
1898
|
+
...vigorBase,
|
|
1899
|
+
use: (plugin, options) => {
|
|
1900
|
+
const ext = plugin.func(vigor, options);
|
|
1901
|
+
return { ...cloneVigor(vigor), ...ext };
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
|
|
1905
|
+
// src/index.ts
|
|
1906
|
+
var index_default = vigor;
|
|
1907
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1908
|
+
0 && (module.exports = {
|
|
1909
|
+
VigorAll,
|
|
1910
|
+
VigorAllBase,
|
|
1911
|
+
VigorAllError,
|
|
1912
|
+
VigorAllErrorMessageFuncs,
|
|
1913
|
+
VigorAllPolicyBase,
|
|
1914
|
+
VigorAllPolicyMiddlewares,
|
|
1915
|
+
VigorAllPolicyMiddlewaresBase,
|
|
1916
|
+
VigorAllPolicySettings,
|
|
1917
|
+
VigorAllPolicySettingsBase,
|
|
1918
|
+
VigorError,
|
|
1919
|
+
VigorFetch,
|
|
1920
|
+
VigorFetchBase,
|
|
1921
|
+
VigorFetchError,
|
|
1922
|
+
VigorFetchErrorMessageFuncs,
|
|
1923
|
+
VigorFetchPolicyBase,
|
|
1924
|
+
VigorFetchPolicyMiddlewares,
|
|
1925
|
+
VigorFetchPolicyMiddlewaresBase,
|
|
1926
|
+
VigorFetchPolicySettings,
|
|
1927
|
+
VigorFetchPolicySettingsBase,
|
|
1928
|
+
VigorJitter,
|
|
1929
|
+
VigorParse,
|
|
1930
|
+
VigorParseBase,
|
|
1931
|
+
VigorParseContentTypeStrategy,
|
|
1932
|
+
VigorParseError,
|
|
1933
|
+
VigorParseErrorMessageFuncs,
|
|
1934
|
+
VigorParsePolicyBase,
|
|
1935
|
+
VigorParsePolicyMiddlewares,
|
|
1936
|
+
VigorParsePolicyMiddlewaresBase,
|
|
1937
|
+
VigorParsePolicySettings,
|
|
1938
|
+
VigorParsePolicySettingsBase,
|
|
1939
|
+
VigorParsePolicyStrategies,
|
|
1940
|
+
VigorParsePolicyStrategiesBase,
|
|
1941
|
+
VigorParseSniffStrategy,
|
|
1942
|
+
VigorRetry,
|
|
1943
|
+
VigorRetryBase,
|
|
1944
|
+
VigorRetryError,
|
|
1945
|
+
VigorRetryErrorMessageFuncs,
|
|
1946
|
+
VigorRetryPolicyAlgorithms,
|
|
1947
|
+
VigorRetryPolicyAlgorithmsBackoff,
|
|
1948
|
+
VigorRetryPolicyAlgorithmsBackoffBase,
|
|
1949
|
+
VigorRetryPolicyAlgorithmsBase,
|
|
1950
|
+
VigorRetryPolicyAlgorithmsConstant,
|
|
1951
|
+
VigorRetryPolicyAlgorithmsConstantBase,
|
|
1952
|
+
VigorRetryPolicyAlgorithmsCustom,
|
|
1953
|
+
VigorRetryPolicyAlgorithmsCustomBase,
|
|
1954
|
+
VigorRetryPolicyAlgorithmsLinear,
|
|
1955
|
+
VigorRetryPolicyAlgorithmsLinearBase,
|
|
1956
|
+
VigorRetryPolicyBase,
|
|
1957
|
+
VigorRetryPolicyMiddlewares,
|
|
1958
|
+
VigorRetryPolicyMiddlewaresBase,
|
|
1959
|
+
VigorRetryPolicySettings,
|
|
1960
|
+
VigorRetryPolicySettingsBase,
|
|
1961
|
+
VigorStatus,
|
|
1962
|
+
vigor
|
|
1963
|
+
});
|