@molecule/app-http 1.2.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/provider.js CHANGED
@@ -8,7 +8,12 @@
8
8
  import { t } from '@molecule/app-i18n';
9
9
  import { getLogger } from '@molecule/app-logger';
10
10
  import { awaitAuthGate } from './auth-gate.js';
11
+ import { retryDelayMs, shouldRetryRequest } from './retry.js';
11
12
  import { HttpError } from './types.js';
13
+ /** Wait for a retry backoff. */
14
+ function sleep(ms) {
15
+ return new Promise((resolve) => setTimeout(resolve, ms));
16
+ }
12
17
  /** A response whose body is an HTML document, not JSON. */
13
18
  const HTML_CONTENT_TYPE = /^text\/html\b/i;
14
19
  /**
@@ -121,85 +126,183 @@ export const createFetchClient = (config = {}) => {
121
126
  }
122
127
  }
123
128
  // Create abort controller for timeout
124
- let timeoutId;
125
129
  const timeout = finalConfig.timeout ?? config.timeout;
126
- if (timeout && !finalConfig.signal) {
127
- const controller = new AbortController();
128
- fetchOptions.signal = controller.signal;
129
- timeoutId = setTimeout(() => controller.abort(), timeout);
130
- }
131
- try {
132
- const fetchResponse = await fetch(url, fetchOptions);
133
- if (timeoutId) {
134
- clearTimeout(timeoutId);
130
+ const retryOptions = finalConfig.retry ?? config.retry;
131
+ // Bounded retry of IDEMPOTENT requests only. A rolling deploy restarts
132
+ // one instance at a time, so a 502/503/504 or a reset connection can
133
+ // appear for a few seconds while the platform is healthy. A POST is
134
+ // repeated only when it carries an Idempotency-Key — never blind.
135
+ for (let attempt = 0;; attempt++) {
136
+ // A timeout signal belongs to ONE attempt: reusing an aborted
137
+ // controller would abort every retry instantly.
138
+ let timeoutId;
139
+ if (timeout && !finalConfig.signal) {
140
+ const controller = new AbortController();
141
+ fetchOptions.signal = controller.signal;
142
+ timeoutId = setTimeout(() => controller.abort(), timeout);
135
143
  }
136
- // Parse response headers
137
- const responseHeaders = {};
138
- fetchResponse.headers.forEach((value, key) => {
139
- responseHeaders[key] = value;
140
- });
141
- // Parse response body
142
- let data;
143
- const responseType = finalConfig.responseType || 'json';
144
- switch (responseType) {
145
- case 'text':
146
- data = (await fetchResponse.text());
147
- break;
148
- case 'blob':
149
- data = (await fetchResponse.blob());
150
- break;
151
- case 'arraybuffer':
152
- data = (await fetchResponse.arrayBuffer());
153
- break;
154
- case 'json':
155
- default: {
156
- const text = await fetchResponse.text();
157
- try {
158
- data = text ? JSON.parse(text) : null;
159
- }
160
- catch (_error) {
161
- // Safe to ignore: the raw text is already captured above and used
162
- // as the fallback value. Non-JSON responses (plain text, HTML errors)
163
- // are a known valid case for some APIs.
164
- //
165
- // A 2xx HTML DOCUMENT is not one of those cases: it is the app's page
166
- // server answering a request that expected JSON — the Vite dev server's
167
- // SPA fallback when a relative URL had no API baseURL. Resolving with the
168
- // HTML as `data` turns that into a `Cannot read properties of undefined`
169
- // crash far from the call (xr-molecule-flash-m126: 6.5 minutes and 22
170
- // probe scripts to discover `getClient().baseURL` was `''`).
171
- const contentType = fetchResponse.headers.get('content-type') ?? '';
172
- if (fetchResponse.ok && HTML_CONTENT_TYPE.test(contentType)) {
173
- throw new HttpError(`${finalConfig.method} ${url} answered ${contentType.split(';')[0]} instead of ` +
174
- "JSON — the request reached the page server, not the API; check the client's " +
175
- 'baseURL (a relative path with no baseURL resolves against the page origin)', fetchResponse.status, {
176
- data: text,
177
- status: fetchResponse.status,
178
- statusText: fetchResponse.statusText,
179
- headers: responseHeaders,
180
- config: finalConfig,
181
- }, finalConfig, 'http.error.requestFailed');
144
+ try {
145
+ const fetchResponse = await fetch(url, fetchOptions);
146
+ if (timeoutId) {
147
+ clearTimeout(timeoutId);
148
+ }
149
+ // Parse response headers
150
+ const responseHeaders = {};
151
+ fetchResponse.headers.forEach((value, key) => {
152
+ responseHeaders[key] = value;
153
+ });
154
+ // Parse response body
155
+ let data;
156
+ const responseType = finalConfig.responseType || 'json';
157
+ switch (responseType) {
158
+ case 'text':
159
+ data = (await fetchResponse.text());
160
+ break;
161
+ case 'blob':
162
+ data = (await fetchResponse.blob());
163
+ break;
164
+ case 'arraybuffer':
165
+ data = (await fetchResponse.arrayBuffer());
166
+ break;
167
+ case 'json':
168
+ default: {
169
+ const text = await fetchResponse.text();
170
+ try {
171
+ data = text ? JSON.parse(text) : null;
182
172
  }
183
- logger.debug('Response is not JSON, using raw text', url);
184
- data = text;
173
+ catch (_error) {
174
+ // Safe to ignore: the raw text is already captured above and used
175
+ // as the fallback value. Non-JSON responses (plain text, HTML errors)
176
+ // are a known valid case for some APIs.
177
+ //
178
+ // A 2xx HTML DOCUMENT is not one of those cases: it is the app's page
179
+ // server answering a request that expected JSON — the Vite dev server's
180
+ // SPA fallback when a relative URL had no API baseURL. Resolving with the
181
+ // HTML as `data` turns that into a `Cannot read properties of undefined`
182
+ // crash far from the call (xr-molecule-flash-m126: 6.5 minutes and 22
183
+ // probe scripts to discover `getClient().baseURL` was `''`).
184
+ const contentType = fetchResponse.headers.get('content-type') ?? '';
185
+ if (fetchResponse.ok && HTML_CONTENT_TYPE.test(contentType)) {
186
+ throw new HttpError(`${finalConfig.method} ${url} answered ${contentType.split(';')[0]} instead of ` +
187
+ "JSON — the request reached the page server, not the API; check the client's " +
188
+ 'baseURL (a relative path with no baseURL resolves against the page origin)', fetchResponse.status, {
189
+ data: text,
190
+ status: fetchResponse.status,
191
+ statusText: fetchResponse.statusText,
192
+ headers: responseHeaders,
193
+ config: finalConfig,
194
+ }, finalConfig, 'http.error.requestFailed');
195
+ }
196
+ logger.debug('Response is not JSON, using raw text', url);
197
+ data = text;
198
+ }
199
+ break;
200
+ }
201
+ }
202
+ let response = {
203
+ data,
204
+ status: fetchResponse.status,
205
+ statusText: fetchResponse.statusText,
206
+ headers: responseHeaders,
207
+ config: finalConfig,
208
+ };
209
+ // Handle error status codes
210
+ if (!fetchResponse.ok) {
211
+ logger.warn('HTTP error', finalConfig.method, url, fetchResponse.status);
212
+ const error = new HttpError(t('http.error.requestFailed', { status: fetchResponse.status }, { defaultValue: `Request failed with status ${fetchResponse.status}` }), fetchResponse.status, response, finalConfig, 'http.error.requestFailed');
213
+ // Handle auth errors
214
+ if (fetchResponse.status === 401) {
215
+ authErrorHandlers.forEach((handler) => handler());
185
216
  }
186
- break;
217
+ if (shouldRetryRequest({
218
+ method: finalConfig.method,
219
+ headers,
220
+ status: fetchResponse.status,
221
+ attempt,
222
+ errorMessage: error.message,
223
+ options: retryOptions,
224
+ })) {
225
+ await sleep(retryDelayMs(fetchResponse.headers.get('retry-after') ?? undefined, attempt, retryOptions));
226
+ continue;
227
+ }
228
+ // Apply error interceptors
229
+ let finalError = error;
230
+ for (const interceptor of errorInterceptors) {
231
+ finalError = await interceptor(finalError);
232
+ }
233
+ throw finalError;
234
+ }
235
+ // Apply response interceptors
236
+ for (const interceptor of responseInterceptors) {
237
+ response = (await interceptor(response));
187
238
  }
239
+ return response;
188
240
  }
189
- let response = {
190
- data,
191
- status: fetchResponse.status,
192
- statusText: fetchResponse.statusText,
193
- headers: responseHeaders,
194
- config: finalConfig,
195
- };
196
- // Handle error status codes
197
- if (!fetchResponse.ok) {
198
- logger.warn('HTTP error', finalConfig.method, url, fetchResponse.status);
199
- const error = new HttpError(t('http.error.requestFailed', { status: fetchResponse.status }, { defaultValue: `Request failed with status ${fetchResponse.status}` }), fetchResponse.status, response, finalConfig, 'http.error.requestFailed');
200
- // Handle auth errors
201
- if (fetchResponse.status === 401) {
202
- authErrorHandlers.forEach((handler) => handler());
241
+ catch (err) {
242
+ if (timeoutId) {
243
+ clearTimeout(timeoutId);
244
+ }
245
+ if (err instanceof HttpError) {
246
+ throw err;
247
+ }
248
+ // Distinguish an explicit abort (AbortController, page unload
249
+ // wired up via signal) and SPA navigation-induced cancellation
250
+ // from a real network outage.
251
+ //
252
+ // - AbortError → user-initiated cancel: silent
253
+ // - "TypeError: Failed to fetch" while the browser tab is
254
+ // hidden / unloading → SPA tore down a fetch as it left the
255
+ // page. Demote to warn so it stays visible in the console
256
+ // for debugging but doesn't fail strict console-error gates.
257
+ // - Anything else (including "Failed to fetch" while the tab
258
+ // is visible) → real outage: logger.error.
259
+ //
260
+ // Components that want zero navigation noise should still pass
261
+ // an AbortSignal from their useEffect cleanup.
262
+ const errMsg = err instanceof Error ? err.message : '';
263
+ const errName = err instanceof Error ? err.name : '';
264
+ const isAbort = errName === 'AbortError' ||
265
+ (typeof DOMException !== 'undefined' &&
266
+ err instanceof DOMException &&
267
+ err.name === 'AbortError') ||
268
+ /the user aborted a request/i.test(errMsg);
269
+ const tabHidden = typeof document !== 'undefined' &&
270
+ (document.visibilityState === 'hidden' || document.hidden === true);
271
+ const isNavCancel = !isAbort &&
272
+ errName === 'TypeError' &&
273
+ /failed to fetch|network ?error|load failed/i.test(errMsg) &&
274
+ (tabHidden || navigationInProgress);
275
+ if (isAbort) {
276
+ // silent — not interesting
277
+ }
278
+ else if (isNavCancel) {
279
+ logger.warn('Network request cancelled by navigation', finalConfig.method, url);
280
+ }
281
+ else {
282
+ logger.error('Network error', finalConfig.method, url, err);
283
+ }
284
+ // An abort and a navigation cancellation are the SAME fact to a caller —
285
+ // the request was cancelled before any response — and neither is a network
286
+ // outage. Flag it (`aborted`) and give it its own errorKey so app code does
287
+ // not have to parse the message, and so a session-clearing check can tell
288
+ // it apart from a real failure without treating `status === 0` as a 4xx.
289
+ const aborted = isAbort || isNavCancel;
290
+ const error = new HttpError(err instanceof Error
291
+ ? err.message
292
+ : t(aborted ? 'http.error.aborted' : 'http.error.networkError', undefined, {
293
+ defaultValue: aborted ? 'Request aborted' : 'Network error',
294
+ }), 0, undefined, finalConfig, aborted ? 'http.error.aborted' : 'http.error.networkError', aborted);
295
+ if (shouldRetryRequest({
296
+ method: finalConfig.method,
297
+ headers,
298
+ status: 0,
299
+ attempt,
300
+ errorMessage: errMsg,
301
+ aborted,
302
+ options: retryOptions,
303
+ })) {
304
+ await sleep(retryDelayMs(undefined, attempt, retryOptions));
305
+ continue;
203
306
  }
204
307
  // Apply error interceptors
205
308
  let finalError = error;
@@ -208,64 +311,6 @@ export const createFetchClient = (config = {}) => {
208
311
  }
209
312
  throw finalError;
210
313
  }
211
- // Apply response interceptors
212
- for (const interceptor of responseInterceptors) {
213
- response = (await interceptor(response));
214
- }
215
- return response;
216
- }
217
- catch (err) {
218
- if (timeoutId) {
219
- clearTimeout(timeoutId);
220
- }
221
- if (err instanceof HttpError) {
222
- throw err;
223
- }
224
- // Distinguish an explicit abort (AbortController, page unload
225
- // wired up via signal) and SPA navigation-induced cancellation
226
- // from a real network outage.
227
- //
228
- // - AbortError → user-initiated cancel: silent
229
- // - "TypeError: Failed to fetch" while the browser tab is
230
- // hidden / unloading → SPA tore down a fetch as it left the
231
- // page. Demote to warn so it stays visible in the console
232
- // for debugging but doesn't fail strict console-error gates.
233
- // - Anything else (including "Failed to fetch" while the tab
234
- // is visible) → real outage: logger.error.
235
- //
236
- // Components that want zero navigation noise should still pass
237
- // an AbortSignal from their useEffect cleanup.
238
- const errMsg = err instanceof Error ? err.message : '';
239
- const errName = err instanceof Error ? err.name : '';
240
- const isAbort = errName === 'AbortError' ||
241
- (typeof DOMException !== 'undefined' &&
242
- err instanceof DOMException &&
243
- err.name === 'AbortError') ||
244
- /the user aborted a request/i.test(errMsg);
245
- const tabHidden = typeof document !== 'undefined' &&
246
- (document.visibilityState === 'hidden' || document.hidden === true);
247
- const isNavCancel = !isAbort &&
248
- errName === 'TypeError' &&
249
- /failed to fetch|network ?error|load failed/i.test(errMsg) &&
250
- (tabHidden || navigationInProgress);
251
- if (isAbort) {
252
- // silent — not interesting
253
- }
254
- else if (isNavCancel) {
255
- logger.warn('Network request cancelled by navigation', finalConfig.method, url);
256
- }
257
- else {
258
- logger.error('Network error', finalConfig.method, url, err);
259
- }
260
- const error = new HttpError(err instanceof Error
261
- ? err.message
262
- : t('http.error.networkError', undefined, { defaultValue: 'Network error' }), 0, undefined, finalConfig, 'http.error.networkError');
263
- // Apply error interceptors
264
- let finalError = error;
265
- for (const interceptor of errorInterceptors) {
266
- finalError = await interceptor(finalError);
267
- }
268
- throw finalError;
269
314
  }
270
315
  },
271
316
  get(url, requestConfig) {
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Bounded retry policy for idempotent HTTP requests.
3
+ *
4
+ * A rolling deploy restarts one API instance at a time, so a request can fail
5
+ * with `502`/`503`/`504` or a reset connection for a few seconds even though
6
+ * the platform is healthy. Retrying those — and ONLY those, and only when the
7
+ * request is safe to repeat — turns a user-visible error into a short wait.
8
+ *
9
+ * The rules the policy enforces:
10
+ *
11
+ * - **Idempotent methods only.** `GET`, `HEAD`, `PUT`, `DELETE` and `OPTIONS`
12
+ * may be repeated. `POST` and `PATCH` are retried ONLY when the caller sent
13
+ * an `Idempotency-Key` header, which tells the server to collapse the repeat
14
+ * (a retried POST without one can create two records).
15
+ * - **Transient failures only.** Statuses `502`/`503`/`504`, and connection
16
+ * errors (reset/refused/timeout). A `500` is a server bug, not a rolling
17
+ * restart, and is not retried.
18
+ * - **Bounded.** Two retries by default, exponential backoff with jitter, and
19
+ * `Retry-After` from the server is honored when present.
20
+ * - **Never on an abort.** A cancelled request (effect cleanup, navigation) is
21
+ * not retried.
22
+ *
23
+ * @module
24
+ */
25
+ import type { HttpMethod } from './types.js';
26
+ /**
27
+ * Tuning for the retry policy.
28
+ */
29
+ export interface RetryOptions {
30
+ /**
31
+ * Maximum retries AFTER the first attempt. Defaults to `2` (three attempts
32
+ * in total).
33
+ */
34
+ maxRetries?: number;
35
+ /** Base backoff in milliseconds. Defaults to `300`. */
36
+ baseDelayMs?: number;
37
+ /** Maximum backoff (before `Retry-After` can extend it). Defaults to `5000`. */
38
+ maxDelayMs?: number;
39
+ /** Statuses treated as transient. Defaults to `[502, 503, 504]`. */
40
+ retryStatuses?: number[];
41
+ }
42
+ /** The resolved policy used when a caller passes no options. */
43
+ export declare const DEFAULT_RETRY_OPTIONS: Required<RetryOptions>;
44
+ /** The request fields the policy decides from. */
45
+ export interface RetryDecisionInput {
46
+ /** The request method. */
47
+ method: HttpMethod;
48
+ /** The request headers (lower-cased lookup is done here). */
49
+ headers: Record<string, string | undefined>;
50
+ /** The HTTP status, or `0` when no response arrived. */
51
+ status: number;
52
+ /** How many retries have already been made (0 for the first failure). */
53
+ attempt: number;
54
+ /** The error message, used to recognize a connection reset/refusal. */
55
+ errorMessage?: string;
56
+ /** `true` when the request was aborted before a response. */
57
+ aborted?: boolean;
58
+ /** Overrides layered over {@link DEFAULT_RETRY_OPTIONS}. */
59
+ options?: RetryOptions | false;
60
+ }
61
+ /**
62
+ * Whether a request may be repeated at all.
63
+ *
64
+ * @param method - The HTTP method.
65
+ * @param headers - The request headers (an `Idempotency-Key` makes POST/PATCH repeatable).
66
+ * @returns `true` when repeating the request cannot duplicate a side effect.
67
+ */
68
+ export declare function isIdempotentRequest(method: HttpMethod, headers: Record<string, string | undefined>): boolean;
69
+ /**
70
+ * Whether a connection-level error is transient (a restarted process refuses
71
+ * or resets connections; a DNS or TLS configuration error does not).
72
+ *
73
+ * @param message - The error message.
74
+ * @returns `true` for reset/refused/closed-early/timeout shapes.
75
+ */
76
+ export declare function isTransientConnectionError(message: string | undefined): boolean;
77
+ /**
78
+ * Parse a `Retry-After` header into milliseconds from now.
79
+ *
80
+ * @param value - The header value (`seconds` or an HTTP date).
81
+ * @param now - The clock, injected for tests.
82
+ * @returns Milliseconds to wait, or undefined when absent/unparseable.
83
+ */
84
+ export declare function parseRetryAfter(value: string | undefined, now?: number): number | undefined;
85
+ /**
86
+ * Decide whether one failed request should be retried.
87
+ *
88
+ * @param input - The method, headers, status/error and attempt count.
89
+ * @returns `true` when the request may be repeated.
90
+ */
91
+ export declare function shouldRetryRequest(input: RetryDecisionInput): boolean;
92
+ /**
93
+ * Compute the wait before the next attempt.
94
+ *
95
+ * `Retry-After` wins when the server sent one (it knows when the instance will
96
+ * be back); otherwise exponential backoff with full jitter.
97
+ *
98
+ * @param retryAfter - The raw `Retry-After` header value, when present.
99
+ * @param attempt - How many retries have already been made (0 for the first).
100
+ * @param options - Policy overrides.
101
+ * @param random - Jitter source, injected for tests (defaults to `Math.random`).
102
+ * @returns Milliseconds to wait before retrying.
103
+ */
104
+ export declare function retryDelayMs(retryAfter: string | undefined, attempt: number, options?: RetryOptions | false, random?: () => number): number;
105
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CACzB;AAED,gEAAgE;AAChE,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,YAAY,CAKxD,CAAA;AAED,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IAC3C,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAA;IACf,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,YAAY,GAAG,KAAK,CAAA;CAC/B;AAoBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAC1C,OAAO,CAgBT;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAK/E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,GAAG,GAAE,MAAmB,GACvB,MAAM,GAAG,SAAS,CAOpB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAQrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,GAAG,KAAK,EAC9B,MAAM,GAAE,MAAM,MAAoB,GACjC,MAAM,CASR"}
package/dist/retry.js ADDED
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Bounded retry policy for idempotent HTTP requests.
3
+ *
4
+ * A rolling deploy restarts one API instance at a time, so a request can fail
5
+ * with `502`/`503`/`504` or a reset connection for a few seconds even though
6
+ * the platform is healthy. Retrying those — and ONLY those, and only when the
7
+ * request is safe to repeat — turns a user-visible error into a short wait.
8
+ *
9
+ * The rules the policy enforces:
10
+ *
11
+ * - **Idempotent methods only.** `GET`, `HEAD`, `PUT`, `DELETE` and `OPTIONS`
12
+ * may be repeated. `POST` and `PATCH` are retried ONLY when the caller sent
13
+ * an `Idempotency-Key` header, which tells the server to collapse the repeat
14
+ * (a retried POST without one can create two records).
15
+ * - **Transient failures only.** Statuses `502`/`503`/`504`, and connection
16
+ * errors (reset/refused/timeout). A `500` is a server bug, not a rolling
17
+ * restart, and is not retried.
18
+ * - **Bounded.** Two retries by default, exponential backoff with jitter, and
19
+ * `Retry-After` from the server is honored when present.
20
+ * - **Never on an abort.** A cancelled request (effect cleanup, navigation) is
21
+ * not retried.
22
+ *
23
+ * @module
24
+ */
25
+ /** The resolved policy used when a caller passes no options. */
26
+ export const DEFAULT_RETRY_OPTIONS = {
27
+ maxRetries: 2,
28
+ baseDelayMs: 300,
29
+ maxDelayMs: 5_000,
30
+ retryStatuses: [502, 503, 504],
31
+ };
32
+ /**
33
+ * Read one header case-insensitively.
34
+ *
35
+ * @param headers - The header map.
36
+ * @param name - The header name (any case).
37
+ * @returns The value, or undefined.
38
+ */
39
+ function headerValue(headers, name) {
40
+ const wanted = name.toLowerCase();
41
+ for (const [key, value] of Object.entries(headers)) {
42
+ if (key.toLowerCase() === wanted)
43
+ return value;
44
+ }
45
+ return undefined;
46
+ }
47
+ /**
48
+ * Whether a request may be repeated at all.
49
+ *
50
+ * @param method - The HTTP method.
51
+ * @param headers - The request headers (an `Idempotency-Key` makes POST/PATCH repeatable).
52
+ * @returns `true` when repeating the request cannot duplicate a side effect.
53
+ */
54
+ export function isIdempotentRequest(method, headers) {
55
+ switch (method) {
56
+ case 'GET':
57
+ case 'HEAD':
58
+ case 'PUT':
59
+ case 'DELETE':
60
+ case 'OPTIONS':
61
+ return true;
62
+ case 'POST':
63
+ case 'PATCH':
64
+ // Repeating a create is only safe when the SERVER has a key to collapse
65
+ // the duplicate on — the caller's assertion, not ours to assume.
66
+ return Boolean(headerValue(headers, 'idempotency-key'));
67
+ default:
68
+ return false;
69
+ }
70
+ }
71
+ /**
72
+ * Whether a connection-level error is transient (a restarted process refuses
73
+ * or resets connections; a DNS or TLS configuration error does not).
74
+ *
75
+ * @param message - The error message.
76
+ * @returns `true` for reset/refused/closed-early/timeout shapes.
77
+ */
78
+ export function isTransientConnectionError(message) {
79
+ if (!message)
80
+ return false;
81
+ return /ECONNRESET|ECONNREFUSED|EPIPE|ETIMEDOUT|socket hang up|connection (?:reset|refused|closed)|failed to fetch|fetch failed|network ?error|load failed/i.test(message);
82
+ }
83
+ /**
84
+ * Parse a `Retry-After` header into milliseconds from now.
85
+ *
86
+ * @param value - The header value (`seconds` or an HTTP date).
87
+ * @param now - The clock, injected for tests.
88
+ * @returns Milliseconds to wait, or undefined when absent/unparseable.
89
+ */
90
+ export function parseRetryAfter(value, now = Date.now()) {
91
+ if (!value)
92
+ return undefined;
93
+ const trimmed = value.trim();
94
+ if (/^\d+$/.test(trimmed))
95
+ return Number(trimmed) * 1_000;
96
+ const date = Date.parse(trimmed);
97
+ if (Number.isNaN(date))
98
+ return undefined;
99
+ return Math.max(0, date - now);
100
+ }
101
+ /**
102
+ * Decide whether one failed request should be retried.
103
+ *
104
+ * @param input - The method, headers, status/error and attempt count.
105
+ * @returns `true` when the request may be repeated.
106
+ */
107
+ export function shouldRetryRequest(input) {
108
+ if (input.options === false)
109
+ return false;
110
+ if (input.aborted)
111
+ return false;
112
+ const options = { ...DEFAULT_RETRY_OPTIONS, ...(input.options ?? {}) };
113
+ if (input.attempt >= options.maxRetries)
114
+ return false;
115
+ if (!isIdempotentRequest(input.method, input.headers))
116
+ return false;
117
+ if (input.status !== 0)
118
+ return options.retryStatuses.includes(input.status);
119
+ return isTransientConnectionError(input.errorMessage);
120
+ }
121
+ /**
122
+ * Compute the wait before the next attempt.
123
+ *
124
+ * `Retry-After` wins when the server sent one (it knows when the instance will
125
+ * be back); otherwise exponential backoff with full jitter.
126
+ *
127
+ * @param retryAfter - The raw `Retry-After` header value, when present.
128
+ * @param attempt - How many retries have already been made (0 for the first).
129
+ * @param options - Policy overrides.
130
+ * @param random - Jitter source, injected for tests (defaults to `Math.random`).
131
+ * @returns Milliseconds to wait before retrying.
132
+ */
133
+ export function retryDelayMs(retryAfter, attempt, options, random = Math.random) {
134
+ const resolved = { ...DEFAULT_RETRY_OPTIONS, ...(options === false ? {} : (options ?? {})) };
135
+ const fromHeader = parseRetryAfter(retryAfter);
136
+ if (fromHeader !== undefined)
137
+ return Math.min(fromHeader, resolved.maxDelayMs);
138
+ const exponential = resolved.baseDelayMs * 2 ** attempt;
139
+ // Full jitter in [0, exponential] avoids a fleet of clients retrying in
140
+ // lockstep after one instance restarts.
141
+ const jittered = random() * exponential;
142
+ return Math.min(Math.max(resolved.baseDelayMs / 2, jittered), resolved.maxDelayMs);
143
+ }
144
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}