fetch-retrier 0.7.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -16
- package/lib/core/backoff/retry-after.d.ts +24 -6
- package/lib/core/backoff/retry-after.js +37 -10
- package/lib/core/options.d.ts +11 -4
- package/lib/core/options.js +1 -1
- package/lib/core/policy/validate-options.d.ts +4 -4
- package/lib/core/policy/validate-options.js +25 -13
- package/lib/fetch-retrier.d.ts +8 -5
- package/lib/fetch-retrier.js +12 -9
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -1
- package/lib/parse-retry-after.d.ts +1 -0
- package/lib/parse-retry-after.js +1 -1
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -9,27 +9,27 @@ A lightweight wrapper around `fetch` that adds **retries**, **per-attempt timeou
|
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
- **Configurable retries** – Set the maximum number of attempts per request (`retries
|
|
13
|
-
- **Per-attempt timeout** – Abort each attempt when it exceeds a given duration (`timeoutMs
|
|
14
|
-
- **Retry-After support** – On HTTP retries, prefers a valid `Retry-After` header (delta-seconds or HTTP-date); falls back to full jitter when absent or
|
|
15
|
-
- **Full jitter backoff** – Exponential backoff with random jitter (AWS-style) for abort/network retries and as the HTTP fallback (`baseBackoffMs
|
|
16
|
-
- **Option validation** –
|
|
12
|
+
- **Configurable retries** – Set the maximum number of attempts per request (`retries` is a finite integer `>= 1`).
|
|
13
|
+
- **Per-attempt timeout** – Abort each attempt when it exceeds a given duration (`timeoutMs` is a finite integer `> 0`).
|
|
14
|
+
- **Retry-After support** – On HTTP retries, prefers a valid `Retry-After` header (delta-seconds or HTTP-date); falls back to full jitter when absent, invalid, or non-finite. Optional `maxRetryAfterMs` clips a finite delay (a finite integer `>= 0` when set) and does not change jitter.
|
|
15
|
+
- **Full jitter backoff** – Exponential backoff with random jitter (AWS-style) for abort/network retries and as the HTTP fallback (`baseBackoffMs` is a finite integer `>= 0`). Optional `maxBackoffMs` clips the jitter result (a finite integer `>= 0` when set); it does not clip a valid `Retry-After`.
|
|
16
|
+
- **Option validation** – Non-finite or non-integer numeric options throw `FetchRetrierInvalidOptionsError` before any request.
|
|
17
17
|
- **RequestInit forwarding** – Pass `method`, `body`, `credentials`, `redirect`, and other `fetch` options via `init` on every attempt.
|
|
18
18
|
- **Header shorthand** – Optional top-level `headers` override `init.headers` when both are set.
|
|
19
19
|
- **Default retry policy** – Retries transient HTTP statuses (408, 425, 429, 500, 502, 503, 504) via `defaultShouldRetry` and `DEFAULT_RETRYABLE_HTTP_STATUSES`.
|
|
20
20
|
- **Extensible retry predicate** – Compose `defaultShouldRetry` with custom `shouldRetry` logic (receives response body text).
|
|
21
21
|
- **External cancellation** – Pass an `AbortSignal` to cancel in-flight requests and backoff waits.
|
|
22
|
-
- **Typed errors** –
|
|
23
|
-
- **TypeScript** – Exported types including `RequestOptions` and `
|
|
22
|
+
- **Typed errors** – Errors created by this package extend abstract `FetchRetrierError`. Subclasses include `FetchRetrierHttpError` (with `status` and `body`), `FetchRetrierNetworkError`, `FetchRetrierAbortError`, `FetchRetrierAlreadyAbortedError`, and `FetchRetrierInvalidOptionsError`. Any other exception is rethrown as-is.
|
|
23
|
+
- **TypeScript** – Exported types including `RequestOptions`, `FetchInitOptions`, and `ParseRetryAfterOptions`.
|
|
24
24
|
|
|
25
25
|
## How it works
|
|
26
26
|
|
|
27
|
-
Options are validated, then each attempt sends the same URL and `init`/`headers` with an internal timeout. If `response.ok` is true, that response is returned. Otherwise `shouldRetry` decides whether to wait and try again. HTTP retries prefer a valid `Retry-After` header; abort and network retries use full jitter. After the last attempt, a subclass of `FetchRetrierError` is thrown.
|
|
27
|
+
Options are validated, then each attempt sends the same URL and `init`/`headers` with an internal timeout. If `response.ok` is true, that response is returned. Otherwise `shouldRetry` decides whether to wait and try again. HTTP retries prefer a valid `Retry-After` header; abort and network retries use full jitter. After the last attempt, a subclass of `FetchRetrierError` is thrown. An exception that is neither an abort nor a network `TypeError` is rethrown immediately.
|
|
28
28
|
|
|
29
29
|
- **Success** – If `response.ok` is true, the response is returned immediately.
|
|
30
30
|
- **Package errors** – Failures from this package extend abstract `FetchRetrierError`. Catch the base, or a subclass for a specific case. Construct a subclass.
|
|
31
|
-
- **Invalid options** – If `retries
|
|
32
|
-
- **Retriable failure** – If the response is not OK and `shouldRetry(response, body)` returns true, the client waits and retries until `retries` is exhausted. Wait prefers a valid `Retry-After` header (delta-seconds or HTTP-date); otherwise uses full jitter. On the last attempt, `FetchRetrierHttpError` is thrown (includes `status` and `body`).
|
|
31
|
+
- **Invalid options** – If `retries`, `timeoutMs`, `baseBackoffMs`, or a set `maxBackoffMs` or `maxRetryAfterMs` is not a finite integer in range (`retries >= 1`, `timeoutMs > 0`, backoff and Retry-After ceilings `>= 0`), `FetchRetrierInvalidOptionsError` is thrown before any request is made. `NaN`, `Infinity`, and decimals are rejected. This is not a `TypeError`.
|
|
32
|
+
- **Retriable failure** – If the response is not OK and `shouldRetry(response, body)` returns true, the client waits and retries until `retries` is exhausted. Wait prefers a valid `Retry-After` header (delta-seconds or HTTP-date); otherwise uses full jitter. When `maxRetryAfterMs` is set, a longer finite `Retry-After` is clipped to that ceiling. On the last attempt, `FetchRetrierHttpError` is thrown (includes `status` and `body`).
|
|
33
33
|
- **Non-retriable failure** – If `shouldRetry` returns false, `FetchRetrierHttpError` is thrown immediately with `status` and `body` (e.g. `Non-retriable HTTP error: 404`).
|
|
34
34
|
- **Timeout** – If a request exceeds `timeoutMs`, that attempt is aborted and retried with full jitter until `retries` is exhausted. Timeout is per-attempt and does not cancel later attempts. The final failure is `FetchRetrierAbortError`.
|
|
35
35
|
- **External abort (in-flight)** – If `signal` is aborted during an attempt, the in-flight request is aborted. On the last attempt, the failure is `FetchRetrierAbortError`. If retries remain, backoff is skipped and the next attempt sees the still-aborted signal and throws `FetchRetrierAlreadyAbortedError` (no further request is made).
|
|
@@ -127,8 +127,9 @@ const response = await fetchRetrier('https://api.example.com/data', {
|
|
|
127
127
|
|
|
128
128
|
### Handling errors
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
Errors created by `fetchRetrier` extend `FetchRetrierError`. The base class is abstract.
|
|
131
131
|
Catch it for any library failure, or a subclass for a specific case. Construct a subclass.
|
|
132
|
+
An exception that is neither an abort nor a network `TypeError` is rethrown as-is.
|
|
132
133
|
`FetchRetrierInvalidOptionsError` does not extend `TypeError`.
|
|
133
134
|
|
|
134
135
|
On a non-OK response that is not retried (or after retries are exhausted), `FetchRetrierHttpError`
|
|
@@ -202,10 +203,11 @@ try {
|
|
|
202
203
|
|
|
203
204
|
| Option | Type | Required | Description |
|
|
204
205
|
|--------|------|----------|-------------|
|
|
205
|
-
| `retries` | `number` | Yes | Maximum number of attempts (including the first request). Must be `>= 1`. |
|
|
206
|
-
| `timeoutMs` | `number` | Yes | Timeout in milliseconds for each attempt. Exceeded attempts are aborted and retried. Must be `> 0`. |
|
|
207
|
-
| `baseBackoffMs` | `number` | Yes | Base delay in milliseconds for full jitter when `Retry-After` is absent or invalid (also used for abort/network retries). Exponential span is `baseBackoffMs * 2^attempt`, randomized. Must be `>= 0` (`0` skips backoff delay when falling back). |
|
|
208
|
-
| `maxBackoffMs` | `number` | No | Optional ceiling in milliseconds applied to the full-jitter result (`Math.min(jitter, maxBackoffMs)`). Does not clip a valid `Retry-After`. Must be `>= 0` when set (`0` skips jitter wait). Omitted means no extra clip. |
|
|
206
|
+
| `retries` | `number` | Yes | Maximum number of attempts (including the first request). Must be a finite integer `>= 1`. |
|
|
207
|
+
| `timeoutMs` | `number` | Yes | Timeout in milliseconds for each attempt. Exceeded attempts are aborted and retried. Must be a finite integer `> 0`. |
|
|
208
|
+
| `baseBackoffMs` | `number` | Yes | Base delay in milliseconds for full jitter when `Retry-After` is absent or invalid (also used for abort/network retries). Exponential span is `baseBackoffMs * 2^attempt`, randomized. Must be a finite integer `>= 0` (`0` skips backoff delay when falling back). |
|
|
209
|
+
| `maxBackoffMs` | `number` | No | Optional ceiling in milliseconds applied to the full-jitter result (`Math.min(jitter, maxBackoffMs)`). Does not clip a valid `Retry-After`. Must be a finite integer `>= 0` when set (`0` skips jitter wait). Omitted means no extra clip. |
|
|
210
|
+
| `maxRetryAfterMs` | `number` | No | Optional ceiling in milliseconds applied to a finite `Retry-After` delay (`Math.min(delay, maxRetryAfterMs)`). Does not change full jitter. A non-finite delta-seconds value still falls back to jitter. Must be a finite integer `>= 0` when set (`0` skips the `Retry-After` wait). Omitted means a finite `Retry-After` is not clipped. |
|
|
209
211
|
| `init` | `FetchInitOptions` | No | `fetch` options forwarded to every attempt: `method`, `body`, `credentials`, `redirect`, `mode`, `cache`, etc. `signal` is reserved for internal timeout and cancellation. |
|
|
210
212
|
| `headers` | `Record<string, string>` | No | Headers sent on every attempt. Overrides `init.headers` when both are set. |
|
|
211
213
|
| `signal` | `AbortSignal` | No | External abort signal. If already aborted before an attempt, `FetchRetrierAlreadyAbortedError` is thrown. If aborted during an attempt, the in-flight request is aborted: the last attempt fails with `FetchRetrierAbortError`; remaining attempts fail with `FetchRetrierAlreadyAbortedError` without waiting out backoff. If aborted during a full-jitter or `Retry-After` wait, the wait ends immediately and `FetchRetrierAlreadyAbortedError` is thrown. Distinct from `timeoutMs`, which retries remaining attempts and then throws `FetchRetrierAbortError`. |
|
|
@@ -217,7 +219,10 @@ try {
|
|
|
217
219
|
|--------|-------------|
|
|
218
220
|
| `defaultShouldRetry` | Default `shouldRetry` predicate; compose with custom logic. |
|
|
219
221
|
| `DEFAULT_RETRYABLE_HTTP_STATUSES` | Readonly list of HTTP status codes retried by default. |
|
|
220
|
-
| `parseRetryAfterMs` | Parses a `Retry-After` header (delta-seconds or HTTP-date) into a delay in milliseconds. |
|
|
222
|
+
| `parseRetryAfterMs` | Parses a `Retry-After` header (delta-seconds or HTTP-date) into a delay in milliseconds. Pass `ParseRetryAfterOptions` (`{ nowMs }`) to inject the current time. Overflowing delta-seconds are unparsable. |
|
|
223
|
+
| `ParseRetryAfterOptions` | Options for `parseRetryAfterMs`. `nowMs` is the current time in milliseconds and defaults to `Date.now()` when omitted. |
|
|
224
|
+
|
|
225
|
+
`parseRetryAfterMs(value, nowMs)` still works.
|
|
221
226
|
|
|
222
227
|
## Requirements
|
|
223
228
|
|
|
@@ -1,27 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for {@link parseRetryAfterMs}.
|
|
3
|
+
*
|
|
4
|
+
* Pass this object as the second argument. A numeric second argument is still accepted.
|
|
5
|
+
*/
|
|
6
|
+
export interface ParseRetryAfterOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Current time in milliseconds.
|
|
9
|
+
* When omitted, {@link parseRetryAfterMs} uses `Date.now()`.
|
|
10
|
+
*/
|
|
11
|
+
nowMs?: number;
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* Parses a `Retry-After` header value into a delay in milliseconds.
|
|
3
15
|
*
|
|
4
16
|
* Supports RFC 7231 forms: non-negative integer delta-seconds, or an HTTP-date. Empty values,
|
|
5
|
-
* non-integer numerics (e.g. floats or negatives),
|
|
6
|
-
* callers can fall back to full jitter.
|
|
17
|
+
* non-integer numerics (e.g. floats or negatives), unparsable dates, and delta-seconds that
|
|
18
|
+
* overflow to a non-finite delay yield `undefined` so callers can fall back to full jitter.
|
|
19
|
+
* An HTTP-date in the past yields `0`.
|
|
20
|
+
*
|
|
21
|
+
* Prefer `{ nowMs }` from {@link ParseRetryAfterOptions}. A numeric second argument is still accepted.
|
|
7
22
|
*
|
|
8
23
|
* @param value - Raw `Retry-After` header value
|
|
9
|
-
* @param
|
|
24
|
+
* @param nowMsOrOptions - `{ nowMs }` (preferred) or a current time in milliseconds. Defaults to `Date.now()`
|
|
10
25
|
* @returns Delay in milliseconds, or `undefined` when the value cannot be parsed
|
|
11
26
|
*/
|
|
12
|
-
export declare const parseRetryAfterMs: (value: string,
|
|
27
|
+
export declare const parseRetryAfterMs: (value: string, nowMsOrOptions?: number | ParseRetryAfterOptions) => number | undefined;
|
|
13
28
|
/**
|
|
14
29
|
* Chooses the delay before the next HTTP retry: prefer a valid `Retry-After`, else full jitter.
|
|
15
30
|
*
|
|
16
31
|
* Reads `response.headers.get('Retry-After')` and parses it with {@link parseRetryAfterMs}.
|
|
17
32
|
* Missing headers, or values that parse to `undefined`, fall back to {@link fullJitter}.
|
|
18
|
-
*
|
|
33
|
+
* A finite delay is returned as-is when `maxRetryAfterMs` is omitted, and clipped with
|
|
34
|
+
* `Math.min(delay, maxRetryAfterMs)` when that ceiling is set. Abort and network retries do not
|
|
35
|
+
* use this helper.
|
|
19
36
|
*
|
|
20
37
|
* @param response - Non-OK response from the current attempt
|
|
21
38
|
* @param baseBackoffMs - Base backoff passed to {@link fullJitter} when falling back
|
|
22
39
|
* @param attempt - 1-based attempt index
|
|
23
40
|
* @param maxBackoffMs - Optional ceiling applied only to the jitter fallback
|
|
41
|
+
* @param maxRetryAfterMs - Optional ceiling applied only to a finite `Retry-After` delay
|
|
24
42
|
* @param nowMs - Current time in milliseconds (injectable for tests)
|
|
25
43
|
* @returns Wait duration in milliseconds before the next attempt
|
|
26
44
|
*/
|
|
27
|
-
export declare const resolveRetryDelayMs: (response: Response, baseBackoffMs: number, attempt: number, maxBackoffMs?: number, nowMs?: number) => number;
|
|
45
|
+
export declare const resolveRetryDelayMs: (response: Response, baseBackoffMs: number, attempt: number, maxBackoffMs?: number, maxRetryAfterMs?: number, nowMs?: number) => number;
|
|
@@ -2,24 +2,45 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveRetryDelayMs = exports.parseRetryAfterMs = void 0;
|
|
4
4
|
const jitter_1 = require("./jitter");
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the clock for {@link parseRetryAfterMs}.
|
|
7
|
+
*
|
|
8
|
+
* A number is the positional current time. An options object reads `nowMs`.
|
|
9
|
+
* Either form falls back to `Date.now()` when the clock is omitted.
|
|
10
|
+
*/
|
|
11
|
+
const currentTimeMs = (nowMsOrOptions) => {
|
|
12
|
+
if (typeof nowMsOrOptions === 'number') {
|
|
13
|
+
return nowMsOrOptions;
|
|
14
|
+
}
|
|
15
|
+
return nowMsOrOptions?.nowMs ?? Date.now();
|
|
16
|
+
};
|
|
5
17
|
/**
|
|
6
18
|
* Parses a `Retry-After` header value into a delay in milliseconds.
|
|
7
19
|
*
|
|
8
20
|
* Supports RFC 7231 forms: non-negative integer delta-seconds, or an HTTP-date. Empty values,
|
|
9
|
-
* non-integer numerics (e.g. floats or negatives),
|
|
10
|
-
* callers can fall back to full jitter.
|
|
21
|
+
* non-integer numerics (e.g. floats or negatives), unparsable dates, and delta-seconds that
|
|
22
|
+
* overflow to a non-finite delay yield `undefined` so callers can fall back to full jitter.
|
|
23
|
+
* An HTTP-date in the past yields `0`.
|
|
24
|
+
*
|
|
25
|
+
* Prefer `{ nowMs }` from {@link ParseRetryAfterOptions}. A numeric second argument is still accepted.
|
|
11
26
|
*
|
|
12
27
|
* @param value - Raw `Retry-After` header value
|
|
13
|
-
* @param
|
|
28
|
+
* @param nowMsOrOptions - `{ nowMs }` (preferred) or a current time in milliseconds. Defaults to `Date.now()`
|
|
14
29
|
* @returns Delay in milliseconds, or `undefined` when the value cannot be parsed
|
|
15
30
|
*/
|
|
16
|
-
const parseRetryAfterMs = (value,
|
|
31
|
+
const parseRetryAfterMs = (value, nowMsOrOptions) => {
|
|
32
|
+
const nowMs = currentTimeMs(nowMsOrOptions);
|
|
17
33
|
const trimmed = value.trim();
|
|
18
34
|
if (trimmed === '') {
|
|
19
35
|
return undefined;
|
|
20
36
|
}
|
|
21
37
|
if (/^\d+$/.test(trimmed)) {
|
|
22
|
-
|
|
38
|
+
// A long digit string can overflow to Infinity. That delay cannot be waited on safely.
|
|
39
|
+
const delayMs = Number.parseInt(trimmed, 10) * 1000;
|
|
40
|
+
if (!Number.isFinite(delayMs)) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return delayMs;
|
|
23
44
|
}
|
|
24
45
|
// Reject other numeric forms (floats, negatives); not valid delta-seconds or HTTP-date.
|
|
25
46
|
if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
@@ -37,25 +58,31 @@ exports.parseRetryAfterMs = parseRetryAfterMs;
|
|
|
37
58
|
*
|
|
38
59
|
* Reads `response.headers.get('Retry-After')` and parses it with {@link parseRetryAfterMs}.
|
|
39
60
|
* Missing headers, or values that parse to `undefined`, fall back to {@link fullJitter}.
|
|
40
|
-
*
|
|
61
|
+
* A finite delay is returned as-is when `maxRetryAfterMs` is omitted, and clipped with
|
|
62
|
+
* `Math.min(delay, maxRetryAfterMs)` when that ceiling is set. Abort and network retries do not
|
|
63
|
+
* use this helper.
|
|
41
64
|
*
|
|
42
65
|
* @param response - Non-OK response from the current attempt
|
|
43
66
|
* @param baseBackoffMs - Base backoff passed to {@link fullJitter} when falling back
|
|
44
67
|
* @param attempt - 1-based attempt index
|
|
45
68
|
* @param maxBackoffMs - Optional ceiling applied only to the jitter fallback
|
|
69
|
+
* @param maxRetryAfterMs - Optional ceiling applied only to a finite `Retry-After` delay
|
|
46
70
|
* @param nowMs - Current time in milliseconds (injectable for tests)
|
|
47
71
|
* @returns Wait duration in milliseconds before the next attempt
|
|
48
72
|
*/
|
|
49
|
-
const resolveRetryDelayMs = (response, baseBackoffMs, attempt, maxBackoffMs, nowMs = Date.now()) => {
|
|
73
|
+
const resolveRetryDelayMs = (response, baseBackoffMs, attempt, maxBackoffMs, maxRetryAfterMs, nowMs = Date.now()) => {
|
|
50
74
|
const header = response.headers?.get('Retry-After');
|
|
51
75
|
if (header == null) {
|
|
52
76
|
return (0, jitter_1.fullJitter)(baseBackoffMs, attempt, maxBackoffMs);
|
|
53
77
|
}
|
|
54
|
-
const fromHeader = (0, exports.parseRetryAfterMs)(header, nowMs);
|
|
78
|
+
const fromHeader = (0, exports.parseRetryAfterMs)(header, { nowMs });
|
|
55
79
|
if (fromHeader === undefined) {
|
|
56
80
|
return (0, jitter_1.fullJitter)(baseBackoffMs, attempt, maxBackoffMs);
|
|
57
81
|
}
|
|
58
|
-
|
|
82
|
+
if (maxRetryAfterMs === undefined) {
|
|
83
|
+
return fromHeader;
|
|
84
|
+
}
|
|
85
|
+
return Math.min(fromHeader, maxRetryAfterMs);
|
|
59
86
|
};
|
|
60
87
|
exports.resolveRetryDelayMs = resolveRetryDelayMs;
|
|
61
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV0cnktYWZ0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29yZS9iYWNrb2ZmL3JldHJ5LWFmdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFDQUFzQztBQWV0Qzs7Ozs7R0FLRztBQUNILE1BQU0sYUFBYSxHQUFHLENBQUMsY0FBZ0QsRUFBVSxFQUFFO0lBQ2pGLElBQUksT0FBTyxjQUFjLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDdkMsT0FBTyxjQUFjLENBQUM7SUFDeEIsQ0FBQztJQUNELE9BQU8sY0FBYyxFQUFFLEtBQUssSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDN0MsQ0FBQyxDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNJLE1BQU0saUJBQWlCLEdBQUcsQ0FDL0IsS0FBYSxFQUNiLGNBQWdELEVBQzVCLEVBQUU7SUFDdEIsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzVDLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM3QixJQUFJLE9BQU8sS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNuQixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDMUIsdUZBQXVGO1FBQ3ZGLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQztRQUNwRCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzlCLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQsd0ZBQXdGO0lBQ3hGLElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDcEMsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDekIsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQ3JDLENBQUMsQ0FBQztBQTlCVyxRQUFBLGlCQUFpQixxQkE4QjVCO0FBRUY7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSSxNQUFNLG1CQUFtQixHQUFHLENBQ2pDLFFBQWtCLEVBQ2xCLGFBQXFCLEVBQ3JCLE9BQWUsRUFDZixZQUFxQixFQUNyQixlQUF3QixFQUN4QixRQUFnQixJQUFJLENBQUMsR0FBRyxFQUFFLEVBQ2xCLEVBQUU7SUFDVixNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNwRCxJQUFJLE1BQU0sSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNuQixPQUFPLElBQUEsbUJBQVUsRUFBQyxhQUFhLEVBQUUsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzFELENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxJQUFBLHlCQUFpQixFQUFDLE1BQU0sRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDeEQsSUFBSSxVQUFVLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDN0IsT0FBTyxJQUFBLG1CQUFVLEVBQUMsYUFBYSxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBQ0QsSUFBSSxlQUFlLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDbEMsT0FBTyxVQUFVLENBQUM7SUFDcEIsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsZUFBZSxDQUFDLENBQUM7QUFDL0MsQ0FBQyxDQUFDO0FBdEJXLFFBQUEsbUJBQW1CLHVCQXNCOUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmdWxsSml0dGVyIH0gZnJvbSAnLi9qaXR0ZXInO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHtAbGluayBwYXJzZVJldHJ5QWZ0ZXJNc30uXG4gKlxuICogUGFzcyB0aGlzIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50LiBBIG51bWVyaWMgc2Vjb25kIGFyZ3VtZW50IGlzIHN0aWxsIGFjY2VwdGVkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBhcnNlUmV0cnlBZnRlck9wdGlvbnMge1xuICAvKipcbiAgICogQ3VycmVudCB0aW1lIGluIG1pbGxpc2Vjb25kcy5cbiAgICogV2hlbiBvbWl0dGVkLCB7QGxpbmsgcGFyc2VSZXRyeUFmdGVyTXN9IHVzZXMgYERhdGUubm93KClgLlxuICAgKi9cbiAgbm93TXM/OiBudW1iZXI7XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgdGhlIGNsb2NrIGZvciB7QGxpbmsgcGFyc2VSZXRyeUFmdGVyTXN9LlxuICpcbiAqIEEgbnVtYmVyIGlzIHRoZSBwb3NpdGlvbmFsIGN1cnJlbnQgdGltZS4gQW4gb3B0aW9ucyBvYmplY3QgcmVhZHMgYG5vd01zYC5cbiAqIEVpdGhlciBmb3JtIGZhbGxzIGJhY2sgdG8gYERhdGUubm93KClgIHdoZW4gdGhlIGNsb2NrIGlzIG9taXR0ZWQuXG4gKi9cbmNvbnN0IGN1cnJlbnRUaW1lTXMgPSAobm93TXNPck9wdGlvbnM/OiBudW1iZXIgfCBQYXJzZVJldHJ5QWZ0ZXJPcHRpb25zKTogbnVtYmVyID0+IHtcbiAgaWYgKHR5cGVvZiBub3dNc09yT3B0aW9ucyA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gbm93TXNPck9wdGlvbnM7XG4gIH1cbiAgcmV0dXJuIG5vd01zT3JPcHRpb25zPy5ub3dNcyA/PyBEYXRlLm5vdygpO1xufTtcblxuLyoqXG4gKiBQYXJzZXMgYSBgUmV0cnktQWZ0ZXJgIGhlYWRlciB2YWx1ZSBpbnRvIGEgZGVsYXkgaW4gbWlsbGlzZWNvbmRzLlxuICpcbiAqIFN1cHBvcnRzIFJGQyA3MjMxIGZvcm1zOiBub24tbmVnYXRpdmUgaW50ZWdlciBkZWx0YS1zZWNvbmRzLCBvciBhbiBIVFRQLWRhdGUuIEVtcHR5IHZhbHVlcyxcbiAqIG5vbi1pbnRlZ2VyIG51bWVyaWNzIChlLmcuIGZsb2F0cyBvciBuZWdhdGl2ZXMpLCB1bnBhcnNhYmxlIGRhdGVzLCBhbmQgZGVsdGEtc2Vjb25kcyB0aGF0XG4gKiBvdmVyZmxvdyB0byBhIG5vbi1maW5pdGUgZGVsYXkgeWllbGQgYHVuZGVmaW5lZGAgc28gY2FsbGVycyBjYW4gZmFsbCBiYWNrIHRvIGZ1bGwgaml0dGVyLlxuICogQW4gSFRUUC1kYXRlIGluIHRoZSBwYXN0IHlpZWxkcyBgMGAuXG4gKlxuICogUHJlZmVyIGB7IG5vd01zIH1gIGZyb20ge0BsaW5rIFBhcnNlUmV0cnlBZnRlck9wdGlvbnN9LiBBIG51bWVyaWMgc2Vjb25kIGFyZ3VtZW50IGlzIHN0aWxsIGFjY2VwdGVkLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIFJhdyBgUmV0cnktQWZ0ZXJgIGhlYWRlciB2YWx1ZVxuICogQHBhcmFtIG5vd01zT3JPcHRpb25zIC0gYHsgbm93TXMgfWAgKHByZWZlcnJlZCkgb3IgYSBjdXJyZW50IHRpbWUgaW4gbWlsbGlzZWNvbmRzLiBEZWZhdWx0cyB0byBgRGF0ZS5ub3coKWBcbiAqIEByZXR1cm5zIERlbGF5IGluIG1pbGxpc2Vjb25kcywgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGUgdmFsdWUgY2Fubm90IGJlIHBhcnNlZFxuICovXG5leHBvcnQgY29uc3QgcGFyc2VSZXRyeUFmdGVyTXMgPSAoXG4gIHZhbHVlOiBzdHJpbmcsXG4gIG5vd01zT3JPcHRpb25zPzogbnVtYmVyIHwgUGFyc2VSZXRyeUFmdGVyT3B0aW9ucyxcbik6IG51bWJlciB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IG5vd01zID0gY3VycmVudFRpbWVNcyhub3dNc09yT3B0aW9ucyk7XG4gIGNvbnN0IHRyaW1tZWQgPSB2YWx1ZS50cmltKCk7XG4gIGlmICh0cmltbWVkID09PSAnJykge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAoL15cXGQrJC8udGVzdCh0cmltbWVkKSkge1xuICAgIC8vIEEgbG9uZyBkaWdpdCBzdHJpbmcgY2FuIG92ZXJmbG93IHRvIEluZmluaXR5LiBUaGF0IGRlbGF5IGNhbm5vdCBiZSB3YWl0ZWQgb24gc2FmZWx5LlxuICAgIGNvbnN0IGRlbGF5TXMgPSBOdW1iZXIucGFyc2VJbnQodHJpbW1lZCwgMTApICogMTAwMDtcbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShkZWxheU1zKSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIGRlbGF5TXM7XG4gIH1cblxuICAvLyBSZWplY3Qgb3RoZXIgbnVtZXJpYyBmb3JtcyAoZmxvYXRzLCBuZWdhdGl2ZXMpOyBub3QgdmFsaWQgZGVsdGEtc2Vjb25kcyBvciBIVFRQLWRhdGUuXG4gIGlmICgvXi0/XFxkKyhcXC5cXGQrKT8kLy50ZXN0KHRyaW1tZWQpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IGRhdGVNcyA9IERhdGUucGFyc2UodHJpbW1lZCk7XG4gIGlmIChOdW1iZXIuaXNOYU4oZGF0ZU1zKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICByZXR1cm4gTWF0aC5tYXgoMCwgZGF0ZU1zIC0gbm93TXMpO1xufTtcblxuLyoqXG4gKiBDaG9vc2VzIHRoZSBkZWxheSBiZWZvcmUgdGhlIG5leHQgSFRUUCByZXRyeTogcHJlZmVyIGEgdmFsaWQgYFJldHJ5LUFmdGVyYCwgZWxzZSBmdWxsIGppdHRlci5cbiAqXG4gKiBSZWFkcyBgcmVzcG9uc2UuaGVhZGVycy5nZXQoJ1JldHJ5LUFmdGVyJylgIGFuZCBwYXJzZXMgaXQgd2l0aCB7QGxpbmsgcGFyc2VSZXRyeUFmdGVyTXN9LlxuICogTWlzc2luZyBoZWFkZXJzLCBvciB2YWx1ZXMgdGhhdCBwYXJzZSB0byBgdW5kZWZpbmVkYCwgZmFsbCBiYWNrIHRvIHtAbGluayBmdWxsSml0dGVyfS5cbiAqIEEgZmluaXRlIGRlbGF5IGlzIHJldHVybmVkIGFzLWlzIHdoZW4gYG1heFJldHJ5QWZ0ZXJNc2AgaXMgb21pdHRlZCwgYW5kIGNsaXBwZWQgd2l0aFxuICogYE1hdGgubWluKGRlbGF5LCBtYXhSZXRyeUFmdGVyTXMpYCB3aGVuIHRoYXQgY2VpbGluZyBpcyBzZXQuIEFib3J0IGFuZCBuZXR3b3JrIHJldHJpZXMgZG8gbm90XG4gKiB1c2UgdGhpcyBoZWxwZXIuXG4gKlxuICogQHBhcmFtIHJlc3BvbnNlIC0gTm9uLU9LIHJlc3BvbnNlIGZyb20gdGhlIGN1cnJlbnQgYXR0ZW1wdFxuICogQHBhcmFtIGJhc2VCYWNrb2ZmTXMgLSBCYXNlIGJhY2tvZmYgcGFzc2VkIHRvIHtAbGluayBmdWxsSml0dGVyfSB3aGVuIGZhbGxpbmcgYmFja1xuICogQHBhcmFtIGF0dGVtcHQgLSAxLWJhc2VkIGF0dGVtcHQgaW5kZXhcbiAqIEBwYXJhbSBtYXhCYWNrb2ZmTXMgLSBPcHRpb25hbCBjZWlsaW5nIGFwcGxpZWQgb25seSB0byB0aGUgaml0dGVyIGZhbGxiYWNrXG4gKiBAcGFyYW0gbWF4UmV0cnlBZnRlck1zIC0gT3B0aW9uYWwgY2VpbGluZyBhcHBsaWVkIG9ubHkgdG8gYSBmaW5pdGUgYFJldHJ5LUFmdGVyYCBkZWxheVxuICogQHBhcmFtIG5vd01zIC0gQ3VycmVudCB0aW1lIGluIG1pbGxpc2Vjb25kcyAoaW5qZWN0YWJsZSBmb3IgdGVzdHMpXG4gKiBAcmV0dXJucyBXYWl0IGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgdGhlIG5leHQgYXR0ZW1wdFxuICovXG5leHBvcnQgY29uc3QgcmVzb2x2ZVJldHJ5RGVsYXlNcyA9IChcbiAgcmVzcG9uc2U6IFJlc3BvbnNlLFxuICBiYXNlQmFja29mZk1zOiBudW1iZXIsXG4gIGF0dGVtcHQ6IG51bWJlcixcbiAgbWF4QmFja29mZk1zPzogbnVtYmVyLFxuICBtYXhSZXRyeUFmdGVyTXM/OiBudW1iZXIsXG4gIG5vd01zOiBudW1iZXIgPSBEYXRlLm5vdygpLFxuKTogbnVtYmVyID0+IHtcbiAgY29uc3QgaGVhZGVyID0gcmVzcG9uc2UuaGVhZGVycz8uZ2V0KCdSZXRyeS1BZnRlcicpO1xuICBpZiAoaGVhZGVyID09IG51bGwpIHtcbiAgICByZXR1cm4gZnVsbEppdHRlcihiYXNlQmFja29mZk1zLCBhdHRlbXB0LCBtYXhCYWNrb2ZmTXMpO1xuICB9XG5cbiAgY29uc3QgZnJvbUhlYWRlciA9IHBhcnNlUmV0cnlBZnRlck1zKGhlYWRlciwgeyBub3dNcyB9KTtcbiAgaWYgKGZyb21IZWFkZXIgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBmdWxsSml0dGVyKGJhc2VCYWNrb2ZmTXMsIGF0dGVtcHQsIG1heEJhY2tvZmZNcyk7XG4gIH1cbiAgaWYgKG1heFJldHJ5QWZ0ZXJNcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGZyb21IZWFkZXI7XG4gIH1cblxuICByZXR1cm4gTWF0aC5taW4oZnJvbUhlYWRlciwgbWF4UmV0cnlBZnRlck1zKTtcbn07XG4iXX0=
|
package/lib/core/options.d.ts
CHANGED
|
@@ -32,27 +32,34 @@ export interface RequestOptions {
|
|
|
32
32
|
init?: FetchInitOptions;
|
|
33
33
|
/**
|
|
34
34
|
* Maximum number of attempts, including the first.
|
|
35
|
-
* Must be `>= 1`.
|
|
35
|
+
* Must be a finite integer `>= 1`.
|
|
36
36
|
*/
|
|
37
37
|
retries: number;
|
|
38
38
|
/**
|
|
39
39
|
* Per-attempt timeout in milliseconds; uses an internal {@link AbortController} when exceeded.
|
|
40
|
-
* Must be `> 0`.
|
|
40
|
+
* Must be a finite integer `> 0`.
|
|
41
41
|
*/
|
|
42
42
|
timeoutMs: number;
|
|
43
43
|
/**
|
|
44
44
|
* Base backoff in milliseconds for full jitter when `Retry-After` is absent or invalid.
|
|
45
45
|
* The exponential span for attempt `n` is `baseBackoffMs * 2^n`, then the result is clipped
|
|
46
46
|
* by {@link RequestOptions.maxBackoffMs} when that option is set.
|
|
47
|
-
* Must be `>= 0` (`0` skips backoff delay between attempts when falling back to jitter).
|
|
47
|
+
* Must be a finite integer `>= 0` (`0` skips backoff delay between attempts when falling back to jitter).
|
|
48
48
|
*/
|
|
49
49
|
baseBackoffMs: number;
|
|
50
50
|
/**
|
|
51
51
|
* Optional ceiling in milliseconds applied to the full-jitter delay.
|
|
52
52
|
* When set, `Math.min(jitter, maxBackoffMs)` is used. Does not clip a valid `Retry-After`.
|
|
53
|
-
* Must be `>= 0` when provided (`0` skips jitter wait). Omitted means no extra clip.
|
|
53
|
+
* Must be a finite integer `>= 0` when provided (`0` skips jitter wait). Omitted means no extra clip.
|
|
54
54
|
*/
|
|
55
55
|
maxBackoffMs?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Optional ceiling in milliseconds applied to a finite `Retry-After` delay.
|
|
58
|
+
* When set, `Math.min(delay, maxRetryAfterMs)` is used. Does not change full jitter.
|
|
59
|
+
* Must be a finite integer `>= 0` when provided (`0` skips the `Retry-After` wait).
|
|
60
|
+
* Omitted means a finite `Retry-After` delay is not clipped.
|
|
61
|
+
*/
|
|
62
|
+
maxRetryAfterMs?: number;
|
|
56
63
|
/**
|
|
57
64
|
* Optional external {@link AbortSignal}. When aborted during an attempt, the in-flight request
|
|
58
65
|
* is aborted. On the last attempt this surfaces as {@link FetchRetrierAbortError}. If retries
|
package/lib/core/options.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* Public option types for {@link fetchRetrier}.
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL29wdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQdWJsaWMgb3B0aW9uIHR5cGVzIGZvciB7QGxpbmsgZmV0Y2hSZXRyaWVyfS5cbiAqL1xuXG4vKipcbiAqIGBmZXRjaGAgb3B0aW9ucyBmb3J3YXJkZWQgdG8gZXZlcnkgYXR0ZW1wdCwgZXhjbHVkaW5nIGBzaWduYWxgLlxuICpcbiAqIFVzZSBmb3IgYG1ldGhvZGAsIGBib2R5YCwgYGNyZWRlbnRpYWxzYCwgYHJlZGlyZWN0YCwgYG1vZGVgLCBgY2FjaGVgLCBhbmQgb3RoZXJcbiAqIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUmVxdWVzdEluaXQgfCBSZXF1ZXN0SW5pdH0gZmllbGRzLlxuICogUGVyLWF0dGVtcHQgYWJvcnQgYW5kIHRpbWVvdXQgYXJlIGhhbmRsZWQgaW50ZXJuYWxseSB2aWEgYHNpZ25hbGAgYW5kIG11c3Qgbm90IGJlIHNldCBoZXJlLlxuICovXG5leHBvcnQgdHlwZSBGZXRjaEluaXRPcHRpb25zID0gT21pdDxSZXF1ZXN0SW5pdCwgJ3NpZ25hbCc+O1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHtAbGluayBmZXRjaFJldHJpZXJ9OiByZXRyeSBwb2xpY3ksIHRpbWVvdXQsIGJhY2tvZmYgKGluY2x1ZGluZyBgUmV0cnktQWZ0ZXJgKSxcbiAqIHJlcXVlc3QgcGF5bG9hZCwgYW5kIGNhbmNlbGxhdGlvbi5cbiAqXG4gKiBSZXF1ZXN0IHNoYXBlIGlzIGJ1aWx0IGFzIGB7IC4uLmluaXQsIGhlYWRlcnM/LCBzaWduYWwgfWAgb24gZWFjaCBhdHRlbXB0LiBUb3AtbGV2ZWwgYGhlYWRlcnNgXG4gKiBvdmVycmlkZSBgaW5pdC5oZWFkZXJzYCB3aGVuIGJvdGggYXJlIHByb3ZpZGVkLlxuICpcbiAqIE51bWVyaWMgZmllbGRzIGFyZSB2YWxpZGF0ZWQgd2hlbiB7QGxpbmsgZmV0Y2hSZXRyaWVyfSBpcyBjYWxsZWQ7IGludmFsaWQgdmFsdWVzIHRocm93XG4gKiB7QGxpbmsgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcn0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVxdWVzdE9wdGlvbnMge1xuICAvKipcbiAgICogSFRUUCBoZWFkZXJzIHNlbnQgb24gZXZlcnkgYXR0ZW1wdC5cbiAgICogV2hlbiBgaW5pdC5oZWFkZXJzYCBpcyBhbHNvIHNldCwgdGhlc2UgdmFsdWVzIHRha2UgcHJlY2VkZW5jZSBmb3IgZHVwbGljYXRlIGtleXMuXG4gICAqL1xuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwge0BsaW5rIEZldGNoSW5pdE9wdGlvbnN9IG1lcmdlZCBpbnRvIGVhY2ggYGZldGNoYCBjYWxsIChlLmcuIFBPU1QgYG1ldGhvZGAgYW5kIEpTT04gYGJvZHlgKS5cbiAgICogVGhlIHNhbWUgYGluaXRgIGlzIHJldXNlZCBhY3Jvc3MgcmV0cmllcy5cbiAgICovXG4gIGluaXQ/
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL29wdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQdWJsaWMgb3B0aW9uIHR5cGVzIGZvciB7QGxpbmsgZmV0Y2hSZXRyaWVyfS5cbiAqL1xuXG4vKipcbiAqIGBmZXRjaGAgb3B0aW9ucyBmb3J3YXJkZWQgdG8gZXZlcnkgYXR0ZW1wdCwgZXhjbHVkaW5nIGBzaWduYWxgLlxuICpcbiAqIFVzZSBmb3IgYG1ldGhvZGAsIGBib2R5YCwgYGNyZWRlbnRpYWxzYCwgYHJlZGlyZWN0YCwgYG1vZGVgLCBgY2FjaGVgLCBhbmQgb3RoZXJcbiAqIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUmVxdWVzdEluaXQgfCBSZXF1ZXN0SW5pdH0gZmllbGRzLlxuICogUGVyLWF0dGVtcHQgYWJvcnQgYW5kIHRpbWVvdXQgYXJlIGhhbmRsZWQgaW50ZXJuYWxseSB2aWEgYHNpZ25hbGAgYW5kIG11c3Qgbm90IGJlIHNldCBoZXJlLlxuICovXG5leHBvcnQgdHlwZSBGZXRjaEluaXRPcHRpb25zID0gT21pdDxSZXF1ZXN0SW5pdCwgJ3NpZ25hbCc+O1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHtAbGluayBmZXRjaFJldHJpZXJ9OiByZXRyeSBwb2xpY3ksIHRpbWVvdXQsIGJhY2tvZmYgKGluY2x1ZGluZyBgUmV0cnktQWZ0ZXJgKSxcbiAqIHJlcXVlc3QgcGF5bG9hZCwgYW5kIGNhbmNlbGxhdGlvbi5cbiAqXG4gKiBSZXF1ZXN0IHNoYXBlIGlzIGJ1aWx0IGFzIGB7IC4uLmluaXQsIGhlYWRlcnM/LCBzaWduYWwgfWAgb24gZWFjaCBhdHRlbXB0LiBUb3AtbGV2ZWwgYGhlYWRlcnNgXG4gKiBvdmVycmlkZSBgaW5pdC5oZWFkZXJzYCB3aGVuIGJvdGggYXJlIHByb3ZpZGVkLlxuICpcbiAqIE51bWVyaWMgZmllbGRzIGFyZSB2YWxpZGF0ZWQgd2hlbiB7QGxpbmsgZmV0Y2hSZXRyaWVyfSBpcyBjYWxsZWQ7IGludmFsaWQgdmFsdWVzIHRocm93XG4gKiB7QGxpbmsgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcn0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVxdWVzdE9wdGlvbnMge1xuICAvKipcbiAgICogSFRUUCBoZWFkZXJzIHNlbnQgb24gZXZlcnkgYXR0ZW1wdC5cbiAgICogV2hlbiBgaW5pdC5oZWFkZXJzYCBpcyBhbHNvIHNldCwgdGhlc2UgdmFsdWVzIHRha2UgcHJlY2VkZW5jZSBmb3IgZHVwbGljYXRlIGtleXMuXG4gICAqL1xuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwge0BsaW5rIEZldGNoSW5pdE9wdGlvbnN9IG1lcmdlZCBpbnRvIGVhY2ggYGZldGNoYCBjYWxsIChlLmcuIFBPU1QgYG1ldGhvZGAgYW5kIEpTT04gYGJvZHlgKS5cbiAgICogVGhlIHNhbWUgYGluaXRgIGlzIHJldXNlZCBhY3Jvc3MgcmV0cmllcy5cbiAgICovXG4gIGluaXQ/OiBGZXRjaEluaXRPcHRpb25zO1xuICAvKipcbiAgICogTWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMsIGluY2x1ZGluZyB0aGUgZmlyc3QuXG4gICAqIE11c3QgYmUgYSBmaW5pdGUgaW50ZWdlciBgPj0gMWAuXG4gICAqL1xuICByZXRyaWVzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBQZXItYXR0ZW1wdCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kczsgdXNlcyBhbiBpbnRlcm5hbCB7QGxpbmsgQWJvcnRDb250cm9sbGVyfSB3aGVuIGV4Y2VlZGVkLlxuICAgKiBNdXN0IGJlIGEgZmluaXRlIGludGVnZXIgYD4gMGAuXG4gICAqL1xuICB0aW1lb3V0TXM6IG51bWJlcjtcbiAgLyoqXG4gICAqIEJhc2UgYmFja29mZiBpbiBtaWxsaXNlY29uZHMgZm9yIGZ1bGwgaml0dGVyIHdoZW4gYFJldHJ5LUFmdGVyYCBpcyBhYnNlbnQgb3IgaW52YWxpZC5cbiAgICogVGhlIGV4cG9uZW50aWFsIHNwYW4gZm9yIGF0dGVtcHQgYG5gIGlzIGBiYXNlQmFja29mZk1zICogMl5uYCwgdGhlbiB0aGUgcmVzdWx0IGlzIGNsaXBwZWRcbiAgICogYnkge0BsaW5rIFJlcXVlc3RPcHRpb25zLm1heEJhY2tvZmZNc30gd2hlbiB0aGF0IG9wdGlvbiBpcyBzZXQuXG4gICAqIE11c3QgYmUgYSBmaW5pdGUgaW50ZWdlciBgPj0gMGAgKGAwYCBza2lwcyBiYWNrb2ZmIGRlbGF5IGJldHdlZW4gYXR0ZW1wdHMgd2hlbiBmYWxsaW5nIGJhY2sgdG8gaml0dGVyKS5cbiAgICovXG4gIGJhc2VCYWNrb2ZmTXM6IG51bWJlcjtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIGNlaWxpbmcgaW4gbWlsbGlzZWNvbmRzIGFwcGxpZWQgdG8gdGhlIGZ1bGwtaml0dGVyIGRlbGF5LlxuICAgKiBXaGVuIHNldCwgYE1hdGgubWluKGppdHRlciwgbWF4QmFja29mZk1zKWAgaXMgdXNlZC4gRG9lcyBub3QgY2xpcCBhIHZhbGlkIGBSZXRyeS1BZnRlcmAuXG4gICAqIE11c3QgYmUgYSBmaW5pdGUgaW50ZWdlciBgPj0gMGAgd2hlbiBwcm92aWRlZCAoYDBgIHNraXBzIGppdHRlciB3YWl0KS4gT21pdHRlZCBtZWFucyBubyBleHRyYSBjbGlwLlxuICAgKi9cbiAgbWF4QmFja29mZk1zPzogbnVtYmVyO1xuICAvKipcbiAgICogT3B0aW9uYWwgY2VpbGluZyBpbiBtaWxsaXNlY29uZHMgYXBwbGllZCB0byBhIGZpbml0ZSBgUmV0cnktQWZ0ZXJgIGRlbGF5LlxuICAgKiBXaGVuIHNldCwgYE1hdGgubWluKGRlbGF5LCBtYXhSZXRyeUFmdGVyTXMpYCBpcyB1c2VkLiBEb2VzIG5vdCBjaGFuZ2UgZnVsbCBqaXR0ZXIuXG4gICAqIE11c3QgYmUgYSBmaW5pdGUgaW50ZWdlciBgPj0gMGAgd2hlbiBwcm92aWRlZCAoYDBgIHNraXBzIHRoZSBgUmV0cnktQWZ0ZXJgIHdhaXQpLlxuICAgKiBPbWl0dGVkIG1lYW5zIGEgZmluaXRlIGBSZXRyeS1BZnRlcmAgZGVsYXkgaXMgbm90IGNsaXBwZWQuXG4gICAqL1xuICBtYXhSZXRyeUFmdGVyTXM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBleHRlcm5hbCB7QGxpbmsgQWJvcnRTaWduYWx9LiBXaGVuIGFib3J0ZWQgZHVyaW5nIGFuIGF0dGVtcHQsIHRoZSBpbi1mbGlnaHQgcmVxdWVzdFxuICAgKiBpcyBhYm9ydGVkLiBPbiB0aGUgbGFzdCBhdHRlbXB0IHRoaXMgc3VyZmFjZXMgYXMge0BsaW5rIEZldGNoUmV0cmllckFib3J0RXJyb3J9LiBJZiByZXRyaWVzXG4gICAqIHJlbWFpbiwgYmFja29mZiBpcyBza2lwcGVkIGFuZCB0aGUgbmV4dCBhdHRlbXB0IHRocm93c1xuICAgKiB7QGxpbmsgRmV0Y2hSZXRyaWVyQWxyZWFkeUFib3J0ZWRFcnJvcn0uIEFib3J0aW5nIGR1cmluZyBhIGZ1bGwtaml0dGVyIG9yIGBSZXRyeS1BZnRlcmAgd2FpdFxuICAgKiBlbmRzIHRoYXQgd2FpdCBpbW1lZGlhdGVseSBhbmQgdGhyb3dzIHtAbGluayBGZXRjaFJldHJpZXJBbHJlYWR5QWJvcnRlZEVycm9yfS4gRGlzdGluY3QgZnJvbVxuICAgKiBwZXItYXR0ZW1wdCB0aW1lb3V0LCB3aGljaCByZXRyaWVzIHJlbWFpbmluZyBhdHRlbXB0cyBhbmQgb25seSB0aGVuIHRocm93c1xuICAgKiB7QGxpbmsgRmV0Y2hSZXRyaWVyQWJvcnRFcnJvcn0uXG4gICAqL1xuICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgLyoqXG4gICAqIEludm9rZWQgYWZ0ZXIgYHJlc3BvbnNlLnRleHQoKWAgd2hlbiBgcmVzcG9uc2Uub2tgIGlzIGZhbHNlLlxuICAgKiBSZXR1cm4gYHRydWVgIHRvIHNjaGVkdWxlIGFub3RoZXIgYXR0ZW1wdCAodW50aWwgYHJldHJpZXNgIGlzIGV4aGF1c3RlZCkuXG4gICAqIERlZmF1bHQ6IHtAbGluayBkZWZhdWx0U2hvdWxkUmV0cnl9IChzZWUge0BsaW5rIERFRkFVTFRfUkVUUllBQkxFX0hUVFBfU1RBVFVTRVN9KS5cbiAgICpcbiAgICogQHBhcmFtIHJlc3BvbnNlIC0gTm9uLU9LIHJlc3BvbnNlIGZyb20gdGhlIGN1cnJlbnQgYXR0ZW1wdFxuICAgKiBAcGFyYW0gYm9keSAtIFJlc3BvbnNlIGJvZHkgdGV4dCBmcm9tIGByZXNwb25zZS50ZXh0KClgXG4gICAqIEByZXR1cm5zIGB0cnVlYCB0byBzY2hlZHVsZSBhbm90aGVyIGF0dGVtcHQgKHVudGlsIGByZXRyaWVzYCBpcyBleGhhdXN0ZWQpXG4gICAqL1xuICBzaG91bGRSZXRyeT86IChyZXNwb25zZTogUmVzcG9uc2UsIGJvZHk6IHN0cmluZykgPT4gYm9vbGVhbjtcbn1cbiJdfQ==
|
|
@@ -2,11 +2,11 @@ import { RequestOptions } from '../options';
|
|
|
2
2
|
/**
|
|
3
3
|
* Validates retry policy numeric fields on {@link RequestOptions}.
|
|
4
4
|
*
|
|
5
|
-
* Constraints: `retries >= 1`, `timeoutMs > 0`,
|
|
6
|
-
* `maxBackoffMs >= 0`.
|
|
5
|
+
* Each value must be a finite integer. Constraints: `retries >= 1`, `timeoutMs > 0`,
|
|
6
|
+
* `baseBackoffMs >= 0`, and when set `maxBackoffMs >= 0` and `maxRetryAfterMs >= 0`.
|
|
7
7
|
*
|
|
8
8
|
* @param options - Options whose `retries`, `timeoutMs`, `baseBackoffMs`, and optional
|
|
9
|
-
* `maxBackoffMs` are checked
|
|
9
|
+
* `maxBackoffMs` and `maxRetryAfterMs` are checked
|
|
10
10
|
* @throws {FetchRetrierInvalidOptionsError} When any constraint is violated
|
|
11
11
|
*/
|
|
12
|
-
export declare const validateRequestOptions: (options: Pick<RequestOptions, "retries" | "timeoutMs" | "baseBackoffMs" | "maxBackoffMs">) => void;
|
|
12
|
+
export declare const validateRequestOptions: (options: Pick<RequestOptions, "retries" | "timeoutMs" | "baseBackoffMs" | "maxBackoffMs" | "maxRetryAfterMs">) => void;
|
|
@@ -2,30 +2,42 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateRequestOptions = void 0;
|
|
4
4
|
const errors_1 = require("../errors");
|
|
5
|
+
/**
|
|
6
|
+
* True when `value` is a finite integer.
|
|
7
|
+
*
|
|
8
|
+
* Relational checks alone accept `NaN` (every comparison is false) and `Infinity`.
|
|
9
|
+
* A non-integer `retries` also changes how many attempts the loop runs.
|
|
10
|
+
*/
|
|
11
|
+
const isFiniteInteger = (value) => {
|
|
12
|
+
return Number.isFinite(value) && Number.isInteger(value);
|
|
13
|
+
};
|
|
5
14
|
/**
|
|
6
15
|
* Validates retry policy numeric fields on {@link RequestOptions}.
|
|
7
16
|
*
|
|
8
|
-
* Constraints: `retries >= 1`, `timeoutMs > 0`,
|
|
9
|
-
* `maxBackoffMs >= 0`.
|
|
17
|
+
* Each value must be a finite integer. Constraints: `retries >= 1`, `timeoutMs > 0`,
|
|
18
|
+
* `baseBackoffMs >= 0`, and when set `maxBackoffMs >= 0` and `maxRetryAfterMs >= 0`.
|
|
10
19
|
*
|
|
11
20
|
* @param options - Options whose `retries`, `timeoutMs`, `baseBackoffMs`, and optional
|
|
12
|
-
* `maxBackoffMs` are checked
|
|
21
|
+
* `maxBackoffMs` and `maxRetryAfterMs` are checked
|
|
13
22
|
* @throws {FetchRetrierInvalidOptionsError} When any constraint is violated
|
|
14
23
|
*/
|
|
15
24
|
const validateRequestOptions = (options) => {
|
|
16
|
-
const { retries, timeoutMs, baseBackoffMs, maxBackoffMs } = options;
|
|
17
|
-
if (retries < 1) {
|
|
18
|
-
throw new errors_1.FetchRetrierInvalidOptionsError('retries must be >= 1');
|
|
25
|
+
const { retries, timeoutMs, baseBackoffMs, maxBackoffMs, maxRetryAfterMs } = options;
|
|
26
|
+
if (!isFiniteInteger(retries) || retries < 1) {
|
|
27
|
+
throw new errors_1.FetchRetrierInvalidOptionsError('retries must be an integer >= 1');
|
|
28
|
+
}
|
|
29
|
+
if (!isFiniteInteger(timeoutMs) || timeoutMs <= 0) {
|
|
30
|
+
throw new errors_1.FetchRetrierInvalidOptionsError('timeoutMs must be an integer > 0');
|
|
19
31
|
}
|
|
20
|
-
if (
|
|
21
|
-
throw new errors_1.FetchRetrierInvalidOptionsError('
|
|
32
|
+
if (!isFiniteInteger(baseBackoffMs) || baseBackoffMs < 0) {
|
|
33
|
+
throw new errors_1.FetchRetrierInvalidOptionsError('baseBackoffMs must be an integer >= 0');
|
|
22
34
|
}
|
|
23
|
-
if (
|
|
24
|
-
throw new errors_1.FetchRetrierInvalidOptionsError('
|
|
35
|
+
if (maxBackoffMs !== undefined && (!isFiniteInteger(maxBackoffMs) || maxBackoffMs < 0)) {
|
|
36
|
+
throw new errors_1.FetchRetrierInvalidOptionsError('maxBackoffMs must be an integer >= 0');
|
|
25
37
|
}
|
|
26
|
-
if (
|
|
27
|
-
throw new errors_1.FetchRetrierInvalidOptionsError('
|
|
38
|
+
if (maxRetryAfterMs !== undefined && (!isFiniteInteger(maxRetryAfterMs) || maxRetryAfterMs < 0)) {
|
|
39
|
+
throw new errors_1.FetchRetrierInvalidOptionsError('maxRetryAfterMs must be an integer >= 0');
|
|
28
40
|
}
|
|
29
41
|
};
|
|
30
42
|
exports.validateRequestOptions = validateRequestOptions;
|
|
31
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUtb3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb3JlL3BvbGljeS92YWxpZGF0ZS1vcHRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNDQUE0RDtBQUc1RDs7Ozs7R0FLRztBQUNILE1BQU0sZUFBZSxHQUFHLENBQUMsS0FBYSxFQUFXLEVBQUU7SUFDakQsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDM0QsQ0FBQyxDQUFDO0FBRUY7Ozs7Ozs7OztHQVNHO0FBQ0ksTUFBTSxzQkFBc0IsR0FBRyxDQUNwQyxPQUE2RyxFQUN2RyxFQUFFO0lBQ1IsTUFBTSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxlQUFlLEVBQUUsR0FBRyxPQUFPLENBQUM7SUFFckYsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsSUFBSSxPQUFPLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDN0MsTUFBTSxJQUFJLHdDQUErQixDQUFDLGlDQUFpQyxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUNELElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLElBQUksU0FBUyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ2xELE1BQU0sSUFBSSx3Q0FBK0IsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO0lBQ2hGLENBQUM7SUFDRCxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxJQUFJLGFBQWEsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN6RCxNQUFNLElBQUksd0NBQStCLENBQUMsdUNBQXVDLENBQUMsQ0FBQztJQUNyRixDQUFDO0lBQ0QsSUFBSSxZQUFZLEtBQUssU0FBUyxJQUFJLENBQUMsQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLElBQUksWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDdkYsTUFBTSxJQUFJLHdDQUErQixDQUFDLHNDQUFzQyxDQUFDLENBQUM7SUFDcEYsQ0FBQztJQUNELElBQUksZUFBZSxLQUFLLFNBQVMsSUFBSSxDQUFDLENBQUMsZUFBZSxDQUFDLGVBQWUsQ0FBQyxJQUFJLGVBQWUsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2hHLE1BQU0sSUFBSSx3Q0FBK0IsQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO0lBQ3ZGLENBQUM7QUFDSCxDQUFDLENBQUM7QUFwQlcsUUFBQSxzQkFBc0IsMEJBb0JqQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEZldGNoUmV0cmllckludmFsaWRPcHRpb25zRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgUmVxdWVzdE9wdGlvbnMgfSBmcm9tICcuLi9vcHRpb25zJztcblxuLyoqXG4gKiBUcnVlIHdoZW4gYHZhbHVlYCBpcyBhIGZpbml0ZSBpbnRlZ2VyLlxuICpcbiAqIFJlbGF0aW9uYWwgY2hlY2tzIGFsb25lIGFjY2VwdCBgTmFOYCAoZXZlcnkgY29tcGFyaXNvbiBpcyBmYWxzZSkgYW5kIGBJbmZpbml0eWAuXG4gKiBBIG5vbi1pbnRlZ2VyIGByZXRyaWVzYCBhbHNvIGNoYW5nZXMgaG93IG1hbnkgYXR0ZW1wdHMgdGhlIGxvb3AgcnVucy5cbiAqL1xuY29uc3QgaXNGaW5pdGVJbnRlZ2VyID0gKHZhbHVlOiBudW1iZXIpOiBib29sZWFuID0+IHtcbiAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZSh2YWx1ZSkgJiYgTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSk7XG59O1xuXG4vKipcbiAqIFZhbGlkYXRlcyByZXRyeSBwb2xpY3kgbnVtZXJpYyBmaWVsZHMgb24ge0BsaW5rIFJlcXVlc3RPcHRpb25zfS5cbiAqXG4gKiBFYWNoIHZhbHVlIG11c3QgYmUgYSBmaW5pdGUgaW50ZWdlci4gQ29uc3RyYWludHM6IGByZXRyaWVzID49IDFgLCBgdGltZW91dE1zID4gMGAsXG4gKiBgYmFzZUJhY2tvZmZNcyA+PSAwYCwgYW5kIHdoZW4gc2V0IGBtYXhCYWNrb2ZmTXMgPj0gMGAgYW5kIGBtYXhSZXRyeUFmdGVyTXMgPj0gMGAuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25zIHdob3NlIGByZXRyaWVzYCwgYHRpbWVvdXRNc2AsIGBiYXNlQmFja29mZk1zYCwgYW5kIG9wdGlvbmFsXG4gKiAgIGBtYXhCYWNrb2ZmTXNgIGFuZCBgbWF4UmV0cnlBZnRlck1zYCBhcmUgY2hlY2tlZFxuICogQHRocm93cyB7RmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcn0gV2hlbiBhbnkgY29uc3RyYWludCBpcyB2aW9sYXRlZFxuICovXG5leHBvcnQgY29uc3QgdmFsaWRhdGVSZXF1ZXN0T3B0aW9ucyA9IChcbiAgb3B0aW9uczogUGljazxSZXF1ZXN0T3B0aW9ucywgJ3JldHJpZXMnIHwgJ3RpbWVvdXRNcycgfCAnYmFzZUJhY2tvZmZNcycgfCAnbWF4QmFja29mZk1zJyB8ICdtYXhSZXRyeUFmdGVyTXMnPixcbik6IHZvaWQgPT4ge1xuICBjb25zdCB7IHJldHJpZXMsIHRpbWVvdXRNcywgYmFzZUJhY2tvZmZNcywgbWF4QmFja29mZk1zLCBtYXhSZXRyeUFmdGVyTXMgfSA9IG9wdGlvbnM7XG5cbiAgaWYgKCFpc0Zpbml0ZUludGVnZXIocmV0cmllcykgfHwgcmV0cmllcyA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcigncmV0cmllcyBtdXN0IGJlIGFuIGludGVnZXIgPj0gMScpO1xuICB9XG4gIGlmICghaXNGaW5pdGVJbnRlZ2VyKHRpbWVvdXRNcykgfHwgdGltZW91dE1zIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcigndGltZW91dE1zIG11c3QgYmUgYW4gaW50ZWdlciA+IDAnKTtcbiAgfVxuICBpZiAoIWlzRmluaXRlSW50ZWdlcihiYXNlQmFja29mZk1zKSB8fCBiYXNlQmFja29mZk1zIDwgMCkge1xuICAgIHRocm93IG5ldyBGZXRjaFJldHJpZXJJbnZhbGlkT3B0aW9uc0Vycm9yKCdiYXNlQmFja29mZk1zIG11c3QgYmUgYW4gaW50ZWdlciA+PSAwJyk7XG4gIH1cbiAgaWYgKG1heEJhY2tvZmZNcyAhPT0gdW5kZWZpbmVkICYmICghaXNGaW5pdGVJbnRlZ2VyKG1heEJhY2tvZmZNcykgfHwgbWF4QmFja29mZk1zIDwgMCkpIHtcbiAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcignbWF4QmFja29mZk1zIG11c3QgYmUgYW4gaW50ZWdlciA+PSAwJyk7XG4gIH1cbiAgaWYgKG1heFJldHJ5QWZ0ZXJNcyAhPT0gdW5kZWZpbmVkICYmICghaXNGaW5pdGVJbnRlZ2VyKG1heFJldHJ5QWZ0ZXJNcykgfHwgbWF4UmV0cnlBZnRlck1zIDwgMCkpIHtcbiAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVySW52YWxpZE9wdGlvbnNFcnJvcignbWF4UmV0cnlBZnRlck1zIG11c3QgYmUgYW4gaW50ZWdlciA+PSAwJyk7XG4gIH1cbn07XG4iXX0=
|
package/lib/fetch-retrier.d.ts
CHANGED
|
@@ -9,15 +9,18 @@ export type { FetchInitOptions, RequestOptions } from './core/options';
|
|
|
9
9
|
* valid `Retry-After` header (delta-seconds or HTTP-date) is preferred over full jitter; abort
|
|
10
10
|
* and network retries always use full jitter. Those waits end immediately when
|
|
11
11
|
* {@link RequestOptions.signal} aborts. Optional {@link RequestOptions.maxBackoffMs} clips the
|
|
12
|
-
* jitter result, not a valid `Retry-After`.
|
|
13
|
-
*
|
|
12
|
+
* jitter result, not a valid `Retry-After`. Optional {@link RequestOptions.maxRetryAfterMs} clips
|
|
13
|
+
* a finite `Retry-After` delay and does not change jitter. The same {@link FetchInitOptions}
|
|
14
|
+
* (including `body`) is reused on every attempt.
|
|
14
15
|
*
|
|
15
16
|
* @param url - Request URL passed to `fetch`
|
|
16
17
|
* @param options - {@link RequestOptions} controlling retries, timeout, request init, and cancellation
|
|
17
18
|
* @returns The first {@link Response} for which `ok` is `true`
|
|
18
|
-
* @throws {FetchRetrierError}
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* @throws {FetchRetrierError} Failures created by this function are subclasses of this class.
|
|
20
|
+
* An exception that is neither an `AbortError` nor a network `TypeError` is rethrown as-is
|
|
21
|
+
* @throws {FetchRetrierInvalidOptionsError} If `retries` is not a finite integer `>= 1`, `timeoutMs`
|
|
22
|
+
* is not a finite integer `> 0`, `baseBackoffMs` is not a finite integer `>= 0`, or `maxBackoffMs`
|
|
23
|
+
* or `maxRetryAfterMs` is set and is not a finite integer `>= 0`
|
|
21
24
|
* @throws {FetchRetrierAlreadyAbortedError} If `options.signal` is already aborted before an attempt,
|
|
22
25
|
* including after an in-flight external abort while retries remain, or when it aborts during
|
|
23
26
|
* backoff before the next attempt
|
package/lib/fetch-retrier.js
CHANGED
|
@@ -18,15 +18,18 @@ const wait_1 = require("./core/time/wait");
|
|
|
18
18
|
* valid `Retry-After` header (delta-seconds or HTTP-date) is preferred over full jitter; abort
|
|
19
19
|
* and network retries always use full jitter. Those waits end immediately when
|
|
20
20
|
* {@link RequestOptions.signal} aborts. Optional {@link RequestOptions.maxBackoffMs} clips the
|
|
21
|
-
* jitter result, not a valid `Retry-After`.
|
|
22
|
-
*
|
|
21
|
+
* jitter result, not a valid `Retry-After`. Optional {@link RequestOptions.maxRetryAfterMs} clips
|
|
22
|
+
* a finite `Retry-After` delay and does not change jitter. The same {@link FetchInitOptions}
|
|
23
|
+
* (including `body`) is reused on every attempt.
|
|
23
24
|
*
|
|
24
25
|
* @param url - Request URL passed to `fetch`
|
|
25
26
|
* @param options - {@link RequestOptions} controlling retries, timeout, request init, and cancellation
|
|
26
27
|
* @returns The first {@link Response} for which `ok` is `true`
|
|
27
|
-
* @throws {FetchRetrierError}
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* @throws {FetchRetrierError} Failures created by this function are subclasses of this class.
|
|
29
|
+
* An exception that is neither an `AbortError` nor a network `TypeError` is rethrown as-is
|
|
30
|
+
* @throws {FetchRetrierInvalidOptionsError} If `retries` is not a finite integer `>= 1`, `timeoutMs`
|
|
31
|
+
* is not a finite integer `> 0`, `baseBackoffMs` is not a finite integer `>= 0`, or `maxBackoffMs`
|
|
32
|
+
* or `maxRetryAfterMs` is set and is not a finite integer `>= 0`
|
|
30
33
|
* @throws {FetchRetrierAlreadyAbortedError} If `options.signal` is already aborted before an attempt,
|
|
31
34
|
* including after an in-flight external abort while retries remain, or when it aborts during
|
|
32
35
|
* backoff before the next attempt
|
|
@@ -38,8 +41,8 @@ const wait_1 = require("./core/time/wait");
|
|
|
38
41
|
* @throws {FetchRetrierUnreachableError} If the retry loop exits without returning (internal bug)
|
|
39
42
|
*/
|
|
40
43
|
const fetchRetrier = async (url, options) => {
|
|
41
|
-
const { headers, init, retries, timeoutMs, baseBackoffMs, maxBackoffMs, signal: externalSignal, shouldRetry = default_should_retry_1.defaultShouldRetry, } = options;
|
|
42
|
-
(0, validate_options_1.validateRequestOptions)({ retries, timeoutMs, baseBackoffMs, maxBackoffMs });
|
|
44
|
+
const { headers, init, retries, timeoutMs, baseBackoffMs, maxBackoffMs, maxRetryAfterMs, signal: externalSignal, shouldRetry = default_should_retry_1.defaultShouldRetry, } = options;
|
|
45
|
+
(0, validate_options_1.validateRequestOptions)({ retries, timeoutMs, baseBackoffMs, maxBackoffMs, maxRetryAfterMs });
|
|
43
46
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
44
47
|
if (externalSignal?.aborted) {
|
|
45
48
|
throw new errors_1.FetchRetrierAlreadyAbortedError();
|
|
@@ -62,7 +65,7 @@ const fetchRetrier = async (url, options) => {
|
|
|
62
65
|
if ((0, retry_predicates_1.isLastAttempt)(attempt, retries)) {
|
|
63
66
|
throw new errors_1.FetchRetrierHttpError(`HTTP ${res.status}`, res.status, text);
|
|
64
67
|
}
|
|
65
|
-
await (0, wait_1.wait)((0, retry_after_1.resolveRetryDelayMs)(res, baseBackoffMs, attempt, maxBackoffMs), externalSignal);
|
|
68
|
+
await (0, wait_1.wait)((0, retry_after_1.resolveRetryDelayMs)(res, baseBackoffMs, attempt, maxBackoffMs, maxRetryAfterMs), externalSignal);
|
|
66
69
|
}
|
|
67
70
|
catch (err) {
|
|
68
71
|
if (err instanceof Error && err.name === 'AbortError') {
|
|
@@ -85,4 +88,4 @@ const fetchRetrier = async (url, options) => {
|
|
|
85
88
|
throw new errors_1.FetchRetrierUnreachableError();
|
|
86
89
|
};
|
|
87
90
|
exports.fetchRetrier = fetchRetrier;
|
|
88
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmV0Y2gtcmV0cmllci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9mZXRjaC1yZXRyaWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGtEQUFtRDtBQUNuRCw0REFBaUU7QUFDakUsMENBTXVCO0FBQ3ZCLHlEQUFxRDtBQUVyRCw2RUFBd0U7QUFDeEUscUVBQXdFO0FBQ3hFLDhEQUF3RDtBQUN4RCwyQ0FBd0M7QUFJeEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThCRztBQUNJLE1BQU0sWUFBWSxHQUFHLEtBQUssRUFBRSxHQUFXLEVBQUUsT0FBdUIsRUFBcUIsRUFBRTtJQUM1RixNQUFNLEVBQ0osT0FBTyxFQUNQLElBQUksRUFDSixPQUFPLEVBQ1AsU0FBUyxFQUNULGFBQWEsRUFDYixZQUFZLEVBQ1osZUFBZSxFQUNmLE1BQU0sRUFBRSxjQUFjLEVBQ3RCLFdBQVcsR0FBRyx5Q0FBa0IsR0FDakMsR0FBRyxPQUFPLENBQUM7SUFFWixJQUFBLHlDQUFzQixFQUFDLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUM7SUFFN0YsS0FBSyxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxJQUFJLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQ3BELElBQUksY0FBYyxFQUFFLE9BQU8sRUFBRSxDQUFDO1lBQzVCLE1BQU0sSUFBSSx3Q0FBK0IsRUFBRSxDQUFDO1FBQzlDLENBQUM7UUFFRCxJQUFJLENBQUM7WUFDSCxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUEsd0JBQVUsRUFBQyxHQUFHLEVBQUU7Z0JBQ2hDLFNBQVM7Z0JBQ1QsSUFBSTtnQkFDSixPQUFPO2dCQUNQLE1BQU0sRUFBRSxjQUFjO2FBQ3ZCLENBQUMsQ0FBQztZQUVILElBQUksR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNYLE9BQU8sR0FBRyxDQUFDO1lBQ2IsQ0FBQztZQUVELE1BQU0sSUFBSSxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlCLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFFMUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNoQixNQUFNLElBQUksOEJBQXFCLENBQUMsNkJBQTZCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQy9GLENBQUM7WUFFRCxJQUFJLElBQUEsZ0NBQWEsRUFBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDcEMsTUFBTSxJQUFJLDhCQUFxQixDQUFDLFFBQVEsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDMUUsQ0FBQztZQUVELE1BQU0sSUFBQSxXQUFJLEVBQ1IsSUFBQSxpQ0FBbUIsRUFBQyxHQUFHLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsZUFBZSxDQUFDLEVBQy9FLGNBQWMsQ0FDZixDQUFDO1FBQ0osQ0FBQztRQUFDLE9BQU8sR0FBWSxFQUFFLENBQUM7WUFDdEIsSUFBSSxHQUFHLFlBQVksS0FBSyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7Z0JBQ3RELElBQUksSUFBQSxnQ0FBYSxFQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNwQyxNQUFNLEdBQUcsWUFBWSwrQkFBc0IsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLCtCQUFzQixFQUFFLENBQUM7Z0JBQ25GLENBQUM7Z0JBQ0QsTUFBTSxJQUFBLFdBQUksRUFBQyxJQUFBLG1CQUFVLEVBQUMsYUFBYSxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztnQkFDN0UsU0FBUztZQUNYLENBQUM7WUFFRCxJQUFJLEdBQUcsWUFBWSxTQUFTLEVBQUUsQ0FBQztnQkFDN0IsSUFBSSxJQUFBLGdDQUFhLEVBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUM7b0JBQ3BDLE1BQU0sSUFBSSxpQ0FBd0IsQ0FBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQzNELENBQUM7Z0JBQ0QsTUFBTSxJQUFBLFdBQUksRUFBQyxJQUFBLG1CQUFVLEVBQUMsYUFBYSxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztnQkFDN0UsU0FBUztZQUNYLENBQUM7WUFFRCxNQUFNLEdBQUcsQ0FBQztRQUNaLENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxJQUFJLHFDQUE0QixFQUFFLENBQUM7QUFDM0MsQ0FBQyxDQUFDO0FBckVXLFFBQUEsWUFBWSxnQkFxRXZCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZnVsbEppdHRlciB9IGZyb20gJy4vY29yZS9iYWNrb2ZmL2ppdHRlcic7XG5pbXBvcnQgeyByZXNvbHZlUmV0cnlEZWxheU1zIH0gZnJvbSAnLi9jb3JlL2JhY2tvZmYvcmV0cnktYWZ0ZXInO1xuaW1wb3J0IHtcbiAgRmV0Y2hSZXRyaWVyQWJvcnRFcnJvcixcbiAgRmV0Y2hSZXRyaWVyQWxyZWFkeUFib3J0ZWRFcnJvcixcbiAgRmV0Y2hSZXRyaWVySHR0cEVycm9yLFxuICBGZXRjaFJldHJpZXJOZXR3b3JrRXJyb3IsXG4gIEZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3IsXG59IGZyb20gJy4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgdGltZWRGZXRjaCB9IGZyb20gJy4vY29yZS9odHRwL3RpbWVkLWZldGNoJztcbmltcG9ydCB7IFJlcXVlc3RPcHRpb25zIH0gZnJvbSAnLi9jb3JlL29wdGlvbnMnO1xuaW1wb3J0IHsgZGVmYXVsdFNob3VsZFJldHJ5IH0gZnJvbSAnLi9jb3JlL3BvbGljeS9kZWZhdWx0LXNob3VsZC1yZXRyeSc7XG5pbXBvcnQgeyB2YWxpZGF0ZVJlcXVlc3RPcHRpb25zIH0gZnJvbSAnLi9jb3JlL3BvbGljeS92YWxpZGF0ZS1vcHRpb25zJztcbmltcG9ydCB7IGlzTGFzdEF0dGVtcHQgfSBmcm9tICcuL2NvcmUvcmV0cnktcHJlZGljYXRlcyc7XG5pbXBvcnQgeyB3YWl0IH0gZnJvbSAnLi9jb3JlL3RpbWUvd2FpdCc7XG5cbmV4cG9ydCB0eXBlIHsgRmV0Y2hJbml0T3B0aW9ucywgUmVxdWVzdE9wdGlvbnMgfSBmcm9tICcuL2NvcmUvb3B0aW9ucyc7XG5cbi8qKlxuICogV3JhcHMgYGZldGNoYCB3aXRoIHJldHJpZXMsIHBlci1hdHRlbXB0IHRpbWVvdXQsIFJldHJ5LUFmdGVyIHN1cHBvcnQsIGZ1bGwtaml0dGVyIGJhY2tvZmYsIGFuZFxuICogb3B0aW9uYWwgY2FuY2VsbGF0aW9uLlxuICpcbiAqIEVhY2ggYXR0ZW1wdCBjYWxscyB7QGxpbmsgdGltZWRGZXRjaH0gd2l0aCBgdGltZW91dE1zYC4gTm9uLU9LIHJlc3BvbnNlcyBhcmUgcmV0cmllZCB3aGVuXG4gKiBgc2hvdWxkUmV0cnlgIHJldHVybnMgYHRydWVgIChkZWZhdWx0OiB7QGxpbmsgZGVmYXVsdFNob3VsZFJldHJ5fSkuIEJldHdlZW4gSFRUUCByZXRyaWVzLCBhXG4gKiB2YWxpZCBgUmV0cnktQWZ0ZXJgIGhlYWRlciAoZGVsdGEtc2Vjb25kcyBvciBIVFRQLWRhdGUpIGlzIHByZWZlcnJlZCBvdmVyIGZ1bGwgaml0dGVyOyBhYm9ydFxuICogYW5kIG5ldHdvcmsgcmV0cmllcyBhbHdheXMgdXNlIGZ1bGwgaml0dGVyLiBUaG9zZSB3YWl0cyBlbmQgaW1tZWRpYXRlbHkgd2hlblxuICoge0BsaW5rIFJlcXVlc3RPcHRpb25zLnNpZ25hbH0gYWJvcnRzLiBPcHRpb25hbCB7QGxpbmsgUmVxdWVzdE9wdGlvbnMubWF4QmFja29mZk1zfSBjbGlwcyB0aGVcbiAqIGppdHRlciByZXN1bHQsIG5vdCBhIHZhbGlkIGBSZXRyeS1BZnRlcmAuIE9wdGlvbmFsIHtAbGluayBSZXF1ZXN0T3B0aW9ucy5tYXhSZXRyeUFmdGVyTXN9IGNsaXBzXG4gKiBhIGZpbml0ZSBgUmV0cnktQWZ0ZXJgIGRlbGF5IGFuZCBkb2VzIG5vdCBjaGFuZ2Ugaml0dGVyLiBUaGUgc2FtZSB7QGxpbmsgRmV0Y2hJbml0T3B0aW9uc31cbiAqIChpbmNsdWRpbmcgYGJvZHlgKSBpcyByZXVzZWQgb24gZXZlcnkgYXR0ZW1wdC5cbiAqXG4gKiBAcGFyYW0gdXJsIC0gUmVxdWVzdCBVUkwgcGFzc2VkIHRvIGBmZXRjaGBcbiAqIEBwYXJhbSBvcHRpb25zIC0ge0BsaW5rIFJlcXVlc3RPcHRpb25zfSBjb250cm9sbGluZyByZXRyaWVzLCB0aW1lb3V0LCByZXF1ZXN0IGluaXQsIGFuZCBjYW5jZWxsYXRpb25cbiAqIEByZXR1cm5zIFRoZSBmaXJzdCB7QGxpbmsgUmVzcG9uc2V9IGZvciB3aGljaCBgb2tgIGlzIGB0cnVlYFxuICogQHRocm93cyB7RmV0Y2hSZXRyaWVyRXJyb3J9IEZhaWx1cmVzIGNyZWF0ZWQgYnkgdGhpcyBmdW5jdGlvbiBhcmUgc3ViY2xhc3NlcyBvZiB0aGlzIGNsYXNzLlxuICogICBBbiBleGNlcHRpb24gdGhhdCBpcyBuZWl0aGVyIGFuIGBBYm9ydEVycm9yYCBub3IgYSBuZXR3b3JrIGBUeXBlRXJyb3JgIGlzIHJldGhyb3duIGFzLWlzXG4gKiBAdGhyb3dzIHtGZXRjaFJldHJpZXJJbnZhbGlkT3B0aW9uc0Vycm9yfSBJZiBgcmV0cmllc2AgaXMgbm90IGEgZmluaXRlIGludGVnZXIgYD49IDFgLCBgdGltZW91dE1zYFxuICogICBpcyBub3QgYSBmaW5pdGUgaW50ZWdlciBgPiAwYCwgYGJhc2VCYWNrb2ZmTXNgIGlzIG5vdCBhIGZpbml0ZSBpbnRlZ2VyIGA+PSAwYCwgb3IgYG1heEJhY2tvZmZNc2BcbiAqICAgb3IgYG1heFJldHJ5QWZ0ZXJNc2AgaXMgc2V0IGFuZCBpcyBub3QgYSBmaW5pdGUgaW50ZWdlciBgPj0gMGBcbiAqIEB0aHJvd3Mge0ZldGNoUmV0cmllckFscmVhZHlBYm9ydGVkRXJyb3J9IElmIGBvcHRpb25zLnNpZ25hbGAgaXMgYWxyZWFkeSBhYm9ydGVkIGJlZm9yZSBhbiBhdHRlbXB0LFxuICogICBpbmNsdWRpbmcgYWZ0ZXIgYW4gaW4tZmxpZ2h0IGV4dGVybmFsIGFib3J0IHdoaWxlIHJldHJpZXMgcmVtYWluLCBvciB3aGVuIGl0IGFib3J0cyBkdXJpbmdcbiAqICAgYmFja29mZiBiZWZvcmUgdGhlIG5leHQgYXR0ZW1wdFxuICogQHRocm93cyB7RmV0Y2hSZXRyaWVySHR0cEVycm9yfSBPbiBhIG5vbi1PSyByZXNwb25zZSB0aGF0IGlzIG5vdCByZXRyaWVkIG9yIGFmdGVyIHRoZSBsYXN0IGF0dGVtcHRcbiAqICAgKGluY2x1ZGVzIGBzdGF0dXNgIGFuZCBgYm9keWApXG4gKiBAdGhyb3dzIHtGZXRjaFJldHJpZXJOZXR3b3JrRXJyb3J9IE9uIGEgbmV0d29yayBgVHlwZUVycm9yYCBhZnRlciB0aGUgbGFzdCBhdHRlbXB0XG4gKiBAdGhyb3dzIHtGZXRjaFJldHJpZXJBYm9ydEVycm9yfSBPbiBwZXItYXR0ZW1wdCB0aW1lb3V0IGFmdGVyIHRoZSBsYXN0IGF0dGVtcHQsIG9yIGV4dGVybmFsIGFib3J0XG4gKiAgIG9uIHRoZSBsYXN0IGF0dGVtcHRcbiAqIEB0aHJvd3Mge0ZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3J9IElmIHRoZSByZXRyeSBsb29wIGV4aXRzIHdpdGhvdXQgcmV0dXJuaW5nIChpbnRlcm5hbCBidWcpXG4gKi9cbmV4cG9ydCBjb25zdCBmZXRjaFJldHJpZXIgPSBhc3luYyAodXJsOiBzdHJpbmcsIG9wdGlvbnM6IFJlcXVlc3RPcHRpb25zKTogUHJvbWlzZTxSZXNwb25zZT4gPT4ge1xuICBjb25zdCB7XG4gICAgaGVhZGVycyxcbiAgICBpbml0LFxuICAgIHJldHJpZXMsXG4gICAgdGltZW91dE1zLFxuICAgIGJhc2VCYWNrb2ZmTXMsXG4gICAgbWF4QmFja29mZk1zLFxuICAgIG1heFJldHJ5QWZ0ZXJNcyxcbiAgICBzaWduYWw6IGV4dGVybmFsU2lnbmFsLFxuICAgIHNob3VsZFJldHJ5ID0gZGVmYXVsdFNob3VsZFJldHJ5LFxuICB9ID0gb3B0aW9ucztcblxuICB2YWxpZGF0ZVJlcXVlc3RPcHRpb25zKHsgcmV0cmllcywgdGltZW91dE1zLCBiYXNlQmFja29mZk1zLCBtYXhCYWNrb2ZmTXMsIG1heFJldHJ5QWZ0ZXJNcyB9KTtcblxuICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSByZXRyaWVzOyBhdHRlbXB0KyspIHtcbiAgICBpZiAoZXh0ZXJuYWxTaWduYWw/LmFib3J0ZWQpIHtcbiAgICAgIHRocm93IG5ldyBGZXRjaFJldHJpZXJBbHJlYWR5QWJvcnRlZEVycm9yKCk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRpbWVkRmV0Y2godXJsLCB7XG4gICAgICAgIHRpbWVvdXRNcyxcbiAgICAgICAgaW5pdCxcbiAgICAgICAgaGVhZGVycyxcbiAgICAgICAgc2lnbmFsOiBleHRlcm5hbFNpZ25hbCxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAocmVzLm9rKSB7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgY29uc3QgaXNDb250aW51ZSA9IHNob3VsZFJldHJ5KHJlcywgdGV4dCk7XG5cbiAgICAgIGlmICghaXNDb250aW51ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVySHR0cEVycm9yKGBOb24tcmV0cmlhYmxlIEhUVFAgZXJyb3I6ICR7cmVzLnN0YXR1c31gLCByZXMuc3RhdHVzLCB0ZXh0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzTGFzdEF0dGVtcHQoYXR0ZW1wdCwgcmV0cmllcykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEZldGNoUmV0cmllckh0dHBFcnJvcihgSFRUUCAke3Jlcy5zdGF0dXN9YCwgcmVzLnN0YXR1cywgdGV4dCk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHdhaXQoXG4gICAgICAgIHJlc29sdmVSZXRyeURlbGF5TXMocmVzLCBiYXNlQmFja29mZk1zLCBhdHRlbXB0LCBtYXhCYWNrb2ZmTXMsIG1heFJldHJ5QWZ0ZXJNcyksXG4gICAgICAgIGV4dGVybmFsU2lnbmFsLFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnI6IHVua25vd24pIHtcbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnIubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XG4gICAgICAgIGlmIChpc0xhc3RBdHRlbXB0KGF0dGVtcHQsIHJldHJpZXMpKSB7XG4gICAgICAgICAgdGhyb3cgZXJyIGluc3RhbmNlb2YgRmV0Y2hSZXRyaWVyQWJvcnRFcnJvciA/IGVyciA6IG5ldyBGZXRjaFJldHJpZXJBYm9ydEVycm9yKCk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgd2FpdChmdWxsSml0dGVyKGJhc2VCYWNrb2ZmTXMsIGF0dGVtcHQsIG1heEJhY2tvZmZNcyksIGV4dGVybmFsU2lnbmFsKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBUeXBlRXJyb3IpIHtcbiAgICAgICAgaWYgKGlzTGFzdEF0dGVtcHQoYXR0ZW1wdCwgcmV0cmllcykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRmV0Y2hSZXRyaWVyTmV0d29ya0Vycm9yKCdOZXR3b3JrIGVycm9yJywgZXJyKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB3YWl0KGZ1bGxKaXR0ZXIoYmFzZUJhY2tvZmZNcywgYXR0ZW1wdCwgbWF4QmFja29mZk1zKSwgZXh0ZXJuYWxTaWduYWwpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBGZXRjaFJldHJpZXJVbnJlYWNoYWJsZUVycm9yKCk7XG59O1xuIl19
|
package/lib/index.d.ts
CHANGED
|
@@ -9,3 +9,4 @@ export { DEFAULT_RETRYABLE_HTTP_STATUSES, defaultShouldRetry, } from './default-
|
|
|
9
9
|
export { fetchRetrier } from './fetch-retrier';
|
|
10
10
|
export type { FetchInitOptions, RequestOptions } from './fetch-retrier';
|
|
11
11
|
export { parseRetryAfterMs } from './parse-retry-after';
|
|
12
|
+
export type { ParseRetryAfterOptions } from './parse-retry-after';
|
package/lib/index.js
CHANGED
|
@@ -22,4 +22,4 @@ var fetch_retrier_1 = require("./fetch-retrier");
|
|
|
22
22
|
Object.defineProperty(exports, "fetchRetrier", { enumerable: true, get: function () { return fetch_retrier_1.fetchRetrier; } });
|
|
23
23
|
var parse_retry_after_1 = require("./parse-retry-after");
|
|
24
24
|
Object.defineProperty(exports, "parseRetryAfterMs", { enumerable: true, get: function () { return parse_retry_after_1.parseRetryAfterMs; } });
|
|
25
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7OztHQUtHOzs7QUFFSCx3Q0FRdUI7QUFQckIsZ0hBQUEsc0JBQXNCLE9BQUE7QUFDdEIseUhBQUEsK0JBQStCLE9BQUE7QUFDL0IsMkdBQUEsaUJBQWlCLE9BQUE7QUFDakIsK0dBQUEscUJBQXFCLE9BQUE7QUFDckIseUhBQUEsK0JBQStCLE9BQUE7QUFDL0Isa0hBQUEsd0JBQXdCLE9BQUE7QUFDeEIsc0hBQUEsNEJBQTRCLE9BQUE7QUFFOUIsK0RBR2dDO0FBRjlCLHVJQUFBLCtCQUErQixPQUFBO0FBQy9CLDBIQUFBLGtCQUFrQixPQUFBO0FBRXBCLGlEQUErQztBQUF0Qyw2R0FBQSxZQUFZLE9BQUE7QUFFckIseURBQXdEO0FBQS9DLHNIQUFBLGlCQUFpQixPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSZXRyeS1lbmFibGVkIGBmZXRjaGAgd3JhcHBlciB3aXRoIHBlci1hdHRlbXB0IHRpbWVvdXQsIFJldHJ5LUFmdGVyIHN1cHBvcnQsIGZ1bGwtaml0dGVyIGJhY2tvZmYsXG4gKiBvcHRpb24gdmFsaWRhdGlvbiwgYW5kIHR5cGVkIGVycm9ycy5cbiAqXG4gKiBAbW9kdWxlIGZldGNoLXJldHJpZXJcbiAqL1xuXG5leHBvcnQge1xuICBGZXRjaFJldHJpZXJBYm9ydEVycm9yLFxuICBGZXRjaFJldHJpZXJBbHJlYWR5QWJvcnRlZEVycm9yLFxuICBGZXRjaFJldHJpZXJFcnJvcixcbiAgRmV0Y2hSZXRyaWVySHR0cEVycm9yLFxuICBGZXRjaFJldHJpZXJJbnZhbGlkT3B0aW9uc0Vycm9yLFxuICBGZXRjaFJldHJpZXJOZXR3b3JrRXJyb3IsXG4gIEZldGNoUmV0cmllclVucmVhY2hhYmxlRXJyb3IsXG59IGZyb20gJy4vY29yZS9lcnJvcnMnO1xuZXhwb3J0IHtcbiAgREVGQVVMVF9SRVRSWUFCTEVfSFRUUF9TVEFUVVNFUyxcbiAgZGVmYXVsdFNob3VsZFJldHJ5LFxufSBmcm9tICcuL2RlZmF1bHQtc2hvdWxkLXJldHJ5JztcbmV4cG9ydCB7IGZldGNoUmV0cmllciB9IGZyb20gJy4vZmV0Y2gtcmV0cmllcic7XG5leHBvcnQgdHlwZSB7IEZldGNoSW5pdE9wdGlvbnMsIFJlcXVlc3RPcHRpb25zIH0gZnJvbSAnLi9mZXRjaC1yZXRyaWVyJztcbmV4cG9ydCB7IHBhcnNlUmV0cnlBZnRlck1zIH0gZnJvbSAnLi9wYXJzZS1yZXRyeS1hZnRlcic7XG5leHBvcnQgdHlwZSB7IFBhcnNlUmV0cnlBZnRlck9wdGlvbnMgfSBmcm9tICcuL3BhcnNlLXJldHJ5LWFmdGVyJztcbiJdfQ==
|
package/lib/parse-retry-after.js
CHANGED
|
@@ -8,4 +8,4 @@ exports.parseRetryAfterMs = void 0;
|
|
|
8
8
|
*/
|
|
9
9
|
var retry_after_1 = require("./core/backoff/retry-after");
|
|
10
10
|
Object.defineProperty(exports, "parseRetryAfterMs", { enumerable: true, get: function () { return retry_after_1.parseRetryAfterMs; } });
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UtcmV0cnktYWZ0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcGFyc2UtcmV0cnktYWZ0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUE7Ozs7R0FJRztBQUNILDBEQUErRDtBQUF0RCxnSEFBQSxpQkFBaUIsT0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUHVibGljIGVudHJ5IGZvciBwYXJzaW5nIGEgYFJldHJ5LUFmdGVyYCBoZWFkZXIuXG4gKlxuICogVGhlIGltcGxlbWVudGF0aW9uIHN0YXlzIGluIGNvcmUgYmVjYXVzZSBIVFRQIHJldHJ5IGRlbGF5IHNlbGVjdGlvbiB1c2VzIHRoZSBzYW1lIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgeyBwYXJzZVJldHJ5QWZ0ZXJNcyB9IGZyb20gJy4vY29yZS9iYWNrb2ZmL3JldHJ5LWFmdGVyJztcbmV4cG9ydCB0eXBlIHsgUGFyc2VSZXRyeUFmdGVyT3B0aW9ucyB9IGZyb20gJy4vY29yZS9iYWNrb2ZmL3JldHJ5LWFmdGVyJztcbiJdfQ==
|
package/package.json
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"organization": false
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@gammarers/projen-projects": "^0.
|
|
35
|
+
"@gammarers/projen-projects": "^0.8.0",
|
|
36
36
|
"@stylistic/eslint-plugin": "^2",
|
|
37
37
|
"@types/jest": "^30.0.0",
|
|
38
38
|
"@types/node": "^20",
|
|
@@ -64,9 +64,17 @@
|
|
|
64
64
|
"publishConfig": {
|
|
65
65
|
"access": "public"
|
|
66
66
|
},
|
|
67
|
-
"version": "0.
|
|
67
|
+
"version": "0.8.0",
|
|
68
68
|
"jest": {
|
|
69
69
|
"coverageProvider": "v8",
|
|
70
|
+
"coverageThreshold": {
|
|
71
|
+
"global": {
|
|
72
|
+
"branches": 95,
|
|
73
|
+
"functions": 90,
|
|
74
|
+
"lines": 100,
|
|
75
|
+
"statements": 100
|
|
76
|
+
}
|
|
77
|
+
},
|
|
70
78
|
"testMatch": [
|
|
71
79
|
"<rootDir>/@(src|test)/**/*(*.)@(spec|test).ts?(x)",
|
|
72
80
|
"<rootDir>/@(src|test)/**/__tests__/**/*.ts?(x)",
|