@fetchkit/ffetch 5.2.1 → 5.3.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 +26 -15
- package/dist/chunk-X64PXWPN.min.js +2 -0
- package/dist/chunk-X64PXWPN.min.js.map +1 -0
- package/dist/{chunk-RV6LC73N.js → chunk-ZIJ2DZYZ.js} +7 -1
- package/dist/chunk-ZIJ2DZYZ.js.map +1 -0
- package/dist/{error-XBHPSMAQ.js → error-H4GGJSCM.js} +4 -2
- package/dist/error-HT5UPPWM.min.js +2 -0
- package/dist/index.cjs +53 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +49 -39
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/plugins/bulkhead.cjs +137 -0
- package/dist/plugins/bulkhead.cjs.map +1 -0
- package/dist/plugins/bulkhead.d.cts +15 -0
- package/dist/plugins/bulkhead.d.ts +15 -0
- package/dist/plugins/bulkhead.js +96 -0
- package/dist/plugins/bulkhead.js.map +1 -0
- package/dist/plugins/circuit.cjs +14 -8
- package/dist/plugins/circuit.cjs.map +1 -1
- package/dist/plugins/circuit.d.cts +16 -3
- package/dist/plugins/circuit.d.ts +16 -3
- package/dist/plugins/circuit.js +15 -9
- package/dist/plugins/circuit.js.map +1 -1
- package/dist/plugins/hedge.cjs +127 -0
- package/dist/plugins/hedge.cjs.map +1 -0
- package/dist/plugins/hedge.d.cts +12 -0
- package/dist/plugins/hedge.d.ts +12 -0
- package/dist/plugins/hedge.js +102 -0
- package/dist/plugins/hedge.js.map +1 -0
- package/package.json +12 -2
- package/dist/chunk-RV6LC73N.js.map +0 -1
- package/dist/chunk-UP35S5ZH.min.js +0 -2
- package/dist/chunk-UP35S5ZH.min.js.map +0 -1
- package/dist/error-7EEQP46E.min.js +0 -2
- /package/dist/{error-7EEQP46E.min.js.map → error-H4GGJSCM.js.map} +0 -0
- /package/dist/{error-XBHPSMAQ.js.map → error-HT5UPPWM.min.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AbortError,
|
|
3
|
+
BulkheadFullError,
|
|
3
4
|
CircuitOpenError,
|
|
4
5
|
HttpError,
|
|
5
6
|
NetworkError,
|
|
6
7
|
RetryLimitError,
|
|
7
8
|
TimeoutError
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ZIJ2DZYZ.js";
|
|
9
10
|
|
|
10
11
|
// src/retry.ts
|
|
11
12
|
var defaultDelay = (ctx) => {
|
|
@@ -205,18 +206,19 @@ function createClient(opts = {}) {
|
|
|
205
206
|
controller = new AbortController();
|
|
206
207
|
}
|
|
207
208
|
pluginContext.metadata.signals.combined = combinedSignal;
|
|
208
|
-
const retryWithHooks = async () => {
|
|
209
|
+
const retryWithHooks = async (dispatchCtx, dispatchSignal) => {
|
|
210
|
+
const requestForAttempt = dispatchCtx.request;
|
|
209
211
|
let attempt = 0;
|
|
210
212
|
const shouldRetryWithHook = (ctx) => {
|
|
211
213
|
attempt = ctx.attempt;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
214
|
+
dispatchCtx.metadata.retry.attempt = attempt;
|
|
215
|
+
dispatchCtx.metadata.retry.lastError = ctx.error;
|
|
216
|
+
dispatchCtx.metadata.retry.lastResponse = ctx.response;
|
|
215
217
|
const retrying = effectiveShouldRetry(ctx);
|
|
216
|
-
|
|
218
|
+
dispatchCtx.metadata.retry.shouldRetryResult = retrying;
|
|
217
219
|
if (retrying && attempt <= effectiveRetries) {
|
|
218
220
|
effectiveHooks.onRetry?.(
|
|
219
|
-
|
|
221
|
+
requestForAttempt,
|
|
220
222
|
attempt - 1,
|
|
221
223
|
ctx.error,
|
|
222
224
|
ctx.response
|
|
@@ -229,21 +231,21 @@ function createClient(opts = {}) {
|
|
|
229
231
|
let res = await retry(
|
|
230
232
|
async () => {
|
|
231
233
|
if (userSignal?.aborted) {
|
|
232
|
-
effectiveHooks.onAbort?.(
|
|
234
|
+
effectiveHooks.onAbort?.(requestForAttempt);
|
|
233
235
|
throw new AbortError("Request was aborted by user");
|
|
234
236
|
}
|
|
235
237
|
if (timeoutSignal?.aborted) {
|
|
236
|
-
effectiveHooks.onTimeout?.(
|
|
238
|
+
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
237
239
|
throw new TimeoutError("signal timed out");
|
|
238
240
|
}
|
|
239
|
-
if (typeof
|
|
240
|
-
|
|
241
|
-
} else if (
|
|
241
|
+
if (typeof dispatchSignal?.throwIfAborted === "function") {
|
|
242
|
+
dispatchSignal.throwIfAborted();
|
|
243
|
+
} else if (dispatchSignal?.aborted) {
|
|
242
244
|
if (userSignal?.aborted) {
|
|
243
|
-
effectiveHooks.onAbort?.(
|
|
245
|
+
effectiveHooks.onAbort?.(requestForAttempt);
|
|
244
246
|
throw new AbortError("Request was aborted by user");
|
|
245
247
|
} else if (timeoutSignal?.aborted) {
|
|
246
|
-
effectiveHooks.onTimeout?.(
|
|
248
|
+
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
247
249
|
throw new TimeoutError("signal timed out");
|
|
248
250
|
} else {
|
|
249
251
|
throw new AbortError(
|
|
@@ -252,23 +254,23 @@ function createClient(opts = {}) {
|
|
|
252
254
|
);
|
|
253
255
|
}
|
|
254
256
|
}
|
|
255
|
-
const reqWithSignal = new Request(
|
|
256
|
-
signal:
|
|
257
|
+
const reqWithSignal = new Request(requestForAttempt, {
|
|
258
|
+
signal: dispatchSignal
|
|
257
259
|
});
|
|
258
260
|
try {
|
|
259
261
|
const handler = init.fetchHandler ?? fetchHandler ?? fetch;
|
|
260
262
|
const response = await handler(reqWithSignal);
|
|
261
263
|
lastResponse = response;
|
|
262
|
-
|
|
264
|
+
dispatchCtx.metadata.retry.lastResponse = response;
|
|
263
265
|
return response;
|
|
264
266
|
} catch (err) {
|
|
265
|
-
|
|
267
|
+
dispatchCtx.metadata.retry.lastError = err;
|
|
266
268
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
267
269
|
if (timeoutSignal?.aborted && (!userSignal || !userSignal.aborted)) {
|
|
268
|
-
effectiveHooks.onTimeout?.(
|
|
270
|
+
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
269
271
|
throw new TimeoutError("signal timed out", err);
|
|
270
272
|
} else if (userSignal?.aborted) {
|
|
271
|
-
effectiveHooks.onAbort?.(
|
|
273
|
+
effectiveHooks.onAbort?.(requestForAttempt);
|
|
272
274
|
throw new AbortError("Request was aborted by user");
|
|
273
275
|
} else {
|
|
274
276
|
throw new AbortError(
|
|
@@ -287,16 +289,16 @@ function createClient(opts = {}) {
|
|
|
287
289
|
effectiveRetries,
|
|
288
290
|
effectiveRetryDelay,
|
|
289
291
|
shouldRetryWithHook,
|
|
290
|
-
|
|
291
|
-
|
|
292
|
+
requestForAttempt,
|
|
293
|
+
dispatchSignal
|
|
292
294
|
);
|
|
293
295
|
if (effectiveHooks.transformResponse) {
|
|
294
|
-
res = await effectiveHooks.transformResponse(res,
|
|
296
|
+
res = await effectiveHooks.transformResponse(res, requestForAttempt);
|
|
295
297
|
}
|
|
296
|
-
await effectiveHooks.after?.(
|
|
297
|
-
await effectiveHooks.onComplete?.(
|
|
298
|
+
await effectiveHooks.after?.(requestForAttempt, res);
|
|
299
|
+
await effectiveHooks.onComplete?.(requestForAttempt, res, void 0);
|
|
298
300
|
if (effectiveThrowOnHttpError && (res.status >= 400 && res.status < 500 && res.status !== 429 || res.status >= 500 || res.status === 429)) {
|
|
299
|
-
const { HttpError: HttpError2 } = await import("./error-
|
|
301
|
+
const { HttpError: HttpError2 } = await import("./error-H4GGJSCM.js");
|
|
300
302
|
throw new HttpError2(
|
|
301
303
|
`HTTP error: ${res.status} ${res.statusText}`,
|
|
302
304
|
res
|
|
@@ -304,11 +306,11 @@ function createClient(opts = {}) {
|
|
|
304
306
|
}
|
|
305
307
|
return res;
|
|
306
308
|
} catch (err) {
|
|
307
|
-
|
|
309
|
+
dispatchCtx.metadata.retry.lastError = err;
|
|
308
310
|
if (lastResponse) {
|
|
309
311
|
const resp = lastResponse;
|
|
310
312
|
if (effectiveThrowOnHttpError && (resp.status >= 400 && resp.status < 500 && resp.status !== 429 || resp.status >= 500 || resp.status === 429)) {
|
|
311
|
-
const { HttpError: HttpError2 } = await import("./error-
|
|
313
|
+
const { HttpError: HttpError2 } = await import("./error-H4GGJSCM.js");
|
|
312
314
|
throw new HttpError2(
|
|
313
315
|
`HTTP error: ${resp.status} ${resp.statusText}`,
|
|
314
316
|
resp
|
|
@@ -317,32 +319,39 @@ function createClient(opts = {}) {
|
|
|
317
319
|
return resp;
|
|
318
320
|
}
|
|
319
321
|
if (err instanceof TimeoutError) {
|
|
320
|
-
await effectiveHooks.onTimeout?.(
|
|
321
|
-
await effectiveHooks.onError?.(
|
|
322
|
-
await effectiveHooks.onComplete?.(
|
|
322
|
+
await effectiveHooks.onTimeout?.(requestForAttempt);
|
|
323
|
+
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
324
|
+
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
323
325
|
throw err;
|
|
324
326
|
}
|
|
325
327
|
if (err instanceof AbortError) {
|
|
326
|
-
await effectiveHooks.onAbort?.(
|
|
327
|
-
await effectiveHooks.onError?.(
|
|
328
|
-
await effectiveHooks.onComplete?.(
|
|
328
|
+
await effectiveHooks.onAbort?.(requestForAttempt);
|
|
329
|
+
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
330
|
+
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
329
331
|
throw err;
|
|
330
332
|
}
|
|
331
333
|
if (err instanceof NetworkError) {
|
|
332
|
-
await effectiveHooks.onError?.(
|
|
333
|
-
await effectiveHooks.onComplete?.(
|
|
334
|
+
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
335
|
+
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
334
336
|
throw err;
|
|
335
337
|
}
|
|
336
338
|
const retryErr = new RetryLimitError(
|
|
337
339
|
typeof err === "object" && err && "message" in err && typeof err.message === "string" ? err.message : "Retry limit reached",
|
|
338
340
|
err
|
|
339
341
|
);
|
|
340
|
-
await effectiveHooks.onError?.(
|
|
341
|
-
await effectiveHooks.onComplete?.(
|
|
342
|
+
await effectiveHooks.onError?.(requestForAttempt, retryErr);
|
|
343
|
+
await effectiveHooks.onComplete?.(
|
|
344
|
+
requestForAttempt,
|
|
345
|
+
void 0,
|
|
346
|
+
retryErr
|
|
347
|
+
);
|
|
342
348
|
throw retryErr;
|
|
343
349
|
}
|
|
344
350
|
};
|
|
345
|
-
const baseDispatch = async () =>
|
|
351
|
+
const baseDispatch = async (ctx) => {
|
|
352
|
+
const dispatchSignal = ctx === pluginContext ? combinedSignal : ctx.request.signal;
|
|
353
|
+
return retryWithHooks(ctx, dispatchSignal);
|
|
354
|
+
};
|
|
346
355
|
let dispatch = baseDispatch;
|
|
347
356
|
for (let i = plugins.length - 1; i >= 0; i--) {
|
|
348
357
|
const plugin = plugins[i];
|
|
@@ -403,6 +412,7 @@ function createClient(opts = {}) {
|
|
|
403
412
|
}
|
|
404
413
|
export {
|
|
405
414
|
AbortError,
|
|
415
|
+
BulkheadFullError,
|
|
406
416
|
CircuitOpenError,
|
|
407
417
|
HttpError,
|
|
408
418
|
NetworkError,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/retry.ts","../src/should-retry.ts","../src/client.ts"],"sourcesContent":["import type { RetryContext } from './types.js'\n\nexport type RetryDelay = number | ((ctx: RetryContext) => number)\n\nexport const defaultDelay: RetryDelay = (ctx) => {\n const retryAfter = ctx.response?.headers.get('Retry-After')\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10)\n if (!isNaN(seconds)) return seconds * 1000\n const date = Date.parse(retryAfter)\n if (!isNaN(date)) return Math.max(0, date - Date.now())\n }\n return 2 ** ctx.attempt * 200 + Math.random() * 100\n}\n\nfunction waitForRetryDelay(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise((resolve) => {\n if (!signal) {\n setTimeout(resolve, ms)\n return\n }\n\n if (signal.aborted) {\n resolve()\n return\n }\n\n const onAbort = () => {\n clearTimeout(timer)\n resolve()\n }\n\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport async function retry(\n fn: () => Promise<Response>,\n retries: number,\n delay: RetryDelay,\n shouldRetry: (ctx: RetryContext) => boolean = () => true,\n request: Request,\n signal?: AbortSignal\n): Promise<Response> {\n let lastErr: unknown\n let lastRes: Response | undefined\n\n for (let i = 0; i <= retries; i++) {\n const ctx: RetryContext = {\n attempt: i + 1,\n request,\n response: lastRes,\n error: lastErr,\n }\n try {\n lastRes = await fn()\n ctx.response = lastRes\n ctx.error = undefined\n if (i < retries && shouldRetry(ctx)) {\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n continue\n }\n return lastRes\n } catch (err) {\n lastErr = err\n ctx.error = err\n if (i === retries || !shouldRetry(ctx)) throw err\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n }\n }\n throw lastErr\n}\n","import { AbortError, CircuitOpenError, TimeoutError } from './error.js'\nimport type { RetryContext } from './types.js'\n\nexport function shouldRetry(ctx: RetryContext): boolean {\n const { error, response } = ctx\n if (\n error instanceof AbortError ||\n error instanceof CircuitOpenError ||\n error instanceof TimeoutError\n )\n return false\n if (!response) return true // network error\n return response.status >= 500 || response.status === 429\n}\n","import type {\r\n FFetchOptions,\r\n FFetch,\r\n FFetchRequestInit,\r\n PendingRequest,\r\n} from './types.js'\r\nimport { retry, defaultDelay } from './retry.js'\r\nimport { shouldRetry as defaultShouldRetry } from './should-retry.js'\r\nimport {\r\n type PluginDispatch,\r\n type PluginRequestContext,\r\n type PluginExtensions,\r\n type PluginRequestPromiseExtensions,\r\n type ClientPlugin,\r\n type PluginExtensionBase,\r\n type PluginRequestPromiseExtensionBase,\r\n} from './plugins.js'\r\nimport {\r\n TimeoutError,\r\n AbortError,\r\n RetryLimitError,\r\n NetworkError,\r\n} from './error.js'\r\n\r\nexport function createClient<\r\n TPlugins extends readonly ClientPlugin<\r\n PluginExtensionBase,\r\n PluginRequestPromiseExtensionBase\r\n >[] = readonly ClientPlugin<\r\n PluginExtensionBase,\r\n PluginRequestPromiseExtensionBase\r\n >[],\r\n>(\r\n opts: FFetchOptions<TPlugins> = {} as FFetchOptions<TPlugins>\r\n): FFetch<\r\n PluginExtensions<TPlugins>,\r\n PluginRequestPromiseExtensions<TPlugins>\r\n> {\r\n const {\r\n timeout: clientDefaultTimeout = 5_000,\r\n retries: clientDefaultRetries = 0,\r\n retryDelay: clientDefaultRetryDelay = defaultDelay,\r\n shouldRetry: clientDefaultShouldRetry = defaultShouldRetry,\r\n hooks: clientDefaultHooks = {},\r\n fetchHandler,\r\n plugins: inputPlugins = [] as unknown as TPlugins,\r\n } = opts\r\n\r\n const extensionDescriptors: PropertyDescriptorMap = Object.create(null)\r\n\r\n const plugins = inputPlugins\r\n .map((plugin, index) => ({ plugin, index }))\r\n .sort((a, b) => {\r\n const aOrder = a.plugin.order ?? 0\r\n const bOrder = b.plugin.order ?? 0\r\n if (aOrder !== bOrder) return aOrder - bOrder\r\n return a.index - b.index\r\n })\r\n .map((entry) => entry.plugin)\r\n\r\n for (const plugin of plugins) {\r\n plugin.setup?.({\r\n defineExtension: (key, descriptor) => {\r\n const propertyKey = key as PropertyKey\r\n if (propertyKey in extensionDescriptors) {\r\n throw new Error(\r\n `Plugin extension collision for property \"${String(propertyKey)}\"`\r\n )\r\n }\r\n if ('get' in descriptor) {\r\n extensionDescriptors[propertyKey] = {\r\n get: descriptor.get,\r\n enumerable: descriptor.enumerable ?? true,\r\n configurable: false,\r\n }\r\n return\r\n }\r\n extensionDescriptors[propertyKey] = {\r\n value: descriptor.value,\r\n writable: false,\r\n enumerable: descriptor.enumerable ?? true,\r\n configurable: false,\r\n }\r\n },\r\n })\r\n }\r\n\r\n const pendingRequests: PendingRequest[] = []\r\n\r\n // Helper to abort all pending requests\r\n function abortAll() {\r\n for (const entry of pendingRequests) {\r\n entry.controller?.abort()\r\n }\r\n }\r\n\r\n const client = (input: RequestInfo | URL, init: FFetchRequestInit = {}) => {\r\n const execute = async () => {\r\n let request = new Request(input, init)\r\n\r\n // Merge hooks: per-request hooks override client hooks, but fallback to client hooks\r\n const effectiveHooks = { ...clientDefaultHooks, ...(init.hooks || {}) }\r\n if (effectiveHooks.transformRequest) {\r\n request = await effectiveHooks.transformRequest(request)\r\n }\r\n await effectiveHooks.before?.(request)\r\n\r\n // Determine retry config (per-request overrides client default)\r\n const effectiveRetries = init.retries ?? clientDefaultRetries\r\n const effectiveRetryDelay =\r\n typeof init.retryDelay !== 'undefined'\r\n ? init.retryDelay\r\n : clientDefaultRetryDelay\r\n const effectiveShouldRetry = init.shouldRetry ?? clientDefaultShouldRetry\r\n\r\n // AbortSignal.timeout/any logic\r\n const effectiveTimeout = init.timeout ?? clientDefaultTimeout\r\n const userSignal = init.signal\r\n const transformedSignal = request.signal\r\n\r\n const pluginContext: PluginRequestContext = {\r\n request,\r\n init,\r\n state: Object.create(null),\r\n metadata: {\r\n startedAt: Date.now(),\r\n timeoutMs: effectiveTimeout,\r\n signals: {\r\n user:\r\n userSignal === undefined || userSignal === null\r\n ? undefined\r\n : userSignal,\r\n transformed: transformedSignal,\r\n },\r\n retry: {\r\n configuredRetries: effectiveRetries,\r\n configuredDelay: effectiveRetryDelay,\r\n attempt: 0,\r\n },\r\n },\r\n }\r\n\r\n for (const plugin of plugins) {\r\n await plugin.preRequest?.(pluginContext)\r\n }\r\n\r\n // Determine throwOnHttpError (per-request overrides client default)\r\n const effectiveThrowOnHttpError =\r\n typeof init.throwOnHttpError !== 'undefined'\r\n ? init.throwOnHttpError\r\n : (opts.throwOnHttpError ?? false)\r\n\r\n // Create timeout signal (manual implementation if AbortSignal.timeout not available)\r\n function createTimeoutSignal(timeout: number): AbortSignal {\r\n if (typeof AbortSignal?.timeout === 'function') {\r\n return AbortSignal.timeout(timeout)\r\n }\r\n const controller = new AbortController()\r\n const timeoutId = setTimeout(() => controller.abort(), timeout)\r\n controller.signal.addEventListener(\r\n 'abort',\r\n () => clearTimeout(timeoutId),\r\n { once: true }\r\n )\r\n return controller.signal\r\n }\r\n\r\n let timeoutSignal: AbortSignal | undefined = undefined\r\n let combinedSignal: AbortSignal | undefined = undefined\r\n let controller: AbortController | undefined = undefined\r\n\r\n if (effectiveTimeout > 0) {\r\n timeoutSignal = createTimeoutSignal(effectiveTimeout)\r\n pluginContext.metadata.signals.timeout = timeoutSignal\r\n }\r\n\r\n const signals: AbortSignal[] = []\r\n if (userSignal) signals.push(userSignal)\r\n if (transformedSignal && transformedSignal !== userSignal) {\r\n signals.push(transformedSignal)\r\n }\r\n if (timeoutSignal) signals.push(timeoutSignal)\r\n\r\n if (signals.length === 1) {\r\n combinedSignal = signals[0]\r\n controller = new AbortController()\r\n } else {\r\n if (typeof AbortSignal.any !== 'function') {\r\n throw new Error(\r\n 'AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it.'\r\n )\r\n }\r\n combinedSignal = AbortSignal.any(signals)\r\n controller = new AbortController()\r\n }\r\n pluginContext.metadata.signals.combined = combinedSignal\r\n\r\n const retryWithHooks = async () => {\r\n let attempt = 0\r\n const shouldRetryWithHook = (ctx: import('./types').RetryContext) => {\r\n attempt = ctx.attempt\r\n pluginContext.metadata.retry.attempt = attempt\r\n pluginContext.metadata.retry.lastError = ctx.error\r\n pluginContext.metadata.retry.lastResponse = ctx.response\r\n const retrying = effectiveShouldRetry(ctx)\r\n pluginContext.metadata.retry.shouldRetryResult = retrying\r\n if (retrying && attempt <= effectiveRetries) {\r\n effectiveHooks.onRetry?.(\r\n request,\r\n attempt - 1,\r\n ctx.error,\r\n ctx.response\r\n )\r\n }\r\n return retrying\r\n }\r\n\r\n let lastResponse: Response | undefined = undefined\r\n try {\r\n let res = await retry(\r\n async () => {\r\n if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n }\r\n if (timeoutSignal?.aborted) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out')\r\n }\r\n if (typeof combinedSignal?.throwIfAborted === 'function') {\r\n combinedSignal.throwIfAborted()\r\n } else if (combinedSignal?.aborted) {\r\n if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n } else if (timeoutSignal?.aborted) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out')\r\n } else {\r\n throw new AbortError(\r\n 'Request was aborted',\r\n new DOMException('Aborted', 'AbortError')\r\n )\r\n }\r\n }\r\n const reqWithSignal = new Request(request, {\r\n signal: combinedSignal,\r\n })\r\n try {\r\n const handler = init.fetchHandler ?? fetchHandler ?? fetch\r\n const response = await handler(reqWithSignal)\r\n lastResponse = response\r\n pluginContext.metadata.retry.lastResponse = response\r\n return response\r\n } catch (err) {\r\n pluginContext.metadata.retry.lastError = err\r\n if (err instanceof DOMException && err.name === 'AbortError') {\r\n if (\r\n timeoutSignal?.aborted &&\r\n (!userSignal || !userSignal.aborted)\r\n ) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out', err)\r\n } else if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n } else {\r\n throw new AbortError(\r\n 'Request was aborted',\r\n new DOMException('Aborted', 'AbortError')\r\n )\r\n }\r\n } else if (\r\n err instanceof TypeError &&\r\n /NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(\r\n err.message\r\n )\r\n ) {\r\n throw new NetworkError(err.message, err)\r\n }\r\n throw err\r\n }\r\n },\r\n effectiveRetries,\r\n effectiveRetryDelay,\r\n shouldRetryWithHook,\r\n request,\r\n combinedSignal\r\n )\r\n if (effectiveHooks.transformResponse) {\r\n res = await effectiveHooks.transformResponse(res, request)\r\n }\r\n await effectiveHooks.after?.(request, res)\r\n await effectiveHooks.onComplete?.(request, res, undefined)\r\n if (\r\n effectiveThrowOnHttpError &&\r\n ((res.status >= 400 && res.status < 500 && res.status !== 429) ||\r\n res.status >= 500 ||\r\n res.status === 429)\r\n ) {\r\n const { HttpError } = await import('./error.js')\r\n throw new HttpError(\r\n `HTTP error: ${res.status} ${res.statusText}`,\r\n res\r\n )\r\n }\r\n return res\r\n } catch (err: unknown) {\r\n pluginContext.metadata.retry.lastError = err\r\n if (lastResponse) {\r\n const resp = lastResponse as Response\r\n if (\r\n effectiveThrowOnHttpError &&\r\n ((resp.status >= 400 &&\r\n resp.status < 500 &&\r\n resp.status !== 429) ||\r\n resp.status >= 500 ||\r\n resp.status === 429)\r\n ) {\r\n const { HttpError } = await import('./error.js')\r\n throw new HttpError(\r\n `HTTP error: ${resp.status} ${resp.statusText}`,\r\n resp\r\n )\r\n }\r\n return resp\r\n }\r\n if (err instanceof TimeoutError) {\r\n await effectiveHooks.onTimeout?.(request)\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n if (err instanceof AbortError) {\r\n await effectiveHooks.onAbort?.(request)\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n if (err instanceof NetworkError) {\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n const retryErr = new RetryLimitError(\r\n typeof err === 'object' &&\r\n err &&\r\n 'message' in err &&\r\n typeof (err as { message?: unknown }).message === 'string'\r\n ? (err as { message: string }).message\r\n : 'Retry limit reached',\r\n err\r\n )\r\n await effectiveHooks.onError?.(request, retryErr)\r\n await effectiveHooks.onComplete?.(request, undefined, retryErr)\r\n throw retryErr\r\n }\r\n }\r\n\r\n const baseDispatch: PluginDispatch = async () => retryWithHooks()\r\n\r\n let dispatch = baseDispatch\r\n for (let i = plugins.length - 1; i >= 0; i--) {\r\n const plugin = plugins[i]\r\n if (plugin.wrapDispatch) {\r\n dispatch = plugin.wrapDispatch(dispatch)\r\n }\r\n }\r\n\r\n const actualPromise = dispatch(pluginContext)\r\n .then(async (response) => {\r\n for (const plugin of plugins) {\r\n await plugin.onSuccess?.(pluginContext, response)\r\n }\r\n return response\r\n })\r\n .catch(async (err: unknown) => {\r\n for (const plugin of plugins) {\r\n await plugin.onError?.(pluginContext, err)\r\n }\r\n throw err\r\n })\r\n\r\n const pendingEntry: PendingRequest = {\r\n promise: actualPromise,\r\n request,\r\n controller,\r\n }\r\n pendingRequests.push(pendingEntry)\r\n\r\n return actualPromise.finally(async () => {\r\n for (const plugin of plugins) {\r\n await plugin.onFinally?.(pluginContext)\r\n }\r\n\r\n const index = pendingRequests.indexOf(pendingEntry)\r\n if (index > -1) {\r\n pendingRequests.splice(index, 1)\r\n }\r\n })\r\n }\r\n\r\n let promise = execute() as Promise<Response>\r\n for (const plugin of plugins) {\r\n if (plugin.decoratePromise) {\r\n promise = plugin.decoratePromise(promise)\r\n }\r\n }\r\n return promise as Promise<Response> &\r\n PluginRequestPromiseExtensions<TPlugins>\r\n }\r\n\r\n Object.defineProperty(client, 'pendingRequests', {\r\n get() {\r\n return pendingRequests\r\n },\r\n enumerable: false,\r\n configurable: false,\r\n })\r\n\r\n Object.defineProperty(client, 'abortAll', {\r\n value: abortAll,\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n })\r\n\r\n Object.defineProperties(client, extensionDescriptors)\r\n\r\n return client as FFetch<\r\n PluginExtensions<TPlugins>,\r\n PluginRequestPromiseExtensions<TPlugins>\r\n >\r\n}\r\n"],"mappings":"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","names":["shouldRetry","controller","HttpError"]}
|
|
1
|
+
{"version":3,"sources":["../src/retry.ts","../src/should-retry.ts","../src/client.ts"],"sourcesContent":["import type { RetryContext } from './types.js'\n\nexport type RetryDelay = number | ((ctx: RetryContext) => number)\n\nexport const defaultDelay: RetryDelay = (ctx) => {\n const retryAfter = ctx.response?.headers.get('Retry-After')\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10)\n if (!isNaN(seconds)) return seconds * 1000\n const date = Date.parse(retryAfter)\n if (!isNaN(date)) return Math.max(0, date - Date.now())\n }\n return 2 ** ctx.attempt * 200 + Math.random() * 100\n}\n\nfunction waitForRetryDelay(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise((resolve) => {\n if (!signal) {\n setTimeout(resolve, ms)\n return\n }\n\n if (signal.aborted) {\n resolve()\n return\n }\n\n const onAbort = () => {\n clearTimeout(timer)\n resolve()\n }\n\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport async function retry(\n fn: () => Promise<Response>,\n retries: number,\n delay: RetryDelay,\n shouldRetry: (ctx: RetryContext) => boolean = () => true,\n request: Request,\n signal?: AbortSignal\n): Promise<Response> {\n let lastErr: unknown\n let lastRes: Response | undefined\n\n for (let i = 0; i <= retries; i++) {\n const ctx: RetryContext = {\n attempt: i + 1,\n request,\n response: lastRes,\n error: lastErr,\n }\n try {\n lastRes = await fn()\n ctx.response = lastRes\n ctx.error = undefined\n if (i < retries && shouldRetry(ctx)) {\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n continue\n }\n return lastRes\n } catch (err) {\n lastErr = err\n ctx.error = err\n if (i === retries || !shouldRetry(ctx)) throw err\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n }\n }\n throw lastErr\n}\n","import { AbortError, CircuitOpenError, TimeoutError } from './error.js'\nimport type { RetryContext } from './types.js'\n\nexport function shouldRetry(ctx: RetryContext): boolean {\n const { error, response } = ctx\n if (\n error instanceof AbortError ||\n error instanceof CircuitOpenError ||\n error instanceof TimeoutError\n )\n return false\n if (!response) return true // network error\n return response.status >= 500 || response.status === 429\n}\n","import type {\n FFetchOptions,\n FFetch,\n FFetchRequestInit,\n PendingRequest,\n} from './types.js'\nimport { retry, defaultDelay } from './retry.js'\nimport { shouldRetry as defaultShouldRetry } from './should-retry.js'\nimport {\n type PluginDispatch,\n type PluginRequestContext,\n type PluginExtensions,\n type PluginRequestPromiseExtensions,\n type ClientPlugin,\n type PluginExtensionBase,\n type PluginRequestPromiseExtensionBase,\n} from './plugins.js'\nimport {\n TimeoutError,\n AbortError,\n RetryLimitError,\n NetworkError,\n} from './error.js'\n\nexport function createClient<\n TPlugins extends readonly ClientPlugin<\n PluginExtensionBase,\n PluginRequestPromiseExtensionBase\n >[] = readonly ClientPlugin<\n PluginExtensionBase,\n PluginRequestPromiseExtensionBase\n >[],\n>(\n opts: FFetchOptions<TPlugins> = {} as FFetchOptions<TPlugins>\n): FFetch<\n PluginExtensions<TPlugins>,\n PluginRequestPromiseExtensions<TPlugins>\n> {\n const {\n timeout: clientDefaultTimeout = 5_000,\n retries: clientDefaultRetries = 0,\n retryDelay: clientDefaultRetryDelay = defaultDelay,\n shouldRetry: clientDefaultShouldRetry = defaultShouldRetry,\n hooks: clientDefaultHooks = {},\n fetchHandler,\n plugins: inputPlugins = [] as unknown as TPlugins,\n } = opts\n\n const extensionDescriptors: PropertyDescriptorMap = Object.create(null)\n\n const plugins = inputPlugins\n .map((plugin, index) => ({ plugin, index }))\n .sort((a, b) => {\n const aOrder = a.plugin.order ?? 0\n const bOrder = b.plugin.order ?? 0\n if (aOrder !== bOrder) return aOrder - bOrder\n return a.index - b.index\n })\n .map((entry) => entry.plugin)\n\n for (const plugin of plugins) {\n plugin.setup?.({\n defineExtension: (key, descriptor) => {\n const propertyKey = key as PropertyKey\n if (propertyKey in extensionDescriptors) {\n throw new Error(\n `Plugin extension collision for property \"${String(propertyKey)}\"`\n )\n }\n if ('get' in descriptor) {\n extensionDescriptors[propertyKey] = {\n get: descriptor.get,\n enumerable: descriptor.enumerable ?? true,\n configurable: false,\n }\n return\n }\n extensionDescriptors[propertyKey] = {\n value: descriptor.value,\n writable: false,\n enumerable: descriptor.enumerable ?? true,\n configurable: false,\n }\n },\n })\n }\n\n const pendingRequests: PendingRequest[] = []\n\n // Helper to abort all pending requests\n function abortAll() {\n for (const entry of pendingRequests) {\n entry.controller?.abort()\n }\n }\n\n const client = (input: RequestInfo | URL, init: FFetchRequestInit = {}) => {\n const execute = async () => {\n let request = new Request(input, init)\n\n // Merge hooks: per-request hooks override client hooks, but fallback to client hooks\n const effectiveHooks = { ...clientDefaultHooks, ...(init.hooks || {}) }\n if (effectiveHooks.transformRequest) {\n request = await effectiveHooks.transformRequest(request)\n }\n await effectiveHooks.before?.(request)\n\n // Determine retry config (per-request overrides client default)\n const effectiveRetries = init.retries ?? clientDefaultRetries\n const effectiveRetryDelay =\n typeof init.retryDelay !== 'undefined'\n ? init.retryDelay\n : clientDefaultRetryDelay\n const effectiveShouldRetry = init.shouldRetry ?? clientDefaultShouldRetry\n\n // AbortSignal.timeout/any logic\n const effectiveTimeout = init.timeout ?? clientDefaultTimeout\n const userSignal = init.signal\n const transformedSignal = request.signal\n\n const pluginContext: PluginRequestContext = {\n request,\n init,\n state: Object.create(null),\n metadata: {\n startedAt: Date.now(),\n timeoutMs: effectiveTimeout,\n signals: {\n user:\n userSignal === undefined || userSignal === null\n ? undefined\n : userSignal,\n transformed: transformedSignal,\n },\n retry: {\n configuredRetries: effectiveRetries,\n configuredDelay: effectiveRetryDelay,\n attempt: 0,\n },\n },\n }\n\n for (const plugin of plugins) {\n await plugin.preRequest?.(pluginContext)\n }\n\n // Determine throwOnHttpError (per-request overrides client default)\n const effectiveThrowOnHttpError =\n typeof init.throwOnHttpError !== 'undefined'\n ? init.throwOnHttpError\n : (opts.throwOnHttpError ?? false)\n\n // Create timeout signal (manual implementation if AbortSignal.timeout not available)\n function createTimeoutSignal(timeout: number): AbortSignal {\n if (typeof AbortSignal?.timeout === 'function') {\n return AbortSignal.timeout(timeout)\n }\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n controller.signal.addEventListener(\n 'abort',\n () => clearTimeout(timeoutId),\n { once: true }\n )\n return controller.signal\n }\n\n let timeoutSignal: AbortSignal | undefined = undefined\n let combinedSignal: AbortSignal | undefined = undefined\n let controller: AbortController | undefined = undefined\n\n if (effectiveTimeout > 0) {\n timeoutSignal = createTimeoutSignal(effectiveTimeout)\n pluginContext.metadata.signals.timeout = timeoutSignal\n }\n\n const signals: AbortSignal[] = []\n if (userSignal) signals.push(userSignal)\n if (transformedSignal && transformedSignal !== userSignal) {\n signals.push(transformedSignal)\n }\n if (timeoutSignal) signals.push(timeoutSignal)\n\n if (signals.length === 1) {\n combinedSignal = signals[0]\n controller = new AbortController()\n } else {\n if (typeof AbortSignal.any !== 'function') {\n throw new Error(\n 'AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it.'\n )\n }\n combinedSignal = AbortSignal.any(signals)\n controller = new AbortController()\n }\n pluginContext.metadata.signals.combined = combinedSignal\n\n const retryWithHooks = async (\n dispatchCtx: PluginRequestContext,\n dispatchSignal: AbortSignal | undefined\n ) => {\n const requestForAttempt = dispatchCtx.request\n let attempt = 0\n const shouldRetryWithHook = (ctx: import('./types').RetryContext) => {\n attempt = ctx.attempt\n dispatchCtx.metadata.retry.attempt = attempt\n dispatchCtx.metadata.retry.lastError = ctx.error\n dispatchCtx.metadata.retry.lastResponse = ctx.response\n const retrying = effectiveShouldRetry(ctx)\n dispatchCtx.metadata.retry.shouldRetryResult = retrying\n if (retrying && attempt <= effectiveRetries) {\n effectiveHooks.onRetry?.(\n requestForAttempt,\n attempt - 1,\n ctx.error,\n ctx.response\n )\n }\n return retrying\n }\n\n let lastResponse: Response | undefined = undefined\n try {\n let res = await retry(\n async () => {\n if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n }\n if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out')\n }\n if (typeof dispatchSignal?.throwIfAborted === 'function') {\n dispatchSignal.throwIfAborted()\n } else if (dispatchSignal?.aborted) {\n if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n } else if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out')\n } else {\n throw new AbortError(\n 'Request was aborted',\n new DOMException('Aborted', 'AbortError')\n )\n }\n }\n const reqWithSignal = new Request(requestForAttempt, {\n signal: dispatchSignal,\n })\n try {\n const handler = init.fetchHandler ?? fetchHandler ?? fetch\n const response = await handler(reqWithSignal)\n lastResponse = response\n dispatchCtx.metadata.retry.lastResponse = response\n return response\n } catch (err) {\n dispatchCtx.metadata.retry.lastError = err\n if (err instanceof DOMException && err.name === 'AbortError') {\n if (\n timeoutSignal?.aborted &&\n (!userSignal || !userSignal.aborted)\n ) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out', err)\n } else if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n } else {\n throw new AbortError(\n 'Request was aborted',\n new DOMException('Aborted', 'AbortError')\n )\n }\n } else if (\n err instanceof TypeError &&\n /NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(\n err.message\n )\n ) {\n throw new NetworkError(err.message, err)\n }\n throw err\n }\n },\n effectiveRetries,\n effectiveRetryDelay,\n shouldRetryWithHook,\n requestForAttempt,\n dispatchSignal\n )\n if (effectiveHooks.transformResponse) {\n res = await effectiveHooks.transformResponse(res, requestForAttempt)\n }\n await effectiveHooks.after?.(requestForAttempt, res)\n await effectiveHooks.onComplete?.(requestForAttempt, res, undefined)\n if (\n effectiveThrowOnHttpError &&\n ((res.status >= 400 && res.status < 500 && res.status !== 429) ||\n res.status >= 500 ||\n res.status === 429)\n ) {\n const { HttpError } = await import('./error.js')\n throw new HttpError(\n `HTTP error: ${res.status} ${res.statusText}`,\n res\n )\n }\n return res\n } catch (err: unknown) {\n dispatchCtx.metadata.retry.lastError = err\n if (lastResponse) {\n const resp = lastResponse as Response\n if (\n effectiveThrowOnHttpError &&\n ((resp.status >= 400 &&\n resp.status < 500 &&\n resp.status !== 429) ||\n resp.status >= 500 ||\n resp.status === 429)\n ) {\n const { HttpError } = await import('./error.js')\n throw new HttpError(\n `HTTP error: ${resp.status} ${resp.statusText}`,\n resp\n )\n }\n return resp\n }\n if (err instanceof TimeoutError) {\n await effectiveHooks.onTimeout?.(requestForAttempt)\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n if (err instanceof AbortError) {\n await effectiveHooks.onAbort?.(requestForAttempt)\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n if (err instanceof NetworkError) {\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n const retryErr = new RetryLimitError(\n typeof err === 'object' &&\n err &&\n 'message' in err &&\n typeof (err as { message?: unknown }).message === 'string'\n ? (err as { message: string }).message\n : 'Retry limit reached',\n err\n )\n await effectiveHooks.onError?.(requestForAttempt, retryErr)\n await effectiveHooks.onComplete?.(\n requestForAttempt,\n undefined,\n retryErr\n )\n throw retryErr\n }\n }\n\n const baseDispatch: PluginDispatch = async (ctx) => {\n const dispatchSignal =\n ctx === pluginContext ? combinedSignal : ctx.request.signal\n return retryWithHooks(ctx, dispatchSignal)\n }\n\n let dispatch = baseDispatch\n for (let i = plugins.length - 1; i >= 0; i--) {\n const plugin = plugins[i]\n if (plugin.wrapDispatch) {\n dispatch = plugin.wrapDispatch(dispatch)\n }\n }\n\n const actualPromise = dispatch(pluginContext)\n .then(async (response) => {\n for (const plugin of plugins) {\n await plugin.onSuccess?.(pluginContext, response)\n }\n return response\n })\n .catch(async (err: unknown) => {\n for (const plugin of plugins) {\n await plugin.onError?.(pluginContext, err)\n }\n throw err\n })\n\n const pendingEntry: PendingRequest = {\n promise: actualPromise,\n request,\n controller,\n }\n pendingRequests.push(pendingEntry)\n\n return actualPromise.finally(async () => {\n for (const plugin of plugins) {\n await plugin.onFinally?.(pluginContext)\n }\n\n const index = pendingRequests.indexOf(pendingEntry)\n if (index > -1) {\n pendingRequests.splice(index, 1)\n }\n })\n }\n\n let promise = execute() as Promise<Response>\n for (const plugin of plugins) {\n if (plugin.decoratePromise) {\n promise = plugin.decoratePromise(promise)\n }\n }\n return promise as Promise<Response> &\n PluginRequestPromiseExtensions<TPlugins>\n }\n\n Object.defineProperty(client, 'pendingRequests', {\n get() {\n return pendingRequests\n },\n enumerable: false,\n configurable: false,\n })\n\n Object.defineProperty(client, 'abortAll', {\n value: abortAll,\n writable: false,\n enumerable: false,\n configurable: false,\n })\n\n Object.defineProperties(client, extensionDescriptors)\n\n return client as FFetch<\n PluginExtensions<TPlugins>,\n PluginRequestPromiseExtensions<TPlugins>\n >\n}\n"],"mappings":"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","names":["shouldRetry","controller","HttpError"]}
|
package/dist/index.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as E,b as
|
|
1
|
+
import{a as E,b as $,c as te,d as b,e as W,f as v,g as re}from"./chunk-X64PXWPN.min.js";var J=f=>{let u=f.response?.headers.get("Retry-After");if(u){let o=parseInt(u,10);if(!isNaN(o))return o*1e3;let g=Date.parse(u);if(!isNaN(g))return Math.max(0,g-Date.now())}return 2**f.attempt*200+Math.random()*100};function G(f,u){return f<=0?Promise.resolve():new Promise(o=>{if(!u){setTimeout(o,f);return}if(u.aborted){o();return}let g=()=>{clearTimeout(D),o()},D=setTimeout(()=>{u.removeEventListener("abort",g),o()},f);u.addEventListener("abort",g,{once:!0})})}async function Q(f,u,o,g=()=>!0,D,C){let T,A;for(let w=0;w<=u;w++){let l={attempt:w+1,request:D,response:A,error:T};try{if(A=await f(),l.response=A,l.error=void 0,w<u&&g(l)){let p=typeof o=="function"?o(l):o;await G(p,C);continue}return A}catch(p){if(T=p,l.error=p,w===u||!g(l))throw p;let j=typeof o=="function"?o(l):o;await G(j,C)}}throw T}function V(f){let{error:u,response:o}=f;return u instanceof b||u instanceof $||u instanceof E?!1:o?o.status>=500||o.status===429:!0}function ne(f={}){let{timeout:u=5e3,retries:o=0,retryDelay:g=J,shouldRetry:D=V,hooks:C={},fetchHandler:T,plugins:A=[]}=f,w=Object.create(null),l=A.map((c,a)=>({plugin:c,index:a})).sort((c,a)=>{let h=c.plugin.order??0,m=a.plugin.order??0;return h!==m?h-m:c.index-a.index}).map(c=>c.plugin);for(let c of l)c.setup?.({defineExtension:(a,h)=>{let m=a;if(m in w)throw new Error(`Plugin extension collision for property "${String(m)}"`);if("get"in h){w[m]={get:h.get,enumerable:h.enumerable??!0,configurable:!1};return}w[m]={value:h.value,writable:!1,enumerable:h.enumerable??!0,configurable:!1}}});let p=[];function j(){for(let c of p)c.controller?.abort()}let O=(c,a={})=>{let m=(async()=>{let R=new Request(c,a),r={...C,...a.hooks||{}};r.transformRequest&&(R=await r.transformRequest(R)),await r.before?.(R);let N=a.retries??o,K=typeof a.retryDelay<"u"?a.retryDelay:g,X=a.shouldRetry??D,B=a.timeout??u,d=a.signal,S=R.signal,P={request:R,init:a,state:Object.create(null),metadata:{startedAt:Date.now(),timeoutMs:B,signals:{user:d??void 0,transformed:S},retry:{configuredRetries:N,configuredDelay:K,attempt:0}}};for(let t of l)await t.preRequest?.(P);let U=typeof a.throwOnHttpError<"u"?a.throwOnHttpError:f.throwOnHttpError??!1;function Y(t){if(typeof AbortSignal?.timeout=="function")return AbortSignal.timeout(t);let s=new AbortController,n=setTimeout(()=>s.abort(),t);return s.signal.addEventListener("abort",()=>clearTimeout(n),{once:!0}),s.signal}let x,k,I;B>0&&(x=Y(B),P.metadata.signals.timeout=x);let q=[];if(d&&q.push(d),S&&S!==d&&q.push(S),x&&q.push(x),q.length===1)k=q[0],I=new AbortController;else{if(typeof AbortSignal.any!="function")throw new Error("AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it.");k=AbortSignal.any(q),I=new AbortController}P.metadata.signals.combined=k;let Z=async(t,s)=>{let n=t.request,H=0,ee=e=>{H=e.attempt,t.metadata.retry.attempt=H,t.metadata.retry.lastError=e.error,t.metadata.retry.lastResponse=e.response;let y=X(e);return t.metadata.retry.shouldRetryResult=y,y&&H<=N&&r.onRetry?.(n,H-1,e.error,e.response),y},L;try{let e=await Q(async()=>{if(d?.aborted)throw r.onAbort?.(n),new b("Request was aborted by user");if(x?.aborted)throw r.onTimeout?.(n),new E("signal timed out");if(typeof s?.throwIfAborted=="function")s.throwIfAborted();else if(s?.aborted)throw d?.aborted?(r.onAbort?.(n),new b("Request was aborted by user")):x?.aborted?(r.onTimeout?.(n),new E("signal timed out")):new b("Request was aborted",new DOMException("Aborted","AbortError"));let y=new Request(n,{signal:s});try{let F=await(a.fetchHandler??T??fetch)(y);return L=F,t.metadata.retry.lastResponse=F,F}catch(i){throw t.metadata.retry.lastError=i,i instanceof DOMException&&i.name==="AbortError"?x?.aborted&&(!d||!d.aborted)?(r.onTimeout?.(n),new E("signal timed out",i)):d?.aborted?(r.onAbort?.(n),new b("Request was aborted by user")):new b("Request was aborted",new DOMException("Aborted","AbortError")):i instanceof TypeError&&/NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(i.message)?new v(i.message,i):i}},N,K,ee,n,s);if(r.transformResponse&&(e=await r.transformResponse(e,n)),await r.after?.(n,e),await r.onComplete?.(n,e,void 0),U&&(e.status>=400&&e.status<500&&e.status!==429||e.status>=500||e.status===429)){let{HttpError:y}=await import("./error-HT5UPPWM.min.js");throw new y(`HTTP error: ${e.status} ${e.statusText}`,e)}return e}catch(e){if(t.metadata.retry.lastError=e,L){let i=L;if(U&&(i.status>=400&&i.status<500&&i.status!==429||i.status>=500||i.status===429)){let{HttpError:F}=await import("./error-HT5UPPWM.min.js");throw new F(`HTTP error: ${i.status} ${i.statusText}`,i)}return i}if(e instanceof E)throw await r.onTimeout?.(n),await r.onError?.(n,e),await r.onComplete?.(n,void 0,e),e;if(e instanceof b)throw await r.onAbort?.(n),await r.onError?.(n,e),await r.onComplete?.(n,void 0,e),e;if(e instanceof v)throw await r.onError?.(n,e),await r.onComplete?.(n,void 0,e),e;let y=new W(typeof e=="object"&&e&&"message"in e&&typeof e.message=="string"?e.message:"Retry limit reached",e);throw await r.onError?.(n,y),await r.onComplete?.(n,void 0,y),y}},M=async t=>{let s=t===P?k:t.request.signal;return Z(t,s)};for(let t=l.length-1;t>=0;t--){let s=l[t];s.wrapDispatch&&(M=s.wrapDispatch(M))}let _=M(P).then(async t=>{for(let s of l)await s.onSuccess?.(P,t);return t}).catch(async t=>{for(let s of l)await s.onError?.(P,t);throw t}),z={promise:_,request:R,controller:I};return p.push(z),_.finally(async()=>{for(let s of l)await s.onFinally?.(P);let t=p.indexOf(z);t>-1&&p.splice(t,1)})})();for(let R of l)R.decoratePromise&&(m=R.decoratePromise(m));return m};return Object.defineProperty(O,"pendingRequests",{get(){return p},enumerable:!1,configurable:!1}),Object.defineProperty(O,"abortAll",{value:j,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperties(O,w),O}export{b as AbortError,te as BulkheadFullError,$ as CircuitOpenError,re as HttpError,v as NetworkError,W as RetryLimitError,E as TimeoutError,ne as createClient};
|
|
2
2
|
//# sourceMappingURL=index.min.js.map
|
package/dist/index.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/retry.ts","../src/should-retry.ts","../src/client.ts"],"sourcesContent":["import type { RetryContext } from './types.js'\n\nexport type RetryDelay = number | ((ctx: RetryContext) => number)\n\nexport const defaultDelay: RetryDelay = (ctx) => {\n const retryAfter = ctx.response?.headers.get('Retry-After')\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10)\n if (!isNaN(seconds)) return seconds * 1000\n const date = Date.parse(retryAfter)\n if (!isNaN(date)) return Math.max(0, date - Date.now())\n }\n return 2 ** ctx.attempt * 200 + Math.random() * 100\n}\n\nfunction waitForRetryDelay(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise((resolve) => {\n if (!signal) {\n setTimeout(resolve, ms)\n return\n }\n\n if (signal.aborted) {\n resolve()\n return\n }\n\n const onAbort = () => {\n clearTimeout(timer)\n resolve()\n }\n\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport async function retry(\n fn: () => Promise<Response>,\n retries: number,\n delay: RetryDelay,\n shouldRetry: (ctx: RetryContext) => boolean = () => true,\n request: Request,\n signal?: AbortSignal\n): Promise<Response> {\n let lastErr: unknown\n let lastRes: Response | undefined\n\n for (let i = 0; i <= retries; i++) {\n const ctx: RetryContext = {\n attempt: i + 1,\n request,\n response: lastRes,\n error: lastErr,\n }\n try {\n lastRes = await fn()\n ctx.response = lastRes\n ctx.error = undefined\n if (i < retries && shouldRetry(ctx)) {\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n continue\n }\n return lastRes\n } catch (err) {\n lastErr = err\n ctx.error = err\n if (i === retries || !shouldRetry(ctx)) throw err\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n }\n }\n throw lastErr\n}\n","import { AbortError, CircuitOpenError, TimeoutError } from './error.js'\nimport type { RetryContext } from './types.js'\n\nexport function shouldRetry(ctx: RetryContext): boolean {\n const { error, response } = ctx\n if (\n error instanceof AbortError ||\n error instanceof CircuitOpenError ||\n error instanceof TimeoutError\n )\n return false\n if (!response) return true // network error\n return response.status >= 500 || response.status === 429\n}\n","import type {\r\n FFetchOptions,\r\n FFetch,\r\n FFetchRequestInit,\r\n PendingRequest,\r\n} from './types.js'\r\nimport { retry, defaultDelay } from './retry.js'\r\nimport { shouldRetry as defaultShouldRetry } from './should-retry.js'\r\nimport {\r\n type PluginDispatch,\r\n type PluginRequestContext,\r\n type PluginExtensions,\r\n type PluginRequestPromiseExtensions,\r\n type ClientPlugin,\r\n type PluginExtensionBase,\r\n type PluginRequestPromiseExtensionBase,\r\n} from './plugins.js'\r\nimport {\r\n TimeoutError,\r\n AbortError,\r\n RetryLimitError,\r\n NetworkError,\r\n} from './error.js'\r\n\r\nexport function createClient<\r\n TPlugins extends readonly ClientPlugin<\r\n PluginExtensionBase,\r\n PluginRequestPromiseExtensionBase\r\n >[] = readonly ClientPlugin<\r\n PluginExtensionBase,\r\n PluginRequestPromiseExtensionBase\r\n >[],\r\n>(\r\n opts: FFetchOptions<TPlugins> = {} as FFetchOptions<TPlugins>\r\n): FFetch<\r\n PluginExtensions<TPlugins>,\r\n PluginRequestPromiseExtensions<TPlugins>\r\n> {\r\n const {\r\n timeout: clientDefaultTimeout = 5_000,\r\n retries: clientDefaultRetries = 0,\r\n retryDelay: clientDefaultRetryDelay = defaultDelay,\r\n shouldRetry: clientDefaultShouldRetry = defaultShouldRetry,\r\n hooks: clientDefaultHooks = {},\r\n fetchHandler,\r\n plugins: inputPlugins = [] as unknown as TPlugins,\r\n } = opts\r\n\r\n const extensionDescriptors: PropertyDescriptorMap = Object.create(null)\r\n\r\n const plugins = inputPlugins\r\n .map((plugin, index) => ({ plugin, index }))\r\n .sort((a, b) => {\r\n const aOrder = a.plugin.order ?? 0\r\n const bOrder = b.plugin.order ?? 0\r\n if (aOrder !== bOrder) return aOrder - bOrder\r\n return a.index - b.index\r\n })\r\n .map((entry) => entry.plugin)\r\n\r\n for (const plugin of plugins) {\r\n plugin.setup?.({\r\n defineExtension: (key, descriptor) => {\r\n const propertyKey = key as PropertyKey\r\n if (propertyKey in extensionDescriptors) {\r\n throw new Error(\r\n `Plugin extension collision for property \"${String(propertyKey)}\"`\r\n )\r\n }\r\n if ('get' in descriptor) {\r\n extensionDescriptors[propertyKey] = {\r\n get: descriptor.get,\r\n enumerable: descriptor.enumerable ?? true,\r\n configurable: false,\r\n }\r\n return\r\n }\r\n extensionDescriptors[propertyKey] = {\r\n value: descriptor.value,\r\n writable: false,\r\n enumerable: descriptor.enumerable ?? true,\r\n configurable: false,\r\n }\r\n },\r\n })\r\n }\r\n\r\n const pendingRequests: PendingRequest[] = []\r\n\r\n // Helper to abort all pending requests\r\n function abortAll() {\r\n for (const entry of pendingRequests) {\r\n entry.controller?.abort()\r\n }\r\n }\r\n\r\n const client = (input: RequestInfo | URL, init: FFetchRequestInit = {}) => {\r\n const execute = async () => {\r\n let request = new Request(input, init)\r\n\r\n // Merge hooks: per-request hooks override client hooks, but fallback to client hooks\r\n const effectiveHooks = { ...clientDefaultHooks, ...(init.hooks || {}) }\r\n if (effectiveHooks.transformRequest) {\r\n request = await effectiveHooks.transformRequest(request)\r\n }\r\n await effectiveHooks.before?.(request)\r\n\r\n // Determine retry config (per-request overrides client default)\r\n const effectiveRetries = init.retries ?? clientDefaultRetries\r\n const effectiveRetryDelay =\r\n typeof init.retryDelay !== 'undefined'\r\n ? init.retryDelay\r\n : clientDefaultRetryDelay\r\n const effectiveShouldRetry = init.shouldRetry ?? clientDefaultShouldRetry\r\n\r\n // AbortSignal.timeout/any logic\r\n const effectiveTimeout = init.timeout ?? clientDefaultTimeout\r\n const userSignal = init.signal\r\n const transformedSignal = request.signal\r\n\r\n const pluginContext: PluginRequestContext = {\r\n request,\r\n init,\r\n state: Object.create(null),\r\n metadata: {\r\n startedAt: Date.now(),\r\n timeoutMs: effectiveTimeout,\r\n signals: {\r\n user:\r\n userSignal === undefined || userSignal === null\r\n ? undefined\r\n : userSignal,\r\n transformed: transformedSignal,\r\n },\r\n retry: {\r\n configuredRetries: effectiveRetries,\r\n configuredDelay: effectiveRetryDelay,\r\n attempt: 0,\r\n },\r\n },\r\n }\r\n\r\n for (const plugin of plugins) {\r\n await plugin.preRequest?.(pluginContext)\r\n }\r\n\r\n // Determine throwOnHttpError (per-request overrides client default)\r\n const effectiveThrowOnHttpError =\r\n typeof init.throwOnHttpError !== 'undefined'\r\n ? init.throwOnHttpError\r\n : (opts.throwOnHttpError ?? false)\r\n\r\n // Create timeout signal (manual implementation if AbortSignal.timeout not available)\r\n function createTimeoutSignal(timeout: number): AbortSignal {\r\n if (typeof AbortSignal?.timeout === 'function') {\r\n return AbortSignal.timeout(timeout)\r\n }\r\n const controller = new AbortController()\r\n const timeoutId = setTimeout(() => controller.abort(), timeout)\r\n controller.signal.addEventListener(\r\n 'abort',\r\n () => clearTimeout(timeoutId),\r\n { once: true }\r\n )\r\n return controller.signal\r\n }\r\n\r\n let timeoutSignal: AbortSignal | undefined = undefined\r\n let combinedSignal: AbortSignal | undefined = undefined\r\n let controller: AbortController | undefined = undefined\r\n\r\n if (effectiveTimeout > 0) {\r\n timeoutSignal = createTimeoutSignal(effectiveTimeout)\r\n pluginContext.metadata.signals.timeout = timeoutSignal\r\n }\r\n\r\n const signals: AbortSignal[] = []\r\n if (userSignal) signals.push(userSignal)\r\n if (transformedSignal && transformedSignal !== userSignal) {\r\n signals.push(transformedSignal)\r\n }\r\n if (timeoutSignal) signals.push(timeoutSignal)\r\n\r\n if (signals.length === 1) {\r\n combinedSignal = signals[0]\r\n controller = new AbortController()\r\n } else {\r\n if (typeof AbortSignal.any !== 'function') {\r\n throw new Error(\r\n 'AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it.'\r\n )\r\n }\r\n combinedSignal = AbortSignal.any(signals)\r\n controller = new AbortController()\r\n }\r\n pluginContext.metadata.signals.combined = combinedSignal\r\n\r\n const retryWithHooks = async () => {\r\n let attempt = 0\r\n const shouldRetryWithHook = (ctx: import('./types').RetryContext) => {\r\n attempt = ctx.attempt\r\n pluginContext.metadata.retry.attempt = attempt\r\n pluginContext.metadata.retry.lastError = ctx.error\r\n pluginContext.metadata.retry.lastResponse = ctx.response\r\n const retrying = effectiveShouldRetry(ctx)\r\n pluginContext.metadata.retry.shouldRetryResult = retrying\r\n if (retrying && attempt <= effectiveRetries) {\r\n effectiveHooks.onRetry?.(\r\n request,\r\n attempt - 1,\r\n ctx.error,\r\n ctx.response\r\n )\r\n }\r\n return retrying\r\n }\r\n\r\n let lastResponse: Response | undefined = undefined\r\n try {\r\n let res = await retry(\r\n async () => {\r\n if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n }\r\n if (timeoutSignal?.aborted) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out')\r\n }\r\n if (typeof combinedSignal?.throwIfAborted === 'function') {\r\n combinedSignal.throwIfAborted()\r\n } else if (combinedSignal?.aborted) {\r\n if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n } else if (timeoutSignal?.aborted) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out')\r\n } else {\r\n throw new AbortError(\r\n 'Request was aborted',\r\n new DOMException('Aborted', 'AbortError')\r\n )\r\n }\r\n }\r\n const reqWithSignal = new Request(request, {\r\n signal: combinedSignal,\r\n })\r\n try {\r\n const handler = init.fetchHandler ?? fetchHandler ?? fetch\r\n const response = await handler(reqWithSignal)\r\n lastResponse = response\r\n pluginContext.metadata.retry.lastResponse = response\r\n return response\r\n } catch (err) {\r\n pluginContext.metadata.retry.lastError = err\r\n if (err instanceof DOMException && err.name === 'AbortError') {\r\n if (\r\n timeoutSignal?.aborted &&\r\n (!userSignal || !userSignal.aborted)\r\n ) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out', err)\r\n } else if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n } else {\r\n throw new AbortError(\r\n 'Request was aborted',\r\n new DOMException('Aborted', 'AbortError')\r\n )\r\n }\r\n } else if (\r\n err instanceof TypeError &&\r\n /NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(\r\n err.message\r\n )\r\n ) {\r\n throw new NetworkError(err.message, err)\r\n }\r\n throw err\r\n }\r\n },\r\n effectiveRetries,\r\n effectiveRetryDelay,\r\n shouldRetryWithHook,\r\n request,\r\n combinedSignal\r\n )\r\n if (effectiveHooks.transformResponse) {\r\n res = await effectiveHooks.transformResponse(res, request)\r\n }\r\n await effectiveHooks.after?.(request, res)\r\n await effectiveHooks.onComplete?.(request, res, undefined)\r\n if (\r\n effectiveThrowOnHttpError &&\r\n ((res.status >= 400 && res.status < 500 && res.status !== 429) ||\r\n res.status >= 500 ||\r\n res.status === 429)\r\n ) {\r\n const { HttpError } = await import('./error.js')\r\n throw new HttpError(\r\n `HTTP error: ${res.status} ${res.statusText}`,\r\n res\r\n )\r\n }\r\n return res\r\n } catch (err: unknown) {\r\n pluginContext.metadata.retry.lastError = err\r\n if (lastResponse) {\r\n const resp = lastResponse as Response\r\n if (\r\n effectiveThrowOnHttpError &&\r\n ((resp.status >= 400 &&\r\n resp.status < 500 &&\r\n resp.status !== 429) ||\r\n resp.status >= 500 ||\r\n resp.status === 429)\r\n ) {\r\n const { HttpError } = await import('./error.js')\r\n throw new HttpError(\r\n `HTTP error: ${resp.status} ${resp.statusText}`,\r\n resp\r\n )\r\n }\r\n return resp\r\n }\r\n if (err instanceof TimeoutError) {\r\n await effectiveHooks.onTimeout?.(request)\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n if (err instanceof AbortError) {\r\n await effectiveHooks.onAbort?.(request)\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n if (err instanceof NetworkError) {\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n const retryErr = new RetryLimitError(\r\n typeof err === 'object' &&\r\n err &&\r\n 'message' in err &&\r\n typeof (err as { message?: unknown }).message === 'string'\r\n ? (err as { message: string }).message\r\n : 'Retry limit reached',\r\n err\r\n )\r\n await effectiveHooks.onError?.(request, retryErr)\r\n await effectiveHooks.onComplete?.(request, undefined, retryErr)\r\n throw retryErr\r\n }\r\n }\r\n\r\n const baseDispatch: PluginDispatch = async () => retryWithHooks()\r\n\r\n let dispatch = baseDispatch\r\n for (let i = plugins.length - 1; i >= 0; i--) {\r\n const plugin = plugins[i]\r\n if (plugin.wrapDispatch) {\r\n dispatch = plugin.wrapDispatch(dispatch)\r\n }\r\n }\r\n\r\n const actualPromise = dispatch(pluginContext)\r\n .then(async (response) => {\r\n for (const plugin of plugins) {\r\n await plugin.onSuccess?.(pluginContext, response)\r\n }\r\n return response\r\n })\r\n .catch(async (err: unknown) => {\r\n for (const plugin of plugins) {\r\n await plugin.onError?.(pluginContext, err)\r\n }\r\n throw err\r\n })\r\n\r\n const pendingEntry: PendingRequest = {\r\n promise: actualPromise,\r\n request,\r\n controller,\r\n }\r\n pendingRequests.push(pendingEntry)\r\n\r\n return actualPromise.finally(async () => {\r\n for (const plugin of plugins) {\r\n await plugin.onFinally?.(pluginContext)\r\n }\r\n\r\n const index = pendingRequests.indexOf(pendingEntry)\r\n if (index > -1) {\r\n pendingRequests.splice(index, 1)\r\n }\r\n })\r\n }\r\n\r\n let promise = execute() as Promise<Response>\r\n for (const plugin of plugins) {\r\n if (plugin.decoratePromise) {\r\n promise = plugin.decoratePromise(promise)\r\n }\r\n }\r\n return promise as Promise<Response> &\r\n PluginRequestPromiseExtensions<TPlugins>\r\n }\r\n\r\n Object.defineProperty(client, 'pendingRequests', {\r\n get() {\r\n return pendingRequests\r\n },\r\n enumerable: false,\r\n configurable: false,\r\n })\r\n\r\n Object.defineProperty(client, 'abortAll', {\r\n value: abortAll,\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n })\r\n\r\n Object.defineProperties(client, extensionDescriptors)\r\n\r\n return client as FFetch<\r\n PluginExtensions<TPlugins>,\r\n PluginRequestPromiseExtensions<TPlugins>\r\n >\r\n}\r\n"],"mappings":"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","names":["defaultDelay","ctx","retryAfter","seconds","date","waitForRetryDelay","ms","signal","resolve","onAbort","timer","retry","fn","retries","delay","shouldRetry","request","lastErr","lastRes","i","wait","err","shouldRetry","ctx","error","response","AbortError","CircuitOpenError","TimeoutError","createClient","opts","clientDefaultTimeout","clientDefaultRetries","clientDefaultRetryDelay","defaultDelay","clientDefaultShouldRetry","shouldRetry","clientDefaultHooks","fetchHandler","inputPlugins","extensionDescriptors","plugins","plugin","index","a","b","aOrder","bOrder","entry","key","descriptor","propertyKey","pendingRequests","abortAll","client","input","init","promise","request","effectiveHooks","effectiveRetries","effectiveRetryDelay","effectiveShouldRetry","effectiveTimeout","userSignal","transformedSignal","pluginContext","effectiveThrowOnHttpError","createTimeoutSignal","timeout","controller","timeoutId","timeoutSignal","combinedSignal","signals","retryWithHooks","attempt","shouldRetryWithHook","ctx","retrying","lastResponse","res","retry","AbortError","TimeoutError","reqWithSignal","response","err","NetworkError","HttpError","resp","retryErr","RetryLimitError","dispatch","i","actualPromise","pendingEntry"]}
|
|
1
|
+
{"version":3,"sources":["../src/retry.ts","../src/should-retry.ts","../src/client.ts"],"sourcesContent":["import type { RetryContext } from './types.js'\n\nexport type RetryDelay = number | ((ctx: RetryContext) => number)\n\nexport const defaultDelay: RetryDelay = (ctx) => {\n const retryAfter = ctx.response?.headers.get('Retry-After')\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10)\n if (!isNaN(seconds)) return seconds * 1000\n const date = Date.parse(retryAfter)\n if (!isNaN(date)) return Math.max(0, date - Date.now())\n }\n return 2 ** ctx.attempt * 200 + Math.random() * 100\n}\n\nfunction waitForRetryDelay(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise((resolve) => {\n if (!signal) {\n setTimeout(resolve, ms)\n return\n }\n\n if (signal.aborted) {\n resolve()\n return\n }\n\n const onAbort = () => {\n clearTimeout(timer)\n resolve()\n }\n\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport async function retry(\n fn: () => Promise<Response>,\n retries: number,\n delay: RetryDelay,\n shouldRetry: (ctx: RetryContext) => boolean = () => true,\n request: Request,\n signal?: AbortSignal\n): Promise<Response> {\n let lastErr: unknown\n let lastRes: Response | undefined\n\n for (let i = 0; i <= retries; i++) {\n const ctx: RetryContext = {\n attempt: i + 1,\n request,\n response: lastRes,\n error: lastErr,\n }\n try {\n lastRes = await fn()\n ctx.response = lastRes\n ctx.error = undefined\n if (i < retries && shouldRetry(ctx)) {\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n continue\n }\n return lastRes\n } catch (err) {\n lastErr = err\n ctx.error = err\n if (i === retries || !shouldRetry(ctx)) throw err\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n }\n }\n throw lastErr\n}\n","import { AbortError, CircuitOpenError, TimeoutError } from './error.js'\nimport type { RetryContext } from './types.js'\n\nexport function shouldRetry(ctx: RetryContext): boolean {\n const { error, response } = ctx\n if (\n error instanceof AbortError ||\n error instanceof CircuitOpenError ||\n error instanceof TimeoutError\n )\n return false\n if (!response) return true // network error\n return response.status >= 500 || response.status === 429\n}\n","import type {\n FFetchOptions,\n FFetch,\n FFetchRequestInit,\n PendingRequest,\n} from './types.js'\nimport { retry, defaultDelay } from './retry.js'\nimport { shouldRetry as defaultShouldRetry } from './should-retry.js'\nimport {\n type PluginDispatch,\n type PluginRequestContext,\n type PluginExtensions,\n type PluginRequestPromiseExtensions,\n type ClientPlugin,\n type PluginExtensionBase,\n type PluginRequestPromiseExtensionBase,\n} from './plugins.js'\nimport {\n TimeoutError,\n AbortError,\n RetryLimitError,\n NetworkError,\n} from './error.js'\n\nexport function createClient<\n TPlugins extends readonly ClientPlugin<\n PluginExtensionBase,\n PluginRequestPromiseExtensionBase\n >[] = readonly ClientPlugin<\n PluginExtensionBase,\n PluginRequestPromiseExtensionBase\n >[],\n>(\n opts: FFetchOptions<TPlugins> = {} as FFetchOptions<TPlugins>\n): FFetch<\n PluginExtensions<TPlugins>,\n PluginRequestPromiseExtensions<TPlugins>\n> {\n const {\n timeout: clientDefaultTimeout = 5_000,\n retries: clientDefaultRetries = 0,\n retryDelay: clientDefaultRetryDelay = defaultDelay,\n shouldRetry: clientDefaultShouldRetry = defaultShouldRetry,\n hooks: clientDefaultHooks = {},\n fetchHandler,\n plugins: inputPlugins = [] as unknown as TPlugins,\n } = opts\n\n const extensionDescriptors: PropertyDescriptorMap = Object.create(null)\n\n const plugins = inputPlugins\n .map((plugin, index) => ({ plugin, index }))\n .sort((a, b) => {\n const aOrder = a.plugin.order ?? 0\n const bOrder = b.plugin.order ?? 0\n if (aOrder !== bOrder) return aOrder - bOrder\n return a.index - b.index\n })\n .map((entry) => entry.plugin)\n\n for (const plugin of plugins) {\n plugin.setup?.({\n defineExtension: (key, descriptor) => {\n const propertyKey = key as PropertyKey\n if (propertyKey in extensionDescriptors) {\n throw new Error(\n `Plugin extension collision for property \"${String(propertyKey)}\"`\n )\n }\n if ('get' in descriptor) {\n extensionDescriptors[propertyKey] = {\n get: descriptor.get,\n enumerable: descriptor.enumerable ?? true,\n configurable: false,\n }\n return\n }\n extensionDescriptors[propertyKey] = {\n value: descriptor.value,\n writable: false,\n enumerable: descriptor.enumerable ?? true,\n configurable: false,\n }\n },\n })\n }\n\n const pendingRequests: PendingRequest[] = []\n\n // Helper to abort all pending requests\n function abortAll() {\n for (const entry of pendingRequests) {\n entry.controller?.abort()\n }\n }\n\n const client = (input: RequestInfo | URL, init: FFetchRequestInit = {}) => {\n const execute = async () => {\n let request = new Request(input, init)\n\n // Merge hooks: per-request hooks override client hooks, but fallback to client hooks\n const effectiveHooks = { ...clientDefaultHooks, ...(init.hooks || {}) }\n if (effectiveHooks.transformRequest) {\n request = await effectiveHooks.transformRequest(request)\n }\n await effectiveHooks.before?.(request)\n\n // Determine retry config (per-request overrides client default)\n const effectiveRetries = init.retries ?? clientDefaultRetries\n const effectiveRetryDelay =\n typeof init.retryDelay !== 'undefined'\n ? init.retryDelay\n : clientDefaultRetryDelay\n const effectiveShouldRetry = init.shouldRetry ?? clientDefaultShouldRetry\n\n // AbortSignal.timeout/any logic\n const effectiveTimeout = init.timeout ?? clientDefaultTimeout\n const userSignal = init.signal\n const transformedSignal = request.signal\n\n const pluginContext: PluginRequestContext = {\n request,\n init,\n state: Object.create(null),\n metadata: {\n startedAt: Date.now(),\n timeoutMs: effectiveTimeout,\n signals: {\n user:\n userSignal === undefined || userSignal === null\n ? undefined\n : userSignal,\n transformed: transformedSignal,\n },\n retry: {\n configuredRetries: effectiveRetries,\n configuredDelay: effectiveRetryDelay,\n attempt: 0,\n },\n },\n }\n\n for (const plugin of plugins) {\n await plugin.preRequest?.(pluginContext)\n }\n\n // Determine throwOnHttpError (per-request overrides client default)\n const effectiveThrowOnHttpError =\n typeof init.throwOnHttpError !== 'undefined'\n ? init.throwOnHttpError\n : (opts.throwOnHttpError ?? false)\n\n // Create timeout signal (manual implementation if AbortSignal.timeout not available)\n function createTimeoutSignal(timeout: number): AbortSignal {\n if (typeof AbortSignal?.timeout === 'function') {\n return AbortSignal.timeout(timeout)\n }\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n controller.signal.addEventListener(\n 'abort',\n () => clearTimeout(timeoutId),\n { once: true }\n )\n return controller.signal\n }\n\n let timeoutSignal: AbortSignal | undefined = undefined\n let combinedSignal: AbortSignal | undefined = undefined\n let controller: AbortController | undefined = undefined\n\n if (effectiveTimeout > 0) {\n timeoutSignal = createTimeoutSignal(effectiveTimeout)\n pluginContext.metadata.signals.timeout = timeoutSignal\n }\n\n const signals: AbortSignal[] = []\n if (userSignal) signals.push(userSignal)\n if (transformedSignal && transformedSignal !== userSignal) {\n signals.push(transformedSignal)\n }\n if (timeoutSignal) signals.push(timeoutSignal)\n\n if (signals.length === 1) {\n combinedSignal = signals[0]\n controller = new AbortController()\n } else {\n if (typeof AbortSignal.any !== 'function') {\n throw new Error(\n 'AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it.'\n )\n }\n combinedSignal = AbortSignal.any(signals)\n controller = new AbortController()\n }\n pluginContext.metadata.signals.combined = combinedSignal\n\n const retryWithHooks = async (\n dispatchCtx: PluginRequestContext,\n dispatchSignal: AbortSignal | undefined\n ) => {\n const requestForAttempt = dispatchCtx.request\n let attempt = 0\n const shouldRetryWithHook = (ctx: import('./types').RetryContext) => {\n attempt = ctx.attempt\n dispatchCtx.metadata.retry.attempt = attempt\n dispatchCtx.metadata.retry.lastError = ctx.error\n dispatchCtx.metadata.retry.lastResponse = ctx.response\n const retrying = effectiveShouldRetry(ctx)\n dispatchCtx.metadata.retry.shouldRetryResult = retrying\n if (retrying && attempt <= effectiveRetries) {\n effectiveHooks.onRetry?.(\n requestForAttempt,\n attempt - 1,\n ctx.error,\n ctx.response\n )\n }\n return retrying\n }\n\n let lastResponse: Response | undefined = undefined\n try {\n let res = await retry(\n async () => {\n if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n }\n if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out')\n }\n if (typeof dispatchSignal?.throwIfAborted === 'function') {\n dispatchSignal.throwIfAborted()\n } else if (dispatchSignal?.aborted) {\n if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n } else if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out')\n } else {\n throw new AbortError(\n 'Request was aborted',\n new DOMException('Aborted', 'AbortError')\n )\n }\n }\n const reqWithSignal = new Request(requestForAttempt, {\n signal: dispatchSignal,\n })\n try {\n const handler = init.fetchHandler ?? fetchHandler ?? fetch\n const response = await handler(reqWithSignal)\n lastResponse = response\n dispatchCtx.metadata.retry.lastResponse = response\n return response\n } catch (err) {\n dispatchCtx.metadata.retry.lastError = err\n if (err instanceof DOMException && err.name === 'AbortError') {\n if (\n timeoutSignal?.aborted &&\n (!userSignal || !userSignal.aborted)\n ) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out', err)\n } else if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n } else {\n throw new AbortError(\n 'Request was aborted',\n new DOMException('Aborted', 'AbortError')\n )\n }\n } else if (\n err instanceof TypeError &&\n /NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(\n err.message\n )\n ) {\n throw new NetworkError(err.message, err)\n }\n throw err\n }\n },\n effectiveRetries,\n effectiveRetryDelay,\n shouldRetryWithHook,\n requestForAttempt,\n dispatchSignal\n )\n if (effectiveHooks.transformResponse) {\n res = await effectiveHooks.transformResponse(res, requestForAttempt)\n }\n await effectiveHooks.after?.(requestForAttempt, res)\n await effectiveHooks.onComplete?.(requestForAttempt, res, undefined)\n if (\n effectiveThrowOnHttpError &&\n ((res.status >= 400 && res.status < 500 && res.status !== 429) ||\n res.status >= 500 ||\n res.status === 429)\n ) {\n const { HttpError } = await import('./error.js')\n throw new HttpError(\n `HTTP error: ${res.status} ${res.statusText}`,\n res\n )\n }\n return res\n } catch (err: unknown) {\n dispatchCtx.metadata.retry.lastError = err\n if (lastResponse) {\n const resp = lastResponse as Response\n if (\n effectiveThrowOnHttpError &&\n ((resp.status >= 400 &&\n resp.status < 500 &&\n resp.status !== 429) ||\n resp.status >= 500 ||\n resp.status === 429)\n ) {\n const { HttpError } = await import('./error.js')\n throw new HttpError(\n `HTTP error: ${resp.status} ${resp.statusText}`,\n resp\n )\n }\n return resp\n }\n if (err instanceof TimeoutError) {\n await effectiveHooks.onTimeout?.(requestForAttempt)\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n if (err instanceof AbortError) {\n await effectiveHooks.onAbort?.(requestForAttempt)\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n if (err instanceof NetworkError) {\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n const retryErr = new RetryLimitError(\n typeof err === 'object' &&\n err &&\n 'message' in err &&\n typeof (err as { message?: unknown }).message === 'string'\n ? (err as { message: string }).message\n : 'Retry limit reached',\n err\n )\n await effectiveHooks.onError?.(requestForAttempt, retryErr)\n await effectiveHooks.onComplete?.(\n requestForAttempt,\n undefined,\n retryErr\n )\n throw retryErr\n }\n }\n\n const baseDispatch: PluginDispatch = async (ctx) => {\n const dispatchSignal =\n ctx === pluginContext ? combinedSignal : ctx.request.signal\n return retryWithHooks(ctx, dispatchSignal)\n }\n\n let dispatch = baseDispatch\n for (let i = plugins.length - 1; i >= 0; i--) {\n const plugin = plugins[i]\n if (plugin.wrapDispatch) {\n dispatch = plugin.wrapDispatch(dispatch)\n }\n }\n\n const actualPromise = dispatch(pluginContext)\n .then(async (response) => {\n for (const plugin of plugins) {\n await plugin.onSuccess?.(pluginContext, response)\n }\n return response\n })\n .catch(async (err: unknown) => {\n for (const plugin of plugins) {\n await plugin.onError?.(pluginContext, err)\n }\n throw err\n })\n\n const pendingEntry: PendingRequest = {\n promise: actualPromise,\n request,\n controller,\n }\n pendingRequests.push(pendingEntry)\n\n return actualPromise.finally(async () => {\n for (const plugin of plugins) {\n await plugin.onFinally?.(pluginContext)\n }\n\n const index = pendingRequests.indexOf(pendingEntry)\n if (index > -1) {\n pendingRequests.splice(index, 1)\n }\n })\n }\n\n let promise = execute() as Promise<Response>\n for (const plugin of plugins) {\n if (plugin.decoratePromise) {\n promise = plugin.decoratePromise(promise)\n }\n }\n return promise as Promise<Response> &\n PluginRequestPromiseExtensions<TPlugins>\n }\n\n Object.defineProperty(client, 'pendingRequests', {\n get() {\n return pendingRequests\n },\n enumerable: false,\n configurable: false,\n })\n\n Object.defineProperty(client, 'abortAll', {\n value: abortAll,\n writable: false,\n enumerable: false,\n configurable: false,\n })\n\n Object.defineProperties(client, extensionDescriptors)\n\n return client as FFetch<\n PluginExtensions<TPlugins>,\n PluginRequestPromiseExtensions<TPlugins>\n >\n}\n"],"mappings":"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","names":["defaultDelay","ctx","retryAfter","seconds","date","waitForRetryDelay","ms","signal","resolve","onAbort","timer","retry","fn","retries","delay","shouldRetry","request","lastErr","lastRes","i","wait","err","shouldRetry","ctx","error","response","AbortError","CircuitOpenError","TimeoutError","createClient","opts","clientDefaultTimeout","clientDefaultRetries","clientDefaultRetryDelay","defaultDelay","clientDefaultShouldRetry","shouldRetry","clientDefaultHooks","fetchHandler","inputPlugins","extensionDescriptors","plugins","plugin","index","a","b","aOrder","bOrder","entry","key","descriptor","propertyKey","pendingRequests","abortAll","client","input","init","promise","request","effectiveHooks","effectiveRetries","effectiveRetryDelay","effectiveShouldRetry","effectiveTimeout","userSignal","transformedSignal","pluginContext","effectiveThrowOnHttpError","createTimeoutSignal","timeout","controller","timeoutId","timeoutSignal","combinedSignal","signals","retryWithHooks","dispatchCtx","dispatchSignal","requestForAttempt","attempt","shouldRetryWithHook","ctx","retrying","lastResponse","res","retry","AbortError","TimeoutError","reqWithSignal","response","err","NetworkError","HttpError","resp","retryErr","RetryLimitError","dispatch","i","actualPromise","pendingEntry"]}
|