@fetchkit/ffetch 5.5.4 → 5.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +69 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -45
- 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 +25 -13
- package/dist/plugins/bulkhead.cjs.map +1 -1
- package/dist/plugins/bulkhead.js +22 -14
- package/dist/plugins/bulkhead.js.map +1 -1
- package/dist/plugins/dedupe.cjs +53 -4
- package/dist/plugins/dedupe.cjs.map +1 -1
- package/dist/plugins/dedupe.js +39 -4
- package/dist/plugins/dedupe.js.map +1 -1
- package/dist/plugins/download-progress.cjs +3 -2
- package/dist/plugins/download-progress.cjs.map +1 -1
- package/dist/plugins/download-progress.js +3 -2
- package/dist/plugins/download-progress.js.map +1 -1
- package/dist/plugins/hedge.cjs +22 -22
- package/dist/plugins/hedge.cjs.map +1 -1
- package/dist/plugins/hedge.js +22 -22
- package/dist/plugins/hedge.js.map +1 -1
- package/package.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -3,8 +3,13 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __esm = (fn, res) => function __init() {
|
|
7
|
-
|
|
6
|
+
var __esm = (fn, res, err) => function __init() {
|
|
7
|
+
if (err) throw err[0];
|
|
8
|
+
try {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
throw err = [e], e;
|
|
12
|
+
}
|
|
8
13
|
};
|
|
9
14
|
var __export = (target, all) => {
|
|
10
15
|
for (var name in all)
|
|
@@ -139,21 +144,22 @@ async function retry(fn, retries, delay, shouldRetry2 = () => true, request, sig
|
|
|
139
144
|
};
|
|
140
145
|
try {
|
|
141
146
|
lastRes = await fn();
|
|
142
|
-
ctx.response = lastRes;
|
|
143
|
-
ctx.error = void 0;
|
|
144
|
-
if (i < retries && shouldRetry2(ctx)) {
|
|
145
|
-
const wait = typeof delay === "function" ? delay(ctx) : delay;
|
|
146
|
-
await waitForRetryDelay(wait, signal);
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
return lastRes;
|
|
150
147
|
} catch (err) {
|
|
151
148
|
lastErr = err;
|
|
152
149
|
ctx.error = err;
|
|
153
|
-
if (i === retries || !shouldRetry2(ctx)) throw err;
|
|
150
|
+
if (i === retries || !await shouldRetry2(ctx)) throw err;
|
|
151
|
+
const wait = typeof delay === "function" ? delay(ctx) : delay;
|
|
152
|
+
await waitForRetryDelay(wait, signal);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
ctx.response = lastRes;
|
|
156
|
+
ctx.error = void 0;
|
|
157
|
+
if (i < retries && await shouldRetry2(ctx)) {
|
|
154
158
|
const wait = typeof delay === "function" ? delay(ctx) : delay;
|
|
155
159
|
await waitForRetryDelay(wait, signal);
|
|
160
|
+
continue;
|
|
156
161
|
}
|
|
162
|
+
return lastRes;
|
|
157
163
|
}
|
|
158
164
|
throw lastErr;
|
|
159
165
|
}
|
|
@@ -270,7 +276,7 @@ function createClient(opts = {}) {
|
|
|
270
276
|
}
|
|
271
277
|
let timeoutSignal = void 0;
|
|
272
278
|
let combinedSignal = void 0;
|
|
273
|
-
|
|
279
|
+
const controller = new AbortController();
|
|
274
280
|
if (effectiveTimeout > 0) {
|
|
275
281
|
timeoutSignal = createTimeoutSignal(effectiveTimeout);
|
|
276
282
|
pluginContext.metadata.signals.timeout = timeoutSignal;
|
|
@@ -281,9 +287,9 @@ function createClient(opts = {}) {
|
|
|
281
287
|
signals.push(transformedSignal);
|
|
282
288
|
}
|
|
283
289
|
if (timeoutSignal) signals.push(timeoutSignal);
|
|
290
|
+
signals.push(controller.signal);
|
|
284
291
|
if (signals.length === 1) {
|
|
285
292
|
combinedSignal = signals[0];
|
|
286
|
-
controller = new AbortController();
|
|
287
293
|
} else {
|
|
288
294
|
if (typeof AbortSignal.any !== "function") {
|
|
289
295
|
throw new Error(
|
|
@@ -291,13 +297,26 @@ function createClient(opts = {}) {
|
|
|
291
297
|
);
|
|
292
298
|
}
|
|
293
299
|
combinedSignal = AbortSignal.any(signals);
|
|
294
|
-
controller = new AbortController();
|
|
295
300
|
}
|
|
296
301
|
pluginContext.metadata.signals.combined = combinedSignal;
|
|
302
|
+
let coreErrorReported = false;
|
|
303
|
+
const reportCoreError = async (error, hookRequest) => {
|
|
304
|
+
if (coreErrorReported) return;
|
|
305
|
+
if (!(error instanceof TimeoutError) && !(error instanceof AbortError) && !(error instanceof NetworkError) && !(error instanceof RetryLimitError)) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
coreErrorReported = true;
|
|
309
|
+
if (error instanceof TimeoutError) {
|
|
310
|
+
await effectiveHooks.onTimeout?.(hookRequest);
|
|
311
|
+
} else if (error instanceof AbortError) {
|
|
312
|
+
await effectiveHooks.onAbort?.(hookRequest);
|
|
313
|
+
}
|
|
314
|
+
await effectiveHooks.onError?.(hookRequest, error);
|
|
315
|
+
};
|
|
297
316
|
const retryWithHooks = async (dispatchCtx, dispatchSignal) => {
|
|
298
317
|
const requestForAttempt = dispatchCtx.request;
|
|
299
318
|
let attempt = 0;
|
|
300
|
-
const shouldRetryWithHook = (ctx) => {
|
|
319
|
+
const shouldRetryWithHook = async (ctx) => {
|
|
301
320
|
attempt = ctx.attempt;
|
|
302
321
|
dispatchCtx.metadata.retry.attempt = attempt;
|
|
303
322
|
dispatchCtx.metadata.retry.lastError = ctx.error;
|
|
@@ -305,7 +324,7 @@ function createClient(opts = {}) {
|
|
|
305
324
|
const retrying = effectiveShouldRetry(ctx);
|
|
306
325
|
dispatchCtx.metadata.retry.shouldRetryResult = retrying;
|
|
307
326
|
if (retrying && attempt <= effectiveRetries) {
|
|
308
|
-
effectiveHooks.onRetry?.(
|
|
327
|
+
await effectiveHooks.onRetry?.(
|
|
309
328
|
requestForAttempt,
|
|
310
329
|
attempt - 1,
|
|
311
330
|
ctx.error,
|
|
@@ -318,27 +337,24 @@ function createClient(opts = {}) {
|
|
|
318
337
|
try {
|
|
319
338
|
let res = await retry(
|
|
320
339
|
async () => {
|
|
340
|
+
if (controller.signal.aborted) {
|
|
341
|
+
throw new AbortError("Request was aborted");
|
|
342
|
+
}
|
|
321
343
|
if (userSignal?.aborted) {
|
|
322
|
-
effectiveHooks.onAbort?.(requestForAttempt);
|
|
323
344
|
throw new AbortError("Request was aborted by user");
|
|
324
345
|
}
|
|
325
346
|
if (timeoutSignal?.aborted) {
|
|
326
|
-
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
327
347
|
throw new TimeoutError("signal timed out");
|
|
328
348
|
}
|
|
329
|
-
if (
|
|
330
|
-
dispatchSignal.throwIfAborted();
|
|
331
|
-
} else if (dispatchSignal?.aborted) {
|
|
349
|
+
if (dispatchSignal?.aborted) {
|
|
332
350
|
if (userSignal?.aborted) {
|
|
333
|
-
effectiveHooks.onAbort?.(requestForAttempt);
|
|
334
351
|
throw new AbortError("Request was aborted by user");
|
|
335
352
|
} else if (timeoutSignal?.aborted) {
|
|
336
|
-
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
337
353
|
throw new TimeoutError("signal timed out");
|
|
338
354
|
} else {
|
|
339
355
|
throw new AbortError(
|
|
340
356
|
"Request was aborted",
|
|
341
|
-
|
|
357
|
+
dispatchSignal.reason
|
|
342
358
|
);
|
|
343
359
|
}
|
|
344
360
|
}
|
|
@@ -355,11 +371,11 @@ function createClient(opts = {}) {
|
|
|
355
371
|
dispatchCtx.metadata.retry.lastError = err;
|
|
356
372
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
357
373
|
if (timeoutSignal?.aborted && (!userSignal || !userSignal.aborted)) {
|
|
358
|
-
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
359
374
|
throw new TimeoutError("signal timed out", err);
|
|
360
375
|
} else if (userSignal?.aborted) {
|
|
361
|
-
effectiveHooks.onAbort?.(requestForAttempt);
|
|
362
376
|
throw new AbortError("Request was aborted by user");
|
|
377
|
+
} else if (controller.signal.aborted) {
|
|
378
|
+
throw new AbortError("Request was aborted", err);
|
|
363
379
|
} else {
|
|
364
380
|
throw new AbortError(
|
|
365
381
|
"Request was aborted",
|
|
@@ -384,7 +400,6 @@ function createClient(opts = {}) {
|
|
|
384
400
|
res = await effectiveHooks.transformResponse(res, requestForAttempt);
|
|
385
401
|
}
|
|
386
402
|
await effectiveHooks.after?.(requestForAttempt, res);
|
|
387
|
-
await effectiveHooks.onComplete?.(requestForAttempt, res, void 0);
|
|
388
403
|
if (effectiveThrowOnHttpError && (res.status >= 400 && res.status < 500 && res.status !== 429 || res.status >= 500 || res.status === 429)) {
|
|
389
404
|
const { HttpError: HttpError2 } = await Promise.resolve().then(() => (init_error(), error_exports));
|
|
390
405
|
throw new HttpError2(
|
|
@@ -395,6 +410,18 @@ function createClient(opts = {}) {
|
|
|
395
410
|
return res;
|
|
396
411
|
} catch (err) {
|
|
397
412
|
dispatchCtx.metadata.retry.lastError = err;
|
|
413
|
+
if (err instanceof TimeoutError) {
|
|
414
|
+
if (dispatchCtx === pluginContext) {
|
|
415
|
+
await reportCoreError(err, requestForAttempt);
|
|
416
|
+
}
|
|
417
|
+
throw err;
|
|
418
|
+
}
|
|
419
|
+
if (err instanceof AbortError) {
|
|
420
|
+
if (dispatchCtx === pluginContext) {
|
|
421
|
+
await reportCoreError(err, requestForAttempt);
|
|
422
|
+
}
|
|
423
|
+
throw err;
|
|
424
|
+
}
|
|
398
425
|
if (lastResponse) {
|
|
399
426
|
const resp = lastResponse;
|
|
400
427
|
if (effectiveThrowOnHttpError && (resp.status >= 400 && resp.status < 500 && resp.status !== 429 || resp.status >= 500 || resp.status === 429)) {
|
|
@@ -406,33 +433,19 @@ function createClient(opts = {}) {
|
|
|
406
433
|
}
|
|
407
434
|
return resp;
|
|
408
435
|
}
|
|
409
|
-
if (err instanceof TimeoutError) {
|
|
410
|
-
await effectiveHooks.onTimeout?.(requestForAttempt);
|
|
411
|
-
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
412
|
-
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
413
|
-
throw err;
|
|
414
|
-
}
|
|
415
|
-
if (err instanceof AbortError) {
|
|
416
|
-
await effectiveHooks.onAbort?.(requestForAttempt);
|
|
417
|
-
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
418
|
-
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
419
|
-
throw err;
|
|
420
|
-
}
|
|
421
436
|
if (err instanceof NetworkError) {
|
|
422
|
-
|
|
423
|
-
|
|
437
|
+
if (dispatchCtx === pluginContext) {
|
|
438
|
+
await reportCoreError(err, requestForAttempt);
|
|
439
|
+
}
|
|
424
440
|
throw err;
|
|
425
441
|
}
|
|
426
442
|
const retryErr = new RetryLimitError(
|
|
427
443
|
typeof err === "object" && err && "message" in err && typeof err.message === "string" ? err.message : "Retry limit reached",
|
|
428
444
|
err
|
|
429
445
|
);
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
void 0,
|
|
434
|
-
retryErr
|
|
435
|
-
);
|
|
446
|
+
if (dispatchCtx === pluginContext) {
|
|
447
|
+
await reportCoreError(retryErr, requestForAttempt);
|
|
448
|
+
}
|
|
436
449
|
throw retryErr;
|
|
437
450
|
}
|
|
438
451
|
};
|
|
@@ -447,12 +460,21 @@ function createClient(opts = {}) {
|
|
|
447
460
|
dispatch = plugin.wrapDispatch(dispatch);
|
|
448
461
|
}
|
|
449
462
|
}
|
|
463
|
+
let completeCalled = false;
|
|
464
|
+
const callComplete = async (response, error) => {
|
|
465
|
+
if (completeCalled) return;
|
|
466
|
+
completeCalled = true;
|
|
467
|
+
await effectiveHooks.onComplete?.(request, response, error);
|
|
468
|
+
};
|
|
450
469
|
const actualPromise = dispatch(pluginContext).then(async (response) => {
|
|
470
|
+
await callComplete(response, void 0);
|
|
451
471
|
for (const plugin of plugins) {
|
|
452
472
|
await plugin.onSuccess?.(pluginContext, response);
|
|
453
473
|
}
|
|
454
474
|
return response;
|
|
455
475
|
}).catch(async (err) => {
|
|
476
|
+
await reportCoreError(err, request);
|
|
477
|
+
await callComplete(void 0, err);
|
|
456
478
|
for (const plugin of plugins) {
|
|
457
479
|
await plugin.onError?.(pluginContext, err);
|
|
458
480
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/error.ts","../src/index.ts","../src/retry.ts","../src/should-retry.ts","../src/client.ts"],"sourcesContent":["// Base error class to reduce duplication\nclass BaseError extends Error {\n public cause?: unknown\n constructor(name: string, message: string, cause?: unknown) {\n super(message)\n this.name = name\n if (cause !== undefined) this.cause = cause\n }\n}\n\nexport class TimeoutError extends BaseError {\n constructor(message = 'Request timed out', cause?: unknown) {\n super('TimeoutError', message, cause)\n }\n}\n\nexport class CircuitOpenError extends BaseError {\n constructor(message = 'Circuit is open', cause?: unknown) {\n super('CircuitOpenError', message, cause)\n }\n}\n\nexport class BulkheadFullError extends BaseError {\n constructor(message = 'Bulkhead queue is full', cause?: unknown) {\n super('BulkheadFullError', message, cause)\n }\n}\n\nexport class AbortError extends BaseError {\n constructor(message = 'Request was aborted', cause?: unknown) {\n super('AbortError', message, cause)\n }\n}\n\nexport class RetryLimitError extends BaseError {\n constructor(message = 'Retry limit reached', cause?: unknown) {\n super('RetryLimitError', message, cause)\n }\n}\n\nexport class NetworkError extends BaseError {\n constructor(message = 'Network error occurred', cause?: unknown) {\n super('NetworkError', message, cause)\n }\n}\n\nexport class HttpError extends BaseError {\n constructor(message = 'HTTP error occurred', cause?: unknown) {\n super('HttpError', message, cause)\n }\n}\n","export type { FFetch, FFetchOptions } from './types'\nexport type { Hooks } from './hooks'\nexport type {\n ClientPlugin,\n PluginRequestContext,\n PluginDispatch,\n PluginSetupContext,\n} from './plugins'\n\nexport { createClient } from './client'\n\nexport {\n TimeoutError,\n CircuitOpenError,\n BulkheadFullError,\n AbortError,\n RetryLimitError,\n NetworkError,\n HttpError,\n} from './error'\n","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\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.clone(), {\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"]}
|
|
1
|
+
{"version":3,"sources":["../src/error.ts","../src/index.ts","../src/retry.ts","../src/should-retry.ts","../src/client.ts"],"sourcesContent":["// Base error class to reduce duplication\nclass BaseError extends Error {\n public cause?: unknown\n constructor(name: string, message: string, cause?: unknown) {\n super(message)\n this.name = name\n if (cause !== undefined) this.cause = cause\n }\n}\n\nexport class TimeoutError extends BaseError {\n constructor(message = 'Request timed out', cause?: unknown) {\n super('TimeoutError', message, cause)\n }\n}\n\nexport class CircuitOpenError extends BaseError {\n constructor(message = 'Circuit is open', cause?: unknown) {\n super('CircuitOpenError', message, cause)\n }\n}\n\nexport class BulkheadFullError extends BaseError {\n constructor(message = 'Bulkhead queue is full', cause?: unknown) {\n super('BulkheadFullError', message, cause)\n }\n}\n\nexport class AbortError extends BaseError {\n constructor(message = 'Request was aborted', cause?: unknown) {\n super('AbortError', message, cause)\n }\n}\n\nexport class RetryLimitError extends BaseError {\n constructor(message = 'Retry limit reached', cause?: unknown) {\n super('RetryLimitError', message, cause)\n }\n}\n\nexport class NetworkError extends BaseError {\n constructor(message = 'Network error occurred', cause?: unknown) {\n super('NetworkError', message, cause)\n }\n}\n\nexport class HttpError extends BaseError {\n constructor(message = 'HTTP error occurred', cause?: unknown) {\n super('HttpError', message, cause)\n }\n}\n","export type { FFetch, FFetchOptions } from './types'\nexport type { Hooks } from './hooks'\nexport type {\n ClientPlugin,\n PluginRequestContext,\n PluginDispatch,\n PluginSetupContext,\n} from './plugins'\n\nexport { createClient } from './client'\n\nexport {\n TimeoutError,\n CircuitOpenError,\n BulkheadFullError,\n AbortError,\n RetryLimitError,\n NetworkError,\n HttpError,\n} from './error'\n","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 | Promise<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 } catch (err) {\n lastErr = err\n ctx.error = err\n if (i === retries || !(await shouldRetry(ctx))) throw err\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n continue\n }\n\n ctx.response = lastRes\n ctx.error = undefined\n if (i < retries && (await shouldRetry(ctx))) {\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n continue\n }\n return lastRes\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 const controller = new AbortController()\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 signals.push(controller.signal)\n\n if (signals.length === 1) {\n combinedSignal = signals[0]\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 }\n pluginContext.metadata.signals.combined = combinedSignal\n\n let coreErrorReported = false\n const reportCoreError = async (error: unknown, hookRequest: Request) => {\n if (coreErrorReported) return\n if (\n !(error instanceof TimeoutError) &&\n !(error instanceof AbortError) &&\n !(error instanceof NetworkError) &&\n !(error instanceof RetryLimitError)\n ) {\n return\n }\n\n coreErrorReported = true\n if (error instanceof TimeoutError) {\n await effectiveHooks.onTimeout?.(hookRequest)\n } else if (error instanceof AbortError) {\n await effectiveHooks.onAbort?.(hookRequest)\n }\n await effectiveHooks.onError?.(hookRequest, error)\n }\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 = async (\n ctx: import('./types').RetryContext\n ) => {\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 await 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 (controller.signal.aborted) {\n throw new AbortError('Request was aborted')\n }\n if (userSignal?.aborted) {\n throw new AbortError('Request was aborted by user')\n }\n if (timeoutSignal?.aborted) {\n throw new TimeoutError('signal timed out')\n }\n if (dispatchSignal?.aborted) {\n if (userSignal?.aborted) {\n throw new AbortError('Request was aborted by user')\n } else if (timeoutSignal?.aborted) {\n throw new TimeoutError('signal timed out')\n } else {\n throw new AbortError(\n 'Request was aborted',\n dispatchSignal.reason\n )\n }\n }\n const reqWithSignal = new Request(requestForAttempt.clone(), {\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 throw new TimeoutError('signal timed out', err)\n } else if (userSignal?.aborted) {\n throw new AbortError('Request was aborted by user')\n } else if (controller.signal.aborted) {\n throw new AbortError('Request was aborted', err)\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 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 (err instanceof TimeoutError) {\n if (dispatchCtx === pluginContext) {\n await reportCoreError(err, requestForAttempt)\n }\n throw err\n }\n if (err instanceof AbortError) {\n if (dispatchCtx === pluginContext) {\n await reportCoreError(err, requestForAttempt)\n }\n throw err\n }\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 NetworkError) {\n if (dispatchCtx === pluginContext) {\n await reportCoreError(err, requestForAttempt)\n }\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 if (dispatchCtx === pluginContext) {\n await reportCoreError(retryErr, requestForAttempt)\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 let completeCalled = false\n const callComplete = async (\n response: Response | undefined,\n error: unknown\n ) => {\n if (completeCalled) return\n completeCalled = true\n await effectiveHooks.onComplete?.(request, response, error)\n }\n\n const actualPromise = dispatch(pluginContext)\n .then(async (response) => {\n await callComplete(response, undefined)\n for (const plugin of plugins) {\n await plugin.onSuccess?.(pluginContext, response)\n }\n return response\n })\n .catch(async (err: unknown) => {\n await reportCoreError(err, request)\n await callComplete(undefined, err)\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.js
CHANGED
|
@@ -53,21 +53,22 @@ async function retry(fn, retries, delay, shouldRetry2 = () => true, request, sig
|
|
|
53
53
|
};
|
|
54
54
|
try {
|
|
55
55
|
lastRes = await fn();
|
|
56
|
-
ctx.response = lastRes;
|
|
57
|
-
ctx.error = void 0;
|
|
58
|
-
if (i < retries && shouldRetry2(ctx)) {
|
|
59
|
-
const wait = typeof delay === "function" ? delay(ctx) : delay;
|
|
60
|
-
await waitForRetryDelay(wait, signal);
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
return lastRes;
|
|
64
56
|
} catch (err) {
|
|
65
57
|
lastErr = err;
|
|
66
58
|
ctx.error = err;
|
|
67
|
-
if (i === retries || !shouldRetry2(ctx)) throw err;
|
|
59
|
+
if (i === retries || !await shouldRetry2(ctx)) throw err;
|
|
60
|
+
const wait = typeof delay === "function" ? delay(ctx) : delay;
|
|
61
|
+
await waitForRetryDelay(wait, signal);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
ctx.response = lastRes;
|
|
65
|
+
ctx.error = void 0;
|
|
66
|
+
if (i < retries && await shouldRetry2(ctx)) {
|
|
68
67
|
const wait = typeof delay === "function" ? delay(ctx) : delay;
|
|
69
68
|
await waitForRetryDelay(wait, signal);
|
|
69
|
+
continue;
|
|
70
70
|
}
|
|
71
|
+
return lastRes;
|
|
71
72
|
}
|
|
72
73
|
throw lastErr;
|
|
73
74
|
}
|
|
@@ -182,7 +183,7 @@ function createClient(opts = {}) {
|
|
|
182
183
|
}
|
|
183
184
|
let timeoutSignal = void 0;
|
|
184
185
|
let combinedSignal = void 0;
|
|
185
|
-
|
|
186
|
+
const controller = new AbortController();
|
|
186
187
|
if (effectiveTimeout > 0) {
|
|
187
188
|
timeoutSignal = createTimeoutSignal(effectiveTimeout);
|
|
188
189
|
pluginContext.metadata.signals.timeout = timeoutSignal;
|
|
@@ -193,9 +194,9 @@ function createClient(opts = {}) {
|
|
|
193
194
|
signals.push(transformedSignal);
|
|
194
195
|
}
|
|
195
196
|
if (timeoutSignal) signals.push(timeoutSignal);
|
|
197
|
+
signals.push(controller.signal);
|
|
196
198
|
if (signals.length === 1) {
|
|
197
199
|
combinedSignal = signals[0];
|
|
198
|
-
controller = new AbortController();
|
|
199
200
|
} else {
|
|
200
201
|
if (typeof AbortSignal.any !== "function") {
|
|
201
202
|
throw new Error(
|
|
@@ -203,13 +204,26 @@ function createClient(opts = {}) {
|
|
|
203
204
|
);
|
|
204
205
|
}
|
|
205
206
|
combinedSignal = AbortSignal.any(signals);
|
|
206
|
-
controller = new AbortController();
|
|
207
207
|
}
|
|
208
208
|
pluginContext.metadata.signals.combined = combinedSignal;
|
|
209
|
+
let coreErrorReported = false;
|
|
210
|
+
const reportCoreError = async (error, hookRequest) => {
|
|
211
|
+
if (coreErrorReported) return;
|
|
212
|
+
if (!(error instanceof TimeoutError) && !(error instanceof AbortError) && !(error instanceof NetworkError) && !(error instanceof RetryLimitError)) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
coreErrorReported = true;
|
|
216
|
+
if (error instanceof TimeoutError) {
|
|
217
|
+
await effectiveHooks.onTimeout?.(hookRequest);
|
|
218
|
+
} else if (error instanceof AbortError) {
|
|
219
|
+
await effectiveHooks.onAbort?.(hookRequest);
|
|
220
|
+
}
|
|
221
|
+
await effectiveHooks.onError?.(hookRequest, error);
|
|
222
|
+
};
|
|
209
223
|
const retryWithHooks = async (dispatchCtx, dispatchSignal) => {
|
|
210
224
|
const requestForAttempt = dispatchCtx.request;
|
|
211
225
|
let attempt = 0;
|
|
212
|
-
const shouldRetryWithHook = (ctx) => {
|
|
226
|
+
const shouldRetryWithHook = async (ctx) => {
|
|
213
227
|
attempt = ctx.attempt;
|
|
214
228
|
dispatchCtx.metadata.retry.attempt = attempt;
|
|
215
229
|
dispatchCtx.metadata.retry.lastError = ctx.error;
|
|
@@ -217,7 +231,7 @@ function createClient(opts = {}) {
|
|
|
217
231
|
const retrying = effectiveShouldRetry(ctx);
|
|
218
232
|
dispatchCtx.metadata.retry.shouldRetryResult = retrying;
|
|
219
233
|
if (retrying && attempt <= effectiveRetries) {
|
|
220
|
-
effectiveHooks.onRetry?.(
|
|
234
|
+
await effectiveHooks.onRetry?.(
|
|
221
235
|
requestForAttempt,
|
|
222
236
|
attempt - 1,
|
|
223
237
|
ctx.error,
|
|
@@ -230,27 +244,24 @@ function createClient(opts = {}) {
|
|
|
230
244
|
try {
|
|
231
245
|
let res = await retry(
|
|
232
246
|
async () => {
|
|
247
|
+
if (controller.signal.aborted) {
|
|
248
|
+
throw new AbortError("Request was aborted");
|
|
249
|
+
}
|
|
233
250
|
if (userSignal?.aborted) {
|
|
234
|
-
effectiveHooks.onAbort?.(requestForAttempt);
|
|
235
251
|
throw new AbortError("Request was aborted by user");
|
|
236
252
|
}
|
|
237
253
|
if (timeoutSignal?.aborted) {
|
|
238
|
-
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
239
254
|
throw new TimeoutError("signal timed out");
|
|
240
255
|
}
|
|
241
|
-
if (
|
|
242
|
-
dispatchSignal.throwIfAborted();
|
|
243
|
-
} else if (dispatchSignal?.aborted) {
|
|
256
|
+
if (dispatchSignal?.aborted) {
|
|
244
257
|
if (userSignal?.aborted) {
|
|
245
|
-
effectiveHooks.onAbort?.(requestForAttempt);
|
|
246
258
|
throw new AbortError("Request was aborted by user");
|
|
247
259
|
} else if (timeoutSignal?.aborted) {
|
|
248
|
-
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
249
260
|
throw new TimeoutError("signal timed out");
|
|
250
261
|
} else {
|
|
251
262
|
throw new AbortError(
|
|
252
263
|
"Request was aborted",
|
|
253
|
-
|
|
264
|
+
dispatchSignal.reason
|
|
254
265
|
);
|
|
255
266
|
}
|
|
256
267
|
}
|
|
@@ -267,11 +278,11 @@ function createClient(opts = {}) {
|
|
|
267
278
|
dispatchCtx.metadata.retry.lastError = err;
|
|
268
279
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
269
280
|
if (timeoutSignal?.aborted && (!userSignal || !userSignal.aborted)) {
|
|
270
|
-
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
271
281
|
throw new TimeoutError("signal timed out", err);
|
|
272
282
|
} else if (userSignal?.aborted) {
|
|
273
|
-
effectiveHooks.onAbort?.(requestForAttempt);
|
|
274
283
|
throw new AbortError("Request was aborted by user");
|
|
284
|
+
} else if (controller.signal.aborted) {
|
|
285
|
+
throw new AbortError("Request was aborted", err);
|
|
275
286
|
} else {
|
|
276
287
|
throw new AbortError(
|
|
277
288
|
"Request was aborted",
|
|
@@ -296,7 +307,6 @@ function createClient(opts = {}) {
|
|
|
296
307
|
res = await effectiveHooks.transformResponse(res, requestForAttempt);
|
|
297
308
|
}
|
|
298
309
|
await effectiveHooks.after?.(requestForAttempt, res);
|
|
299
|
-
await effectiveHooks.onComplete?.(requestForAttempt, res, void 0);
|
|
300
310
|
if (effectiveThrowOnHttpError && (res.status >= 400 && res.status < 500 && res.status !== 429 || res.status >= 500 || res.status === 429)) {
|
|
301
311
|
const { HttpError: HttpError2 } = await import("./error-H4GGJSCM.js");
|
|
302
312
|
throw new HttpError2(
|
|
@@ -307,6 +317,18 @@ function createClient(opts = {}) {
|
|
|
307
317
|
return res;
|
|
308
318
|
} catch (err) {
|
|
309
319
|
dispatchCtx.metadata.retry.lastError = err;
|
|
320
|
+
if (err instanceof TimeoutError) {
|
|
321
|
+
if (dispatchCtx === pluginContext) {
|
|
322
|
+
await reportCoreError(err, requestForAttempt);
|
|
323
|
+
}
|
|
324
|
+
throw err;
|
|
325
|
+
}
|
|
326
|
+
if (err instanceof AbortError) {
|
|
327
|
+
if (dispatchCtx === pluginContext) {
|
|
328
|
+
await reportCoreError(err, requestForAttempt);
|
|
329
|
+
}
|
|
330
|
+
throw err;
|
|
331
|
+
}
|
|
310
332
|
if (lastResponse) {
|
|
311
333
|
const resp = lastResponse;
|
|
312
334
|
if (effectiveThrowOnHttpError && (resp.status >= 400 && resp.status < 500 && resp.status !== 429 || resp.status >= 500 || resp.status === 429)) {
|
|
@@ -318,33 +340,19 @@ function createClient(opts = {}) {
|
|
|
318
340
|
}
|
|
319
341
|
return resp;
|
|
320
342
|
}
|
|
321
|
-
if (err instanceof TimeoutError) {
|
|
322
|
-
await effectiveHooks.onTimeout?.(requestForAttempt);
|
|
323
|
-
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
324
|
-
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
325
|
-
throw err;
|
|
326
|
-
}
|
|
327
|
-
if (err instanceof AbortError) {
|
|
328
|
-
await effectiveHooks.onAbort?.(requestForAttempt);
|
|
329
|
-
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
330
|
-
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
331
|
-
throw err;
|
|
332
|
-
}
|
|
333
343
|
if (err instanceof NetworkError) {
|
|
334
|
-
|
|
335
|
-
|
|
344
|
+
if (dispatchCtx === pluginContext) {
|
|
345
|
+
await reportCoreError(err, requestForAttempt);
|
|
346
|
+
}
|
|
336
347
|
throw err;
|
|
337
348
|
}
|
|
338
349
|
const retryErr = new RetryLimitError(
|
|
339
350
|
typeof err === "object" && err && "message" in err && typeof err.message === "string" ? err.message : "Retry limit reached",
|
|
340
351
|
err
|
|
341
352
|
);
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
void 0,
|
|
346
|
-
retryErr
|
|
347
|
-
);
|
|
353
|
+
if (dispatchCtx === pluginContext) {
|
|
354
|
+
await reportCoreError(retryErr, requestForAttempt);
|
|
355
|
+
}
|
|
348
356
|
throw retryErr;
|
|
349
357
|
}
|
|
350
358
|
};
|
|
@@ -359,12 +367,21 @@ function createClient(opts = {}) {
|
|
|
359
367
|
dispatch = plugin.wrapDispatch(dispatch);
|
|
360
368
|
}
|
|
361
369
|
}
|
|
370
|
+
let completeCalled = false;
|
|
371
|
+
const callComplete = async (response, error) => {
|
|
372
|
+
if (completeCalled) return;
|
|
373
|
+
completeCalled = true;
|
|
374
|
+
await effectiveHooks.onComplete?.(request, response, error);
|
|
375
|
+
};
|
|
362
376
|
const actualPromise = dispatch(pluginContext).then(async (response) => {
|
|
377
|
+
await callComplete(response, void 0);
|
|
363
378
|
for (const plugin of plugins) {
|
|
364
379
|
await plugin.onSuccess?.(pluginContext, response);
|
|
365
380
|
}
|
|
366
381
|
return response;
|
|
367
382
|
}).catch(async (err) => {
|
|
383
|
+
await reportCoreError(err, request);
|
|
384
|
+
await callComplete(void 0, err);
|
|
368
385
|
for (const plugin of plugins) {
|
|
369
386
|
await plugin.onError?.(pluginContext, err);
|
|
370
387
|
}
|