fetch-retrier 0.5.6 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -29
- package/lib/core/backoff/jitter.d.ts +13 -0
- package/lib/core/backoff/jitter.js +25 -0
- package/lib/core/backoff/retry-after.d.ts +27 -0
- package/lib/core/backoff/retry-after.js +61 -0
- package/lib/core/errors.d.ts +100 -0
- package/lib/core/errors.js +132 -0
- package/lib/core/fetch-retrier.d.ts +28 -0
- package/lib/core/fetch-retrier.js +86 -0
- package/lib/core/http/timed-fetch.d.ts +32 -0
- package/lib/core/http/timed-fetch.js +41 -0
- package/lib/core/options.d.ts +74 -0
- package/lib/core/options.js +6 -0
- package/lib/core/policy/default-should-retry.d.ts +18 -0
- package/lib/core/policy/default-should-retry.js +25 -0
- package/lib/core/policy/validate-options.d.ts +12 -0
- package/lib/core/policy/validate-options.js +31 -0
- package/lib/core/retry-predicates.d.ts +11 -0
- package/lib/core/retry-predicates.js +18 -0
- package/lib/core/time/wait.d.ts +7 -0
- package/lib/core/time/wait.js +14 -0
- package/lib/index.d.ts +5 -192
- package/lib/index.js +17 -304
- package/package.json +2 -1
package/lib/index.js
CHANGED
|
@@ -6,307 +6,20 @@
|
|
|
6
6
|
* @module fetch-retrier
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
exports.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*/
|
|
27
|
-
class FetchRetrierAlreadyAbortedError extends FetchRetrierAbortError {
|
|
28
|
-
/**
|
|
29
|
-
* @param message - Human-readable reason (default: `'Signal was already aborted'`)
|
|
30
|
-
*/
|
|
31
|
-
constructor(message = 'Signal was already aborted') {
|
|
32
|
-
super(message);
|
|
33
|
-
this.name = 'FetchRetrierAlreadyAbortedError';
|
|
34
|
-
Object.setPrototypeOf(this, FetchRetrierAlreadyAbortedError.prototype);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
exports.FetchRetrierAlreadyAbortedError = FetchRetrierAlreadyAbortedError;
|
|
38
|
-
/**
|
|
39
|
-
* Error thrown when the server returns a non-OK HTTP status and no further retry is performed.
|
|
40
|
-
*
|
|
41
|
-
* Carries the last response `status` and the body text already consumed via `response.text()`
|
|
42
|
-
* (the same text passed to {@link RequestOptions.shouldRetry}).
|
|
43
|
-
*
|
|
44
|
-
* @property status - HTTP status code from the last non-OK response
|
|
45
|
-
* @property body - Response body text already read via `response.text()` for that attempt
|
|
46
|
-
*/
|
|
47
|
-
class FetchRetrierHttpError extends Error {
|
|
48
|
-
/**
|
|
49
|
-
* @param message - Error description
|
|
50
|
-
* @param status - HTTP status code from the last non-OK response
|
|
51
|
-
* @param body - Response body text already read via `response.text()` for that attempt
|
|
52
|
-
*/
|
|
53
|
-
constructor(message, status, body) {
|
|
54
|
-
super(message);
|
|
55
|
-
this.status = status;
|
|
56
|
-
this.body = body;
|
|
57
|
-
this.name = 'FetchRetrierHttpError';
|
|
58
|
-
Object.setPrototypeOf(this, FetchRetrierHttpError.prototype);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
exports.FetchRetrierHttpError = FetchRetrierHttpError;
|
|
62
|
-
/**
|
|
63
|
-
* Error thrown when a fetch fails with a network-level error (e.g. DNS failure, connection refused).
|
|
64
|
-
*
|
|
65
|
-
* @property cause - Original error from the underlying `fetch`, when available
|
|
66
|
-
*/
|
|
67
|
-
class FetchRetrierNetworkError extends Error {
|
|
68
|
-
/**
|
|
69
|
-
* @param message - Human-readable reason (default: `'Network error'`)
|
|
70
|
-
* @param cause - Original error from the underlying `fetch`, when available
|
|
71
|
-
*/
|
|
72
|
-
constructor(message = 'Network error', cause) {
|
|
73
|
-
super(message);
|
|
74
|
-
this.cause = cause;
|
|
75
|
-
this.name = 'FetchRetrierNetworkError';
|
|
76
|
-
Object.setPrototypeOf(this, FetchRetrierNetworkError.prototype);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
exports.FetchRetrierNetworkError = FetchRetrierNetworkError;
|
|
80
|
-
/**
|
|
81
|
-
* Error thrown when {@link RequestOptions} contains invalid numeric values.
|
|
82
|
-
*
|
|
83
|
-
* Subclass of {@link TypeError} for compatibility with `instanceof TypeError`. Distinct from
|
|
84
|
-
* network-level `TypeError` values thrown by `fetch`, which are retried and surfaced as
|
|
85
|
-
* {@link FetchRetrierNetworkError} after the last attempt.
|
|
86
|
-
*/
|
|
87
|
-
class FetchRetrierInvalidOptionsError extends TypeError {
|
|
88
|
-
/**
|
|
89
|
-
* @param message - Human-readable reason describing the invalid option
|
|
90
|
-
*/
|
|
91
|
-
constructor(message) {
|
|
92
|
-
super(message);
|
|
93
|
-
this.name = 'FetchRetrierInvalidOptionsError';
|
|
94
|
-
Object.setPrototypeOf(this, FetchRetrierInvalidOptionsError.prototype);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
exports.FetchRetrierInvalidOptionsError = FetchRetrierInvalidOptionsError;
|
|
98
|
-
/**
|
|
99
|
-
* Error thrown when an internal invariant fails (should not happen in normal use).
|
|
100
|
-
*/
|
|
101
|
-
class FetchRetrierUnreachableError extends Error {
|
|
102
|
-
/**
|
|
103
|
-
* @param message - Human-readable reason (default: `'Unreachable'`)
|
|
104
|
-
*/
|
|
105
|
-
constructor(message = 'Unreachable') {
|
|
106
|
-
super(message);
|
|
107
|
-
this.name = 'FetchRetrierUnreachableError';
|
|
108
|
-
Object.setPrototypeOf(this, FetchRetrierUnreachableError.prototype);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
exports.FetchRetrierUnreachableError = FetchRetrierUnreachableError;
|
|
112
|
-
/**
|
|
113
|
-
* HTTP status codes retried by default when {@link RequestOptions.shouldRetry} is omitted.
|
|
114
|
-
*
|
|
115
|
-
* Includes transient client/server errors: 408, 425, 429, and common 5xx gateway or overload responses.
|
|
116
|
-
*/
|
|
117
|
-
exports.DEFAULT_RETRYABLE_HTTP_STATUSES = [408, 425, 429, 500, 502, 503, 504];
|
|
118
|
-
/**
|
|
119
|
-
* Default {@link RequestOptions.shouldRetry}: retries responses whose status is in
|
|
120
|
-
* {@link DEFAULT_RETRYABLE_HTTP_STATUSES}.
|
|
121
|
-
*
|
|
122
|
-
* Compose with custom logic, for example:
|
|
123
|
-
* `(res, body) => defaultShouldRetry(res, body) || res.status === 418`.
|
|
124
|
-
*
|
|
125
|
-
* @param response - Response from the failed attempt
|
|
126
|
-
* @param _body - Response body text (unused by the default predicate)
|
|
127
|
-
* @returns `true` when another attempt should be scheduled
|
|
128
|
-
*/
|
|
129
|
-
const defaultShouldRetry = (response, _body) => {
|
|
130
|
-
return exports.DEFAULT_RETRYABLE_HTTP_STATUSES.includes(response.status);
|
|
131
|
-
};
|
|
132
|
-
exports.defaultShouldRetry = defaultShouldRetry;
|
|
133
|
-
/**
|
|
134
|
-
* Validates retry policy numeric fields on {@link RequestOptions}.
|
|
135
|
-
*
|
|
136
|
-
* Constraints: `retries >= 1`, `timeoutMs > 0`, `baseBackoffMs >= 0`.
|
|
137
|
-
*
|
|
138
|
-
* @param options - Options whose `retries`, `timeoutMs`, and `baseBackoffMs` are checked
|
|
139
|
-
* @throws {FetchRetrierInvalidOptionsError} When any constraint is violated
|
|
140
|
-
*/
|
|
141
|
-
const validateRequestOptions = (options) => {
|
|
142
|
-
const { retries, timeoutMs, baseBackoffMs } = options;
|
|
143
|
-
if (retries < 1) {
|
|
144
|
-
throw new FetchRetrierInvalidOptionsError('retries must be >= 1');
|
|
145
|
-
}
|
|
146
|
-
if (timeoutMs <= 0) {
|
|
147
|
-
throw new FetchRetrierInvalidOptionsError('timeoutMs must be > 0');
|
|
148
|
-
}
|
|
149
|
-
if (baseBackoffMs < 0) {
|
|
150
|
-
throw new FetchRetrierInvalidOptionsError('baseBackoffMs must be >= 0');
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
/**
|
|
154
|
-
* Wraps `fetch` with retries, per-attempt timeout, Retry-After support, full-jitter backoff, and
|
|
155
|
-
* optional cancellation.
|
|
156
|
-
*
|
|
157
|
-
* Each attempt calls `fetch(url, { ...options.init, headers?, signal })` with an internal
|
|
158
|
-
* {@link AbortSignal} for `timeoutMs`. Non-OK responses are retried when `shouldRetry` returns
|
|
159
|
-
* `true` (default: {@link defaultShouldRetry}). Between HTTP retries, a valid `Retry-After`
|
|
160
|
-
* header (delta-seconds or HTTP-date) is preferred over full jitter; abort and network retries
|
|
161
|
-
* always use full jitter. The same {@link FetchInitOptions} (including `body`) is reused on
|
|
162
|
-
* every attempt.
|
|
163
|
-
*
|
|
164
|
-
* @param url - Request URL passed to `fetch`
|
|
165
|
-
* @param options - {@link RequestOptions} controlling retries, timeout, request init, and cancellation
|
|
166
|
-
* @returns The first {@link Response} for which `ok` is `true`
|
|
167
|
-
* @throws {FetchRetrierInvalidOptionsError} If `retries < 1`, `timeoutMs <= 0`, or `baseBackoffMs < 0`
|
|
168
|
-
* @throws {FetchRetrierAlreadyAbortedError} If `options.signal` is already aborted before an attempt
|
|
169
|
-
* @throws {FetchRetrierHttpError} On a non-OK response that is not retried or after the last attempt
|
|
170
|
-
* (includes `status` and `body`)
|
|
171
|
-
* @throws {FetchRetrierNetworkError} On a network `TypeError` after the last attempt
|
|
172
|
-
* @throws {FetchRetrierAbortError} On timeout or external abort after the last attempt
|
|
173
|
-
* @throws {FetchRetrierUnreachableError} If the retry loop exits without returning (internal bug)
|
|
174
|
-
*/
|
|
175
|
-
const fetchRetrier = async (url, options) => {
|
|
176
|
-
const { headers, init, retries, timeoutMs, baseBackoffMs, signal: externalSignal, shouldRetry = exports.defaultShouldRetry, } = options;
|
|
177
|
-
validateRequestOptions({ retries, timeoutMs, baseBackoffMs });
|
|
178
|
-
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
179
|
-
if (externalSignal?.aborted) {
|
|
180
|
-
throw new FetchRetrierAlreadyAbortedError();
|
|
181
|
-
}
|
|
182
|
-
const controller = new AbortController();
|
|
183
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
184
|
-
const onExternalAbort = () => {
|
|
185
|
-
clearTimeout(timer);
|
|
186
|
-
controller.abort();
|
|
187
|
-
};
|
|
188
|
-
if (externalSignal) {
|
|
189
|
-
externalSignal.addEventListener('abort', onExternalAbort);
|
|
190
|
-
}
|
|
191
|
-
try {
|
|
192
|
-
const res = await fetch(url, {
|
|
193
|
-
...init,
|
|
194
|
-
...(headers !== undefined ? { headers } : {}),
|
|
195
|
-
signal: controller.signal,
|
|
196
|
-
});
|
|
197
|
-
clearTimeout(timer);
|
|
198
|
-
externalSignal?.removeEventListener('abort', onExternalAbort);
|
|
199
|
-
if (res.ok) {
|
|
200
|
-
return res;
|
|
201
|
-
}
|
|
202
|
-
const text = await res.text();
|
|
203
|
-
const isContinue = shouldRetry(res, text);
|
|
204
|
-
if (isContinue) {
|
|
205
|
-
if (attempt === retries) {
|
|
206
|
-
throw new FetchRetrierHttpError(`HTTP ${res.status}`, res.status, text);
|
|
207
|
-
}
|
|
208
|
-
await wait(resolveRetryDelayMs(res, baseBackoffMs, attempt));
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
throw new FetchRetrierHttpError(`Non-retriable HTTP error: ${res.status}`, res.status, text);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
catch (err) {
|
|
215
|
-
clearTimeout(timer);
|
|
216
|
-
externalSignal?.removeEventListener('abort', onExternalAbort);
|
|
217
|
-
if (err instanceof Error && err.name === 'AbortError') {
|
|
218
|
-
if (attempt === retries)
|
|
219
|
-
throw err instanceof FetchRetrierAbortError ? err : new FetchRetrierAbortError();
|
|
220
|
-
await wait(fullJitter(baseBackoffMs, attempt));
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
if (err instanceof TypeError) {
|
|
224
|
-
if (attempt === retries)
|
|
225
|
-
throw new FetchRetrierNetworkError('Network error', err);
|
|
226
|
-
await wait(fullJitter(baseBackoffMs, attempt));
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
|
-
throw err;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
throw new FetchRetrierUnreachableError();
|
|
233
|
-
};
|
|
234
|
-
exports.fetchRetrier = fetchRetrier;
|
|
235
|
-
/**
|
|
236
|
-
* Delays execution for the given duration (used between retry attempts).
|
|
237
|
-
*
|
|
238
|
-
* @param ms - Delay in milliseconds
|
|
239
|
-
* @returns A promise that resolves after `ms`
|
|
240
|
-
*/
|
|
241
|
-
const wait = (ms) => {
|
|
242
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
243
|
-
};
|
|
244
|
-
/**
|
|
245
|
-
* Full jitter backoff: random delay in `[0, base * 2^attempt)` ms (AWS-recommended pattern).
|
|
246
|
-
*
|
|
247
|
-
* Used between abort/network retries, and as the fallback when HTTP retries lack a usable
|
|
248
|
-
* `Retry-After` header.
|
|
249
|
-
*
|
|
250
|
-
* @param base - Base backoff in milliseconds
|
|
251
|
-
* @param attempt - 1-based attempt index (first retry uses `attempt === 1`)
|
|
252
|
-
* @returns Wait duration in milliseconds before the next attempt
|
|
253
|
-
*/
|
|
254
|
-
const fullJitter = (base, attempt) => {
|
|
255
|
-
const cap = base * Math.pow(2, attempt);
|
|
256
|
-
return Math.floor(Math.random() * cap);
|
|
257
|
-
};
|
|
258
|
-
/**
|
|
259
|
-
* Parses a `Retry-After` header value into a delay in milliseconds.
|
|
260
|
-
*
|
|
261
|
-
* Supports RFC 7231 forms: non-negative integer delta-seconds, or an HTTP-date. Empty values,
|
|
262
|
-
* non-integer numerics (e.g. floats or negatives), and unparsable dates yield `undefined` so
|
|
263
|
-
* callers can fall back to full jitter. An HTTP-date in the past yields `0`.
|
|
264
|
-
*
|
|
265
|
-
* @param value - Raw `Retry-After` header value
|
|
266
|
-
* @param nowMs - Current time in milliseconds (injectable for tests)
|
|
267
|
-
* @returns Delay in milliseconds, or `undefined` when the value cannot be parsed
|
|
268
|
-
*/
|
|
269
|
-
const parseRetryAfterMs = (value, nowMs = Date.now()) => {
|
|
270
|
-
const trimmed = value.trim();
|
|
271
|
-
if (trimmed === '') {
|
|
272
|
-
return undefined;
|
|
273
|
-
}
|
|
274
|
-
if (/^\d+$/.test(trimmed)) {
|
|
275
|
-
return Number.parseInt(trimmed, 10) * 1000;
|
|
276
|
-
}
|
|
277
|
-
// Reject other numeric forms (floats, negatives); not valid delta-seconds or HTTP-date.
|
|
278
|
-
if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
279
|
-
return undefined;
|
|
280
|
-
}
|
|
281
|
-
const dateMs = Date.parse(trimmed);
|
|
282
|
-
if (Number.isNaN(dateMs)) {
|
|
283
|
-
return undefined;
|
|
284
|
-
}
|
|
285
|
-
return Math.max(0, dateMs - nowMs);
|
|
286
|
-
};
|
|
287
|
-
exports.parseRetryAfterMs = parseRetryAfterMs;
|
|
288
|
-
/**
|
|
289
|
-
* Chooses the delay before the next HTTP retry: prefer a valid `Retry-After`, else full jitter.
|
|
290
|
-
*
|
|
291
|
-
* Reads `response.headers.get('Retry-After')` and parses it with {@link parseRetryAfterMs}.
|
|
292
|
-
* Missing headers, or values that parse to `undefined`, fall back to {@link fullJitter}.
|
|
293
|
-
* Abort and network retries do not use this helper.
|
|
294
|
-
*
|
|
295
|
-
* @param response - Non-OK response from the current attempt
|
|
296
|
-
* @param baseBackoffMs - Base backoff passed to {@link fullJitter} when falling back
|
|
297
|
-
* @param attempt - 1-based attempt index
|
|
298
|
-
* @param nowMs - Current time in milliseconds (injectable for tests)
|
|
299
|
-
* @returns Wait duration in milliseconds before the next attempt
|
|
300
|
-
*/
|
|
301
|
-
const resolveRetryDelayMs = (response, baseBackoffMs, attempt, nowMs = Date.now()) => {
|
|
302
|
-
const header = response.headers?.get('Retry-After');
|
|
303
|
-
if (header == null) {
|
|
304
|
-
return fullJitter(baseBackoffMs, attempt);
|
|
305
|
-
}
|
|
306
|
-
const fromHeader = (0, exports.parseRetryAfterMs)(header, nowMs);
|
|
307
|
-
if (fromHeader === undefined) {
|
|
308
|
-
return fullJitter(baseBackoffMs, attempt);
|
|
309
|
-
}
|
|
310
|
-
return fromHeader;
|
|
311
|
-
};
|
|
312
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7OztHQUtHOzs7QUFpRUg7O0dBRUc7QUFDSCxNQUFhLHNCQUF1QixTQUFRLEtBQUs7SUFFL0M7O09BRUc7SUFDSCxZQUFZLE9BQU8sR0FBRyxTQUFTO1FBQzdCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUxDLFNBQUksR0FBVyx3QkFBd0IsQ0FBQztRQU14RCxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRSxDQUFDO0NBQ0Y7QUFURCx3REFTQztBQUVEOztHQUVHO0FBQ0gsTUFBYSwrQkFBZ0MsU0FBUSxzQkFBc0I7SUFFekU7O09BRUc7SUFDSCxZQUFZLE9BQU8sR0FBRyw0QkFBNEI7UUFDaEQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBTEMsU0FBSSxHQUFXLGlDQUFpQyxDQUFDO1FBTWpFLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLCtCQUErQixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3pFLENBQUM7Q0FDRjtBQVRELDBFQVNDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFhLHFCQUFzQixTQUFRLEtBQUs7SUFFOUM7Ozs7T0FJRztJQUNILFlBQ0UsT0FBZSxFQUNDLE1BQWMsRUFDZCxJQUFZO1FBRTVCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUhDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxTQUFJLEdBQUosSUFBSSxDQUFRO1FBVFosU0FBSSxHQUFXLHVCQUF1QixDQUFDO1FBWXZELE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQy9ELENBQUM7Q0FDRjtBQWZELHNEQWVDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQWEsd0JBQXlCLFNBQVEsS0FBSztJ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LENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDekIsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQ3JDLENBQUMsQ0FBQztBQXJCVyxRQUFBLGlCQUFpQixxQkFxQjVCO0FBRUY7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxDQUMxQixRQUFrQixFQUNsQixhQUFxQixFQUNyQixPQUFlLEVBQ2YsUUFBZ0IsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUNsQixFQUFFO0lBQ1YsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDcEQsSUFBSSxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7UUFDbkIsT0FBTyxVQUFVLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxJQUFBLHlCQUFpQixFQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNwRCxJQUFJLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUM3QixPQUFPLFVBQVUsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVELE9BQU8sVUFBVSxDQUFDO0FBQ3BCLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUmV0cnktZW5hYmxlZCBgZmV0Y2hgIHdyYXBwZXIgd2l0aCBwZXItYXR0ZW1wdCB0aW1lb3V0LCBSZXRyeS1BZnRlciBzdXBwb3J0LCBmdWxsLWppdHRlciBiYWNrb2ZmLFxuICogb3B0aW9uIHZhbGlkYXRpb24sIGFuZCB0eXBlZCBlcnJvcnMuXG4gKlxuICogQG1vZHVsZSBmZXRjaC1yZXRyaWVyXG4gKi9cblxuLyoqXG4gKiBgZmV0Y2hgIG9wdGlvbnMgZm9yd2FyZGVkIHRvIGV2ZXJ5IGF0dGVtcHQsIGV4Y2x1ZGluZyBgc2lnbmFsYC5cbiAqXG4gKiBVc2UgZm9yIGBtZXRob2RgLCBgYm9keWAsIGBjcmVkZW50aWFsc2AsIGByZWRpcmVjdGAsIGBtb2RlYCwgYGNhY2hlYCwgYW5kIG90aGVyXG4gKiB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JlcXVlc3RJbml0IHwgUmVxdWVzdEluaXR9IGZpZWxkcy5cbiAqIFBlci1hdHRlbXB0IGFib3J0IGFuZCB0aW1lb3V0IGFyZSBoYW5kbGVkIGludGVybmFsbHkgdmlhIGBzaWduYWxgIGFuZCBtdXN0IG5vdCBiZSBzZXQgaGVyZS5cbiAqL1xuZXhwb3J0IHR5cGUgRmV0Y2hJbml0T3B0aW9ucyA9IE9taXQ8UmVxdWVzdEluaXQsICdzaWduYWwnPjtcblxuLyoqXG4gKiBPcHRpb25zIGZvciB7QGxpbmsgZmV0Y2hSZXRyaWVyfTogcmV0cnkgcG9saWN5LCB0aW1lb3V0LCBiYWNrb2ZmIChpbmNsdWRpbmcgYFJldHJ5LUFmdGVyYCksXG4gKiByZXF1ZXN0IHBheWxvYWQsIGFuZCBjYW5jZWxsYXRpb24uXG4gKlxuICogUmVxdWVzdCBzaGFwZSBpcyBidWlsdCBhcyBgeyAuLi5pbml0LCBoZWFkZXJzPywgc2lnbmFsIH1gIG9uIGVhY2ggYXR0ZW1wdC4gVG9wLWxldmVsIGBoZWFkZXJzYFxuICogb3ZlcnJpZGUgYGluaXQuaGVhZGVyc2Agd2hlbiBib3RoIGFyZSBwcm92aWRlZC5cbiAqXG4gKiBOdW1lcmljIGZpZWxkcyBhcmUgdmFsaWRhdGVkIHdoZW4ge0BsaW5rIGZldGNoUmV0cmllcn0gaXMgY2FsbGVkOyBpbnZhbGlkIHZhbHVlcyB0aHJvd1xuICoge0BsaW5rIEZldGNoUmV0cmllckludmFsaWRPcHRpb25zRXJyb3J9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlcXVlc3RPcHRpb25zIHtcbiAgLyoqXG4gICAqIEhUVFAgaGVhZGVycyBzZW50IG9uIGV2ZXJ5IGF0dGVtcHQuXG4gICAqIFdoZW4gYGluaXQuaGVhZGVyc2AgaXMgYWxzbyBzZXQsIHRoZXNlIHZhbHVlcyB0YWtlIHByZWNlZGVuY2UgZm9yIGR1cGxpY2F0ZSBrZXlzLlxuICAgKi9cbiAgaGVhZGVycz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIHtAbGluayBGZXRjaEluaXRPcHRpb25zfSBtZXJnZWQgaW50byBlYWNoIGBmZXRjaGAgY2FsbCAoZS5nLiBQT1NUIGBtZXRob2RgIGFuZCBKU09OIGBib2R5YCkuXG4gICAqIFRoZSBzYW1lIGBpbml0YCBpcyByZXVzZWQgYWNyb3NzIHJldHJpZXMuXG4gICAqL1xuICBpbml0PzogRmV0Y2hJbml0T3B0aW9ucztcbiAgLyoqXG4gICAqIE1heGltdW0gbnVtYmVyIG9mIGF0dGVtcHRzLCBpbmNsdWRpbmcgdGhlIGZpcnN0LlxuICAgKiBNdXN0IGJlIGA+PSAxYC5cbiAgICovXG4gIHJldHJpZXM6IG51bWJlcjtcbiAgLyoqXG4gICAqIFBlci1hdHRlbXB0IHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzOyB1c2VzIGFuIGludGVybmFsIHtAbGluayBBYm9ydENvbnRyb2xsZXJ9IHdoZW4gZXhjZWVkZWQuXG4gICAqIE11c3QgYmUgYD4gMGAuXG4gICAqL1xuICB0aW1lb3V0TXM6IG51bWJlcjtcbiAgLyoqXG4gICAqIEJhc2UgYmFja29mZiBpbiBtaWxsaXNlY29uZHMgZm9yIGZ1bGwgaml0dGVyIHdoZW4gYFJldHJ5LUFmdGVyYCBpcyBhYnNlbnQgb3IgaW52YWxpZC5cbiAgICogVGhlIGNhcCBmb3IgYXR0ZW1wdCBgbmAgaXMgYGJhc2VCYWNrb2ZmTXMgKiAyXm5gLlxuICAgKiBNdXN0IGJlIGA+PSAwYCAoYDBgIHNraXBzIGJhY2tvZmYgZGVsYXkgYmV0d2VlbiBhdHRlbXB0cyB3aGVuIGZhbGxpbmcgYmFjayB0byBqaXR0ZXIpLlxuICAgKi9cbiAgYmFzZUJhY2tvZmZNczogbnVtYmVyO1xuICAvKipcbiAgICogT3B0aW9uYWwgZXh0ZXJuYWwge0BsaW5rIEFib3J0U2lnbmFsfS4gV2hlbiBhYm9ydGVkLCB0aGUgaW4tZmxpZ2h0IHJlcXVlc3QgaXMgYWJvcnRlZDsgb24gdGhlXG4gICAqIGZpbmFsIGF0dGVtcHQsIGNhbmNlbGxhdGlvbiBzdXJmYWNlcyBhcyB7QGxpbmsgRmV0Y2hSZXRyaWVyQWJvcnRFcnJvcn0uXG4gICAqL1xuICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgLyoqXG4gICAqIEludm9rZWQgYWZ0ZXIgYHJlc3BvbnNlLnRleHQoKWAgd2hlbiBgcmVzcG9uc2Uub2tgIGlzIGZhbHNlLlxuICAgKiBSZXR1cm4gYHRydWVgIHRvIHNjaGVkdWxlIGFub3RoZXIgYXR0ZW1wdCAodW50aWwgYHJldHJpZXNgIGlzIGV4aGF1c3RlZCkuXG4gICAqIERlZmF1bHQ6IHtAbGluayBkZWZhdWx0U2hvdWxkUmV0cnl9IChzZWUge0BsaW5rIERFRkFVTFRfUkVUUllBQkxFX0hUVFBfU1RBVFVTRVN9KS5cbiAgICpcbiAgICogQHBhcmFtIHJlc3BvbnNlIC0gTm9uLU9LIHJlc3BvbnNlIGZyb20gdGhlIGN1cnJlbnQgYXR0ZW1wdFxuICAgKiBAcGFyYW0gYm9keSAtIFJlc3BvbnNlIGJvZHkgdGV4dCBmcm9tIGByZXNwb25zZS50ZXh0KClgXG4gICAqIEByZXR1cm5zIGB0cnVlYCB0byBzY2hlZHVsZSBhbm90aGVyIGF0dGVtcHQgKHVudGlsIGByZXRyaWVzYCBpcyBleGhhdXN0ZWQpXG4gICAqL1xuICBzaG91bGRSZXRyeT86IChyZXNwb25zZTogUmVzcG9uc2UsIGJvZHk6IHN0cmluZykgPT4gYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBFcnJvciB0aHJvd24gd2hlbiBhIHJlcXVlc3QgaXMgY2FuY2VsbGVkIGJ5IHRpbWVvdXQgb3IgYW4gZXh0ZXJuYWwge0BsaW5rIEFib3J0U2lnbmFsfS5cbiAqL1xuZXhwb3J0IGNsYXNzIEZldGNoUmV0cmllckFib3J0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIG92ZXJyaWRlIHJlYWRvbmx5IG5hbWU6IHN0cmluZyA9ICdGZXRjaFJldHJpZXJBYm9ydEVycm9yJztcbiAgLyoqXG4gICAqIEBwYXJhbSBtZXNzYWdlIC0gSHVtYW4tcmVhZGFibGUgcmVhc29uIChkZWZhdWx0OiBgJ0Fib3J0ZWQnYClcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSAnQWJvcnRlZCcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgRmV0Y2hSZXRyaWVyQWJvcnRFcnJvci5wcm90b3R5cGUpO1xuICB9XG59XG5cbi8qKlxuICogRXJyb3IgdGhyb3duIHdoZW4ge0BsaW5rIFJlcXVlc3RPcHRpb25zLnNpZ25hbH0gaXMgYWxyZWFkeSBhYm9ydGVkIGJlZm9yZSBhbiBhdHRlbXB0IHN0YXJ0cy5cbiAqL1xuZXhwb3J0IGNsYXNzIEZldGNoUmV0cmllckFscmVhZHlBYm9ydGVkRXJyb3IgZXh0ZW5kcyBGZXRjaFJldHJpZXJBYm9ydEVycm9yIHtcbiAgb3ZlcnJpZGUgcmVhZG9ubHkgbmFtZTogc3RyaW5nID0gJ0ZldGNoUmV0cmllckFscmVhZHlBYm9ydGVkRXJyb3InO1xuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSByZWFzb24gKGRlZmF1bHQ6IGAnU2lnbmFsIHdhcyBhbHJlYWR5IGFib3J0ZWQnYClcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSAnU2lnbmFsIHdhcyBhbHJlYWR5IGFib3J0ZWQnKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIEZldGNoUmV0cmllckFscmVhZHlBYm9ydGVkRXJyb3IucHJvdG90eXBlKTtcbiAgfVxufVxuXG4vKipcbiAqIEVycm9yIHRocm93biB3aGVuIHRoZSBzZXJ2ZXIgcmV0dXJucyBhIG5vbi1PSyBIVFRQIHN0YXR1cyBhbmQgbm8gZnVydGhlciByZXRyeSBpcyBwZXJmb3JtZWQuXG4gKlxuICogQ2FycmllcyB0aGUgbGFzdCByZXNwb25zZSBgc3RhdHVzYCBhbmQgdGhlIGJvZHkgdGV4dCBhbHJlYWR5IGNvbnN1bWVkIHZpYSBgcmVzcG9uc2UudGV4dCgpYFxuICogKHRoZSBzYW1lIHRleHQgcGFzc2VkIHRvIHtAbGluayBSZXF1ZXN0T3B0aW9ucy5zaG91bGRSZXRyeX0pLlxuICpcbiAqIEBwcm9wZXJ0eSBzdGF0dXMgLSBIVFRQIHN0YXR1cyBjb2RlIGZyb20gdGhlIGxhc3Qgbm9uLU9LIHJlc3BvbnNlXG4gKiBAcHJvcGVydHkgYm9keSAtIFJlc3BvbnNlIGJvZHkgdGV4dCBhbHJlYWR5IHJlYWQgdmlhIGByZXNwb25zZS50ZXh0KClgIGZvciB0aGF0IGF0dGVtcHRcbiAqL1xuZXhwb3J0IGNsYXNzIEZldGNoUmV0cmllckh0dHBFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgb3ZlcnJpZGUgcmVhZG9ubHkgbmFtZTogc3RyaW5nID0gJ0ZldGNoUmV0cmllckh0dHBFcnJvcic7XG4gIC8qKlxuICAgKiBAcGFyYW0gbWVzc2FnZSAtIEVycm9yIGRlc2NyaXB0aW9uXG4gICAqIEBwYXJhbSBzdGF0dXMgLSBIVFRQIHN0YXR1cyBjb2RlIGZyb20gdGhlIGxhc3Qgbm9uLU9LIHJlc3BvbnNlXG4gICAqIEBwYXJhbSBib2R5IC0gUmVzcG9uc2UgYm9keSB0ZXh0IGFscmVhZHkgcmVhZCB2aWEgYHJlc3BvbnNlLnRleHQoKWAgZm9yIHRoYXQgYXR0ZW1wdFxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICAgIHB1YmxpYyByZWFkb25seSBzdGF0dXM6IG51bWJlcixcbiAgICBwdWJsaWMgcmVhZG9ubHkgYm9keTogc3RyaW5nLFxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgRmV0Y2hSZXRyaWVySHR0cEVycm9yLnByb3RvdHlwZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBFcnJvciB0aHJvd24gd2hlbiBhIGZldGNoIGZhaWxzIHdpdGggYSBuZXR3b3JrLWxldmVsIGVycm9yIChlLmcuIEROUyBmYWlsdXJlLCBjb25uZWN0aW9uIHJlZnVzZWQpLlxuICpcbiAqIEBwcm9wZXJ0eSBjYXVzZSAtIE9yaWdpbmFsIGVycm9yIGZyb20gdGhlIHVuZGVybHlpbmcgYGZldGNoYCwgd2hlbiBhdmFpbGFibGVcbiAqL1xuZXhwb3J0IGNsYXNzIEZldGNoUmV0cmllck5ldHdvcmtFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgb3ZlcnJpZGUgcmVhZG9ubHkgbmFtZTogc3RyaW5nID0gJ0ZldGNoUmV0cmllck5ldHdvcmtFcnJvcic7XG4gIC8qKlxuICAgKiBAcGFyYW0gbWVzc2FnZSAtIEh1bWFuLXJlYWRhYmxlIHJlYXNvbiAoZGVmYXVsdDogYCdOZXR3b3JrIGVycm9yJ2ApXG4gICAqIEBwYXJhbSBjYXVzZSAtIE9yaWdpbmFsIGVycm9yIGZyb20gdGhlIHVuZGVybHlpbmcgYGZldGNoYCwgd2hlbiBhdmFpbGFibGVcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSAnTmV0d29yayBlcnJvcicsIHB1YmxpYyByZWFkb25seSBjYXVzZT86IHVua25vd24pIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgRmV0Y2hSZXRyaWVyTmV0d29ya0Vycm9yLnByb3RvdHlwZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBFcnJvciB0aHJvd24gd2hlbiB7QGxpbmsgUmVxdWVzdE9wdGlvbnN9IGNvbnRhaW5zIGludmFsaWQgbnVtZXJpYyB2YWx1ZXMuXG4gKlxuICogU3ViY2xhc3Mgb2Yge0BsaW5rIFR5cGVFcnJvcn0gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBgaW5zdGFuY2VvZiBUeXBlRXJyb3JgLiBEaXN0aW5jdCBmcm9tXG4gKiBuZXR3b3JrLWxldmVsIGBUeXBlRXJyb3JgIHZhbHVlcyB0aHJvd24gYnkgYGZldGNoYCwgd2hpY2ggYXJlIHJldHJpZWQgYW5kIHN1cmZhY2VkIGFzXG4gKiB7QGxpbmsgRmV0Y2hSZXRyaWVyTmV0d29ya0Vycm9yfSBhZnRlciB0aGUgbGFzdCBhdHRlbXB0LlxuICovXG5leHBvcnQgY2xhc3MgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvciBleHRlbmRzIFR5cGVFcnJvciB7XG4gIG92ZXJyaWRlIHJlYWRvbmx5IG5hbWU6IHN0cmluZyA9ICdGZXRjaFJldHJpZXJJbnZhbGlkT3B0aW9uc0Vycm9yJztcbiAgLyoqXG4gICAqIEBwYXJhbSBtZXNzYWdlIC0gSHVtYW4tcmVhZGFibGUgcmVhc29uIGRlc2NyaWJpbmcgdGhlIGludmFsaWQgb3B0aW9uXG4gICAqL1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvci5wcm90b3R5cGUpO1xuICB9XG59XG5cbi8qKlxuICogRXJyb3IgdGhyb3duIHdoZW4gYW4gaW50ZXJuYWwgaW52YXJpYW50IGZhaWxzIChzaG91bGQgbm90IGhhcHBlbiBpbiBub3JtYWwgdXNlKS5cbiAqL1xuZXhwb3J0IGNsYXNzIEZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIG92ZXJyaWRlIHJlYWRvbmx5IG5hbWU6IHN0cmluZyA9ICdGZXRjaFJldHJpZXJVbnJlYWNoYWJsZUVycm9yJztcbiAgLyoqXG4gICAqIEBwYXJhbSBtZXNzYWdlIC0gSHVtYW4tcmVhZGFibGUgcmVhc29uIChkZWZhdWx0OiBgJ1VucmVhY2hhYmxlJ2ApXG4gICAqL1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlID0gJ1VucmVhY2hhYmxlJykge1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBGZXRjaFJldHJpZXJVbnJlYWNoYWJsZUVycm9yLnByb3RvdHlwZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBIVFRQIHN0YXR1cyBjb2RlcyByZXRyaWVkIGJ5IGRlZmF1bHQgd2hlbiB7QGxpbmsgUmVxdWVzdE9wdGlvbnMuc2hvdWxkUmV0cnl9IGlzIG9taXR0ZWQuXG4gKlxuICogSW5jbHVkZXMgdHJhbnNpZW50IGNsaWVudC9zZXJ2ZXIgZXJyb3JzOiA0MDgsIDQyNSwgNDI5LCBhbmQgY29tbW9uIDV4eCBnYXRld2F5IG9yIG92ZXJsb2FkIHJlc3BvbnNlcy5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfUkVUUllBQkxFX0hUVFBfU1RBVFVTRVM6IHJlYWRvbmx5IG51bWJlcltdID0gWzQwOCwgNDI1LCA0MjksIDUwMCwgNTAyLCA1MDMsIDUwNF07XG5cbi8qKlxuICogRGVmYXVsdCB7QGxpbmsgUmVxdWVzdE9wdGlvbnMuc2hvdWxkUmV0cnl9OiByZXRyaWVzIHJlc3BvbnNlcyB3aG9zZSBzdGF0dXMgaXMgaW5cbiAqIHtAbGluayBERUZBVUxUX1JFVFJZQUJMRV9IVFRQX1NUQVRVU0VTfS5cbiAqXG4gKiBDb21wb3NlIHdpdGggY3VzdG9tIGxvZ2ljLCBmb3IgZXhhbXBsZTpcbiAqIGAocmVzLCBib2R5KSA9PiBkZWZhdWx0U2hvdWxkUmV0cnkocmVzLCBib2R5KSB8fCByZXMuc3RhdHVzID09PSA0MThgLlxuICpcbiAqIEBwYXJhbSByZXNwb25zZSAtIFJlc3BvbnNlIGZyb20gdGhlIGZhaWxlZCBhdHRlbXB0XG4gKiBAcGFyYW0gX2JvZHkgLSBSZXNwb25zZSBib2R5IHRleHQgKHVudXNlZCBieSB0aGUgZGVmYXVsdCBwcmVkaWNhdGUpXG4gKiBAcmV0dXJucyBgdHJ1ZWAgd2hlbiBhbm90aGVyIGF0dGVtcHQgc2hvdWxkIGJlIHNjaGVkdWxlZFxuICovXG5leHBvcnQgY29uc3QgZGVmYXVsdFNob3VsZFJldHJ5ID0gKHJlc3BvbnNlOiBSZXNwb25zZSwgX2JvZHk6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xuICByZXR1cm4gREVGQVVMVF9SRVRSWUFCTEVfSFRUUF9TVEFUVVNFUy5pbmNsdWRlcyhyZXNwb25zZS5zdGF0dXMpO1xufTtcblxuLyoqXG4gKiBWYWxpZGF0ZXMgcmV0cnkgcG9saWN5IG51bWVyaWMgZmllbGRzIG9uIHtAbGluayBSZXF1ZXN0T3B0aW9uc30uXG4gKlxuICogQ29uc3RyYWludHM6IGByZXRyaWVzID49IDFgLCBgdGltZW91dE1zID4gMGAsIGBiYXNlQmFja29mZk1zID49IDBgLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9ucyB3aG9zZSBgcmV0cmllc2AsIGB0aW1lb3V0TXNgLCBhbmQgYGJhc2VCYWNrb2ZmTXNgIGFyZSBjaGVja2VkXG4gKiBAdGhyb3dzIHtGZXRjaFJldHJpZXJJbnZhbGlkT3B0aW9uc0Vycm9yfSBXaGVuIGFueSBjb25zdHJhaW50IGlzIHZpb2xhdGVkXG4gKi9cbmNvbnN0IHZhbGlkYXRlUmVxdWVzdE9wdGlvbnMgPSAob3B0aW9uczogUGljazxSZXF1ZXN0T3B0aW9ucywgJ3JldHJpZXMnIHwgJ3RpbWVvdXRNcycgfCAnYmFzZUJhY2tvZmZNcyc+KTogdm9pZCA9PiB7XG4gIGNvbnN0IHsgcmV0cmllcywgdGltZW91dE1zLCBiYXNlQmFja29mZk1zIH0gPSBvcHRpb25zO1xuXG4gIGlmIChyZXRyaWVzIDwgMSkge1xuICAgIHRocm93IG5ldyBGZXRjaFJldHJpZXJJbnZhbGlkT3B0aW9uc0Vycm9yKCdyZXRyaWVzIG11c3QgYmUgPj0gMScpO1xuICB9XG4gIGlmICh0aW1lb3V0TXMgPD0gMCkge1xuICAgIHRocm93IG5ldyBGZXRjaFJldHJpZXJJbnZhbGlkT3B0aW9uc0Vycm9yKCd0aW1lb3V0TXMgbXVzdCBiZSA+IDAnKTtcbiAgfVxuICBpZiAoYmFzZUJhY2tvZmZNcyA8IDApIHtcbiAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcignYmFzZUJhY2tvZmZNcyBtdXN0IGJlID49IDAnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBXcmFwcyBgZmV0Y2hgIHdpdGggcmV0cmllcywgcGVyLWF0dGVtcHQgdGltZW91dCwgUmV0cnktQWZ0ZXIgc3VwcG9ydCwgZnVsbC1qaXR0ZXIgYmFja29mZiwgYW5kXG4gKiBvcHRpb25hbCBjYW5jZWxsYXRpb24uXG4gKlxuICogRWFjaCBhdHRlbXB0IGNhbGxzIGBmZXRjaCh1cmwsIHsgLi4ub3B0aW9ucy5pbml0LCBoZWFkZXJzPywgc2lnbmFsIH0pYCB3aXRoIGFuIGludGVybmFsXG4gKiB7QGxpbmsgQWJvcnRTaWduYWx9IGZvciBgdGltZW91dE1zYC4gTm9uLU9LIHJlc3BvbnNlcyBhcmUgcmV0cmllZCB3aGVuIGBzaG91bGRSZXRyeWAgcmV0dXJuc1xuICogYHRydWVgIChkZWZhdWx0OiB7QGxpbmsgZGVmYXVsdFNob3VsZFJldHJ5fSkuIEJldHdlZW4gSFRUUCByZXRyaWVzLCBhIHZhbGlkIGBSZXRyeS1BZnRlcmBcbiAqIGhlYWRlciAoZGVsdGEtc2Vjb25kcyBvciBIVFRQLWRhdGUpIGlzIHByZWZlcnJlZCBvdmVyIGZ1bGwgaml0dGVyOyBhYm9ydCBhbmQgbmV0d29yayByZXRyaWVzXG4gKiBhbHdheXMgdXNlIGZ1bGwgaml0dGVyLiBUaGUgc2FtZSB7QGxpbmsgRmV0Y2hJbml0T3B0aW9uc30gKGluY2x1ZGluZyBgYm9keWApIGlzIHJldXNlZCBvblxuICogZXZlcnkgYXR0ZW1wdC5cbiAqXG4gKiBAcGFyYW0gdXJsIC0gUmVxdWVzdCBVUkwgcGFzc2VkIHRvIGBmZXRjaGBcbiAqIEBwYXJhbSBvcHRpb25zIC0ge0BsaW5rIFJlcXVlc3RPcHRpb25zfSBjb250cm9sbGluZyByZXRyaWVzLCB0aW1lb3V0LCByZXF1ZXN0IGluaXQsIGFuZCBjYW5jZWxsYXRpb25cbiAqIEByZXR1cm5zIFRoZSBmaXJzdCB7QGxpbmsgUmVzcG9uc2V9IGZvciB3aGljaCBgb2tgIGlzIGB0cnVlYFxuICogQHRocm93cyB7RmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcn0gSWYgYHJldHJpZXMgPCAxYCwgYHRpbWVvdXRNcyA8PSAwYCwgb3IgYGJhc2VCYWNrb2ZmTXMgPCAwYFxuICogQHRocm93cyB7RmV0Y2hSZXRyaWVyQWxyZWFkeUFib3J0ZWRFcnJvcn0gSWYgYG9wdGlvbnMuc2lnbmFsYCBpcyBhbHJlYWR5IGFib3J0ZWQgYmVmb3JlIGFuIGF0dGVtcHRcbiAqIEB0aHJvd3Mge0ZldGNoUmV0cmllckh0dHBFcnJvcn0gT24gYSBub24tT0sgcmVzcG9uc2UgdGhhdCBpcyBub3QgcmV0cmllZCBvciBhZnRlciB0aGUgbGFzdCBhdHRlbXB0XG4gKiAgIChpbmNsdWRlcyBgc3RhdHVzYCBhbmQgYGJvZHlgKVxuICogQHRocm93cyB7RmV0Y2hSZXRyaWVyTmV0d29ya0Vycm9yfSBPbiBhIG5ldHdvcmsgYFR5cGVFcnJvcmAgYWZ0ZXIgdGhlIGxhc3QgYXR0ZW1wdFxuICogQHRocm93cyB7RmV0Y2hSZXRyaWVyQWJvcnRFcnJvcn0gT24gdGltZW91dCBvciBleHRlcm5hbCBhYm9ydCBhZnRlciB0aGUgbGFzdCBhdHRlbXB0XG4gKiBAdGhyb3dzIHtGZXRjaFJldHJpZXJVbnJlYWNoYWJsZUVycm9yfSBJZiB0aGUgcmV0cnkgbG9vcCBleGl0cyB3aXRob3V0IHJldHVybmluZyAoaW50ZXJuYWwgYnVnKVxuICovXG5leHBvcnQgY29uc3QgZmV0Y2hSZXRyaWVyID0gYXN5bmMgKHVybDogc3RyaW5nLCBvcHRpb25zOiBSZXF1ZXN0T3B0aW9ucyk6IFByb21pc2U8UmVzcG9uc2U+ID0+IHtcbiAgY29uc3Qge1xuICAgIGhlYWRlcnMsXG4gICAgaW5pdCxcbiAgICByZXRyaWVzLFxuICAgIHRpbWVvdXRNcyxcbiAgICBiYXNlQmFja29mZk1zLFxuICAgIHNpZ25hbDogZXh0ZXJuYWxTaWduYWwsXG4gICAgc2hvdWxkUmV0cnkgPSBkZWZhdWx0U2hvdWxkUmV0cnksXG4gIH0gPSBvcHRpb25zO1xuXG4gIHZhbGlkYXRlUmVxdWVzdE9wdGlvbnMoeyByZXRyaWVzLCB0aW1lb3V0TXMsIGJhc2VCYWNrb2ZmTXMgfSk7XG5cbiAgZm9yIChsZXQgYXR0ZW1wdCA9IDE7IGF0dGVtcHQgPD0gcmV0cmllczsgYXR0ZW1wdCsrKSB7XG4gICAgaWYgKGV4dGVybmFsU2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVyQWxyZWFkeUFib3J0ZWRFcnJvcigpO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKSwgdGltZW91dE1zKTtcblxuICAgIGNvbnN0IG9uRXh0ZXJuYWxBYm9ydCA9ICgpOiB2b2lkID0+IHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICBjb250cm9sbGVyLmFib3J0KCk7XG4gICAgfTtcblxuICAgIGlmIChleHRlcm5hbFNpZ25hbCkge1xuICAgICAgZXh0ZXJuYWxTaWduYWwuYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBvbkV4dGVybmFsQWJvcnQpO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaCh1cmwsIHtcbiAgICAgICAgLi4uaW5pdCxcbiAgICAgICAgLi4uKGhlYWRlcnMgIT09IHVuZGVmaW5lZCA/IHsgaGVhZGVycyB9IDoge30pLFxuICAgICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgfSk7XG5cbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICBleHRlcm5hbFNpZ25hbD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBvbkV4dGVybmFsQWJvcnQpO1xuXG4gICAgICBpZiAocmVzLm9rKSB7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgY29uc3QgaXNDb250aW51ZSA9IHNob3VsZFJldHJ5KHJlcywgdGV4dCk7XG5cbiAgICAgIGlmIChpc0NvbnRpbnVlKSB7XG4gICAgICAgIGlmIChhdHRlbXB0ID09PSByZXRyaWVzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEZldGNoUmV0cmllckh0dHBFcnJvcihgSFRUUCAke3Jlcy5zdGF0dXN9YCwgcmVzLnN0YXR1cywgdGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgd2FpdChyZXNvbHZlUmV0cnlEZWxheU1zKHJlcywgYmFzZUJhY2tvZmZNcywgYXR0ZW1wdCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEZldGNoUmV0cmllckh0dHBFcnJvcihgTm9uLXJldHJpYWJsZSBIVFRQIGVycm9yOiAke3Jlcy5zdGF0dXN9YCwgcmVzLnN0YXR1cywgdGV4dCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyOiB1bmtub3duKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgZXh0ZXJuYWxTaWduYWw/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Fib3J0Jywgb25FeHRlcm5hbEFib3J0KTtcblxuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yICYmIGVyci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHtcbiAgICAgICAgaWYgKGF0dGVtcHQgPT09IHJldHJpZXMpIHRocm93IGVyciBpbnN0YW5jZW9mIEZldGNoUmV0cmllckFib3J0RXJyb3IgPyBlcnIgOiBuZXcgRmV0Y2hSZXRyaWVyQWJvcnRFcnJvcigpO1xuICAgICAgICBhd2FpdCB3YWl0KGZ1bGxKaXR0ZXIoYmFzZUJhY2tvZmZNcywgYXR0ZW1wdCkpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIFR5cGVFcnJvcikge1xuICAgICAgICBpZiAoYXR0ZW1wdCA9PT0gcmV0cmllcykgdGhyb3cgbmV3IEZldGNoUmV0cmllck5ldHdvcmtFcnJvcignTmV0d29yayBlcnJvcicsIGVycik7XG4gICAgICAgIGF3YWl0IHdhaXQoZnVsbEppdHRlcihiYXNlQmFja29mZk1zLCBhdHRlbXB0KSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3IoKTtcbn07XG5cbi8qKlxuICogRGVsYXlzIGV4ZWN1dGlvbiBmb3IgdGhlIGdpdmVuIGR1cmF0aW9uICh1c2VkIGJldHdlZW4gcmV0cnkgYXR0ZW1wdHMpLlxuICpcbiAqIEBwYXJhbSBtcyAtIERlbGF5IGluIG1pbGxpc2Vjb25kc1xuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgYG1zYFxuICovXG5jb25zdCB3YWl0ID0gKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59O1xuXG4vKipcbiAqIEZ1bGwgaml0dGVyIGJhY2tvZmY6IHJhbmRvbSBkZWxheSBpbiBgWzAsIGJhc2UgKiAyXmF0dGVtcHQpYCBtcyAoQVdTLXJlY29tbWVuZGVkIHBhdHRlcm4pLlxuICpcbiAqIFVzZWQgYmV0d2VlbiBhYm9ydC9uZXR3b3JrIHJldHJpZXMsIGFuZCBhcyB0aGUgZmFsbGJhY2sgd2hlbiBIVFRQIHJldHJpZXMgbGFjayBhIHVzYWJsZVxuICogYFJldHJ5LUFmdGVyYCBoZWFkZXIuXG4gKlxuICogQHBhcmFtIGJhc2UgLSBCYXNlIGJhY2tvZmYgaW4gbWlsbGlzZWNvbmRzXG4gKiBAcGFyYW0gYXR0ZW1wdCAtIDEtYmFzZWQgYXR0ZW1wdCBpbmRleCAoZmlyc3QgcmV0cnkgdXNlcyBgYXR0ZW1wdCA9PT0gMWApXG4gKiBAcmV0dXJucyBXYWl0IGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgdGhlIG5leHQgYXR0ZW1wdFxuICovXG5jb25zdCBmdWxsSml0dGVyID0gKGJhc2U6IG51bWJlciwgYXR0ZW1wdDogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgY29uc3QgY2FwID0gYmFzZSAqIE1hdGgucG93KDIsIGF0dGVtcHQpO1xuICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY2FwKTtcbn07XG5cbi8qKlxuICogUGFyc2VzIGEgYFJldHJ5LUFmdGVyYCBoZWFkZXIgdmFsdWUgaW50byBhIGRlbGF5IGluIG1pbGxpc2Vjb25kcy5cbiAqXG4gKiBTdXBwb3J0cyBSRkMgNzIzMSBmb3Jtczogbm9uLW5lZ2F0aXZlIGludGVnZXIgZGVsdGEtc2Vjb25kcywgb3IgYW4gSFRUUC1kYXRlLiBFbXB0eSB2YWx1ZXMsXG4gKiBub24taW50ZWdlciBudW1lcmljcyAoZS5nLiBmbG9hdHMgb3IgbmVnYXRpdmVzKSwgYW5kIHVucGFyc2FibGUgZGF0ZXMgeWllbGQgYHVuZGVmaW5lZGAgc29cbiAqIGNhbGxlcnMgY2FuIGZhbGwgYmFjayB0byBmdWxsIGppdHRlci4gQW4gSFRUUC1kYXRlIGluIHRoZSBwYXN0IHlpZWxkcyBgMGAuXG4gKlxuICogQHBhcmFtIHZhbHVlIC0gUmF3IGBSZXRyeS1BZnRlcmAgaGVhZGVyIHZhbHVlXG4gKiBAcGFyYW0gbm93TXMgLSBDdXJyZW50IHRpbWUgaW4gbWlsbGlzZWNvbmRzIChpbmplY3RhYmxlIGZvciB0ZXN0cylcbiAqIEByZXR1cm5zIERlbGF5IGluIG1pbGxpc2Vjb25kcywgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGUgdmFsdWUgY2Fubm90IGJlIHBhcnNlZFxuICovXG5leHBvcnQgY29uc3QgcGFyc2VSZXRyeUFmdGVyTXMgPSAodmFsdWU6IHN0cmluZywgbm93TXM6IG51bWJlciA9IERhdGUubm93KCkpOiBudW1iZXIgfCB1bmRlZmluZWQgPT4ge1xuICBjb25zdCB0cmltbWVkID0gdmFsdWUudHJpbSgpO1xuICBpZiAodHJpbW1lZCA9PT0gJycpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgaWYgKC9eXFxkKyQvLnRlc3QodHJpbW1lZCkpIHtcbiAgICByZXR1cm4gTnVtYmVyLnBhcnNlSW50KHRyaW1tZWQsIDEwKSAqIDEwMDA7XG4gIH1cblxuICAvLyBSZWplY3Qgb3RoZXIgbnVtZXJpYyBmb3JtcyAoZmxvYXRzLCBuZWdhdGl2ZXMpOyBub3QgdmFsaWQgZGVsdGEtc2Vjb25kcyBvciBIVFRQLWRhdGUuXG4gIGlmICgvXi0/XFxkKyhcXC5cXGQrKT8kLy50ZXN0KHRyaW1tZWQpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IGRhdGVNcyA9IERhdGUucGFyc2UodHJpbW1lZCk7XG4gIGlmIChOdW1iZXIuaXNOYU4oZGF0ZU1zKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICByZXR1cm4gTWF0aC5tYXgoMCwgZGF0ZU1zIC0gbm93TXMpO1xufTtcblxuLyoqXG4gKiBDaG9vc2VzIHRoZSBkZWxheSBiZWZvcmUgdGhlIG5leHQgSFRUUCByZXRyeTogcHJlZmVyIGEgdmFsaWQgYFJldHJ5LUFmdGVyYCwgZWxzZSBmdWxsIGppdHRlci5cbiAqXG4gKiBSZWFkcyBgcmVzcG9uc2UuaGVhZGVycy5nZXQoJ1JldHJ5LUFmdGVyJylgIGFuZCBwYXJzZXMgaXQgd2l0aCB7QGxpbmsgcGFyc2VSZXRyeUFmdGVyTXN9LlxuICogTWlzc2luZyBoZWFkZXJzLCBvciB2YWx1ZXMgdGhhdCBwYXJzZSB0byBgdW5kZWZpbmVkYCwgZmFsbCBiYWNrIHRvIHtAbGluayBmdWxsSml0dGVyfS5cbiAqIEFib3J0IGFuZCBuZXR3b3JrIHJldHJpZXMgZG8gbm90IHVzZSB0aGlzIGhlbHBlci5cbiAqXG4gKiBAcGFyYW0gcmVzcG9uc2UgLSBOb24tT0sgcmVzcG9uc2UgZnJvbSB0aGUgY3VycmVudCBhdHRlbXB0XG4gKiBAcGFyYW0gYmFzZUJhY2tvZmZNcyAtIEJhc2UgYmFja29mZiBwYXNzZWQgdG8ge0BsaW5rIGZ1bGxKaXR0ZXJ9IHdoZW4gZmFsbGluZyBiYWNrXG4gKiBAcGFyYW0gYXR0ZW1wdCAtIDEtYmFzZWQgYXR0ZW1wdCBpbmRleFxuICogQHBhcmFtIG5vd01zIC0gQ3VycmVudCB0aW1lIGluIG1pbGxpc2Vjb25kcyAoaW5qZWN0YWJsZSBmb3IgdGVzdHMpXG4gKiBAcmV0dXJucyBXYWl0IGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgdGhlIG5leHQgYXR0ZW1wdFxuICovXG5jb25zdCByZXNvbHZlUmV0cnlEZWxheU1zID0gKFxuICByZXNwb25zZTogUmVzcG9uc2UsXG4gIGJhc2VCYWNrb2ZmTXM6IG51bWJlcixcbiAgYXR0ZW1wdDogbnVtYmVyLFxuICBub3dNczogbnVtYmVyID0gRGF0ZS5ub3coKSxcbik6IG51bWJlciA9PiB7XG4gIGNvbnN0IGhlYWRlciA9IHJlc3BvbnNlLmhlYWRlcnM/LmdldCgnUmV0cnktQWZ0ZXInKTtcbiAgaWYgKGhlYWRlciA9PSBudWxsKSB7XG4gICAgcmV0dXJuIGZ1bGxKaXR0ZXIoYmFzZUJhY2tvZmZNcywgYXR0ZW1wdCk7XG4gIH1cblxuICBjb25zdCBmcm9tSGVhZGVyID0gcGFyc2VSZXRyeUFmdGVyTXMoaGVhZGVyLCBub3dNcyk7XG4gIGlmIChmcm9tSGVhZGVyID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gZnVsbEppdHRlcihiYXNlQmFja29mZk1zLCBhdHRlbXB0KTtcbiAgfVxuXG4gIHJldHVybiBmcm9tSGVhZGVyO1xufTtcbiJdfQ==
|
|
9
|
+
exports.defaultShouldRetry = exports.DEFAULT_RETRYABLE_HTTP_STATUSES = exports.fetchRetrier = exports.parseRetryAfterMs = exports.FetchRetrierUnreachableError = exports.FetchRetrierNetworkError = exports.FetchRetrierInvalidOptionsError = exports.FetchRetrierHttpError = exports.FetchRetrierError = exports.FetchRetrierAlreadyAbortedError = exports.FetchRetrierAbortError = void 0;
|
|
10
|
+
var errors_1 = require("./core/errors");
|
|
11
|
+
Object.defineProperty(exports, "FetchRetrierAbortError", { enumerable: true, get: function () { return errors_1.FetchRetrierAbortError; } });
|
|
12
|
+
Object.defineProperty(exports, "FetchRetrierAlreadyAbortedError", { enumerable: true, get: function () { return errors_1.FetchRetrierAlreadyAbortedError; } });
|
|
13
|
+
Object.defineProperty(exports, "FetchRetrierError", { enumerable: true, get: function () { return errors_1.FetchRetrierError; } });
|
|
14
|
+
Object.defineProperty(exports, "FetchRetrierHttpError", { enumerable: true, get: function () { return errors_1.FetchRetrierHttpError; } });
|
|
15
|
+
Object.defineProperty(exports, "FetchRetrierInvalidOptionsError", { enumerable: true, get: function () { return errors_1.FetchRetrierInvalidOptionsError; } });
|
|
16
|
+
Object.defineProperty(exports, "FetchRetrierNetworkError", { enumerable: true, get: function () { return errors_1.FetchRetrierNetworkError; } });
|
|
17
|
+
Object.defineProperty(exports, "FetchRetrierUnreachableError", { enumerable: true, get: function () { return errors_1.FetchRetrierUnreachableError; } });
|
|
18
|
+
var retry_after_1 = require("./core/backoff/retry-after");
|
|
19
|
+
Object.defineProperty(exports, "parseRetryAfterMs", { enumerable: true, get: function () { return retry_after_1.parseRetryAfterMs; } });
|
|
20
|
+
var fetch_retrier_1 = require("./core/fetch-retrier");
|
|
21
|
+
Object.defineProperty(exports, "fetchRetrier", { enumerable: true, get: function () { return fetch_retrier_1.fetchRetrier; } });
|
|
22
|
+
var default_should_retry_1 = require("./core/policy/default-should-retry");
|
|
23
|
+
Object.defineProperty(exports, "DEFAULT_RETRYABLE_HTTP_STATUSES", { enumerable: true, get: function () { return default_should_retry_1.DEFAULT_RETRYABLE_HTTP_STATUSES; } });
|
|
24
|
+
Object.defineProperty(exports, "defaultShouldRetry", { enumerable: true, get: function () { return default_should_retry_1.defaultShouldRetry; } });
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7OztHQUtHOzs7QUFFSCx3Q0FRdUI7QUFQckIsZ0hBQUEsc0JBQXNCLE9BQUE7QUFDdEIseUhBQUEsK0JBQStCLE9BQUE7QUFDL0IsMkdBQUEsaUJBQWlCLE9BQUE7QUFDakIsK0dBQUEscUJBQXFCLE9BQUE7QUFDckIseUhBQUEsK0JBQStCLE9BQUE7QUFDL0Isa0hBQUEsd0JBQXdCLE9BQUE7QUFDeEIsc0hBQUEsNEJBQTRCLE9BQUE7QUFHOUIsMERBQStEO0FBQXRELGdIQUFBLGlCQUFpQixPQUFBO0FBQzFCLHNEQUFvRDtBQUEzQyw2R0FBQSxZQUFZLE9BQUE7QUFDckIsMkVBRzRDO0FBRjFDLHVJQUFBLCtCQUErQixPQUFBO0FBQy9CLDBIQUFBLGtCQUFrQixPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSZXRyeS1lbmFibGVkIGBmZXRjaGAgd3JhcHBlciB3aXRoIHBlci1hdHRlbXB0IHRpbWVvdXQsIFJldHJ5LUFmdGVyIHN1cHBvcnQsIGZ1bGwtaml0dGVyIGJhY2tvZmYsXG4gKiBvcHRpb24gdmFsaWRhdGlvbiwgYW5kIHR5cGVkIGVycm9ycy5cbiAqXG4gKiBAbW9kdWxlIGZldGNoLXJldHJpZXJcbiAqL1xuXG5leHBvcnQge1xuICBGZXRjaFJldHJpZXJBYm9ydEVycm9yLFxuICBGZXRjaFJldHJpZXJBbHJlYWR5QWJvcnRlZEVycm9yLFxuICBGZXRjaFJldHJpZXJFcnJvcixcbiAgRmV0Y2hSZXRyaWVySHR0cEVycm9yLFxuICBGZXRjaFJldHJpZXJJbnZhbGlkT3B0aW9uc0Vycm9yLFxuICBGZXRjaFJldHJpZXJOZXR3b3JrRXJyb3IsXG4gIEZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3IsXG59IGZyb20gJy4vY29yZS9lcnJvcnMnO1xuZXhwb3J0IHR5cGUgeyBGZXRjaEluaXRPcHRpb25zLCBSZXF1ZXN0T3B0aW9ucyB9IGZyb20gJy4vY29yZS9vcHRpb25zJztcbmV4cG9ydCB7IHBhcnNlUmV0cnlBZnRlck1zIH0gZnJvbSAnLi9jb3JlL2JhY2tvZmYvcmV0cnktYWZ0ZXInO1xuZXhwb3J0IHsgZmV0Y2hSZXRyaWVyIH0gZnJvbSAnLi9jb3JlL2ZldGNoLXJldHJpZXInO1xuZXhwb3J0IHtcbiAgREVGQVVMVF9SRVRSWUFCTEVfSFRUUF9TVEFUVVNFUyxcbiAgZGVmYXVsdFNob3VsZFJldHJ5LFxufSBmcm9tICcuL2NvcmUvcG9saWN5L2RlZmF1bHQtc2hvdWxkLXJldHJ5JztcbiJdfQ==
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fetch-retrier",
|
|
3
|
+
"description": "Retry-enabled fetch wrapper with per-attempt timeout, Retry-After support, full-jitter backoff, and option validation.",
|
|
3
4
|
"repository": {
|
|
4
5
|
"type": "git",
|
|
5
6
|
"url": "https://github.com/gammarers-labs/fetch-retrier.git"
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
"publishConfig": {
|
|
63
64
|
"access": "public"
|
|
64
65
|
},
|
|
65
|
-
"version": "0.
|
|
66
|
+
"version": "0.6.1",
|
|
66
67
|
"jest": {
|
|
67
68
|
"coverageProvider": "v8",
|
|
68
69
|
"testMatch": [
|