@fetchkit/ffetch 5.0.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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 {\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 ClientPlugin,\n type PluginExtensionBase,\n} from './plugins.js'\nimport {\n TimeoutError,\n AbortError,\n RetryLimitError,\n NetworkError,\n} from './error.js'\n\nexport function createClient<\n TPlugins extends\n readonly ClientPlugin<PluginExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase>[],\n>(\n opts: FFetchOptions<TPlugins> = {} as FFetchOptions<TPlugins>\n): FFetch<PluginExtensions<TPlugins>> {\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 = async (\n input: RequestInfo | URL,\n init: FFetchRequestInit = {}\n ) => {\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 let attempt = 0\n const shouldRetryWithHook = (ctx: import('./types').RetryContext) => {\n attempt = ctx.attempt\n pluginContext.metadata.retry.attempt = attempt\n pluginContext.metadata.retry.lastError = ctx.error\n pluginContext.metadata.retry.lastResponse = ctx.response\n const retrying = effectiveShouldRetry(ctx)\n pluginContext.metadata.retry.shouldRetryResult = retrying\n if (retrying && attempt <= effectiveRetries) {\n effectiveHooks.onRetry?.(\n request,\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?.(request)\n throw new AbortError('Request was aborted by user')\n }\n if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(request)\n throw new TimeoutError('signal timed out')\n }\n if (typeof combinedSignal?.throwIfAborted === 'function') {\n combinedSignal.throwIfAborted()\n } else if (combinedSignal?.aborted) {\n if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(request)\n throw new AbortError('Request was aborted by user')\n } else if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(request)\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(request, {\n signal: combinedSignal,\n })\n try {\n const handler = init.fetchHandler ?? fetchHandler ?? fetch\n const response = await handler(reqWithSignal)\n lastResponse = response\n pluginContext.metadata.retry.lastResponse = response\n return response\n } catch (err) {\n pluginContext.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?.(request)\n throw new TimeoutError('signal timed out', err)\n } else if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(request)\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 request,\n combinedSignal\n )\n if (effectiveHooks.transformResponse) {\n res = await effectiveHooks.transformResponse(res, request)\n }\n await effectiveHooks.after?.(request, res)\n await effectiveHooks.onComplete?.(request, 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 pluginContext.metadata.retry.lastError = err\n if (lastResponse) {\n const resp = lastResponse as Response\n if (\n effectiveThrowOnHttpError &&\n ((resp.status >= 400 && resp.status < 500 && 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?.(request)\n await effectiveHooks.onError?.(request, err)\n await effectiveHooks.onComplete?.(request, undefined, err)\n throw err\n }\n if (err instanceof AbortError) {\n await effectiveHooks.onAbort?.(request)\n await effectiveHooks.onError?.(request, err)\n await effectiveHooks.onComplete?.(request, undefined, err)\n throw err\n }\n if (err instanceof NetworkError) {\n await effectiveHooks.onError?.(request, err)\n await effectiveHooks.onComplete?.(request, 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?.(request, retryErr)\n await effectiveHooks.onComplete?.(request, undefined, retryErr)\n throw retryErr\n }\n }\n\n const baseDispatch: PluginDispatch = async () => retryWithHooks()\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 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<PluginExtensions<TPlugins>>\n}\n"],"mappings":"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","names":["shouldRetry","controller"]}
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"]}
package/dist/index.min.js CHANGED
@@ -1,2 +1,2 @@
1
- import{a as R,b as I,c as b,d as M,e as O}from"./chunk-UP35S5ZH.min.js";var U=c=>{let i=c.response?.headers.get("Retry-After");if(i){let o=parseInt(i,10);if(!isNaN(o))return o*1e3;let w=Date.parse(i);if(!isNaN(w))return Math.max(0,w-Date.now())}return 2**c.attempt*200+Math.random()*100};function K(c,i){return c<=0?Promise.resolve():new Promise(o=>{if(!i){setTimeout(o,c);return}if(i.aborted){o();return}let w=()=>{clearTimeout(A),o()},A=setTimeout(()=>{i.removeEventListener("abort",w),o()},c);i.addEventListener("abort",w,{once:!0})})}async function _(c,i,o,w=()=>!0,A,q){let D,P;for(let g=0;g<=i;g++){let u={attempt:g+1,request:A,response:P,error:D};try{if(P=await c(),u.response=P,u.error=void 0,g<i&&w(u)){let d=typeof o=="function"?o(u):o;await K(d,q);continue}return P}catch(d){if(D=d,u.error=d,g===i||!w(u))throw d;let k=typeof o=="function"?o(u):o;await K(k,q)}}throw D}function z(c){let{error:i,response:o}=c;return i instanceof b||i instanceof I||i instanceof R?!1:o?o.status>=500||o.status===429:!0}function V(c={}){let{timeout:i=5e3,retries:o=0,retryDelay:w=U,shouldRetry:A=z,hooks:q={},fetchHandler:D,plugins:P=[]}=c,g=Object.create(null),u=P.map((p,a)=>({plugin:p,index:a})).sort((p,a)=>{let t=p.plugin.order??0,r=a.plugin.order??0;return t!==r?t-r:p.index-a.index}).map(p=>p.plugin);for(let p of u)p.setup?.({defineExtension:(a,t)=>{let r=a;if(r in g)throw new Error(`Plugin extension collision for property "${String(r)}"`);if("get"in t){g[r]={get:t.get,enumerable:t.enumerable??!0,configurable:!1};return}g[r]={value:t.value,writable:!1,enumerable:t.enumerable??!0,configurable:!1}}});let d=[];function k(){for(let p of d)p.controller?.abort()}let S=async(p,a={})=>{let t=new Request(p,a),r={...q,...a.hooks||{}};r.transformRequest&&(t=await r.transformRequest(t)),await r.before?.(t);let H=a.retries??o,L=typeof a.retryDelay<"u"?a.retryDelay:w,G=a.shouldRetry??A,v=a.timeout??i,m=a.signal,F=t.signal,l={request:t,init:a,state:Object.create(null),metadata:{startedAt:Date.now(),timeoutMs:v,signals:{user:m??void 0,transformed:F},retry:{configuredRetries:H,configuredDelay:L,attempt:0}}};for(let n of u)await n.preRequest?.(l);let $=typeof a.throwOnHttpError<"u"?a.throwOnHttpError:c.throwOnHttpError??!1;function J(n){if(typeof AbortSignal?.timeout=="function")return AbortSignal.timeout(n);let f=new AbortController,C=setTimeout(()=>f.abort(),n);return f.signal.addEventListener("abort",()=>clearTimeout(C),{once:!0}),f.signal}let E,h,j;v>0&&(E=J(v),l.metadata.signals.timeout=E);let x=[];if(m&&x.push(m),F&&F!==m&&x.push(F),E&&x.push(E),x.length===1)h=x[0],j=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.");h=AbortSignal.any(x),j=new AbortController}l.metadata.signals.combined=h;let Q=async()=>{let n=0,f=e=>{n=e.attempt,l.metadata.retry.attempt=n,l.metadata.retry.lastError=e.error,l.metadata.retry.lastResponse=e.response;let y=G(e);return l.metadata.retry.shouldRetryResult=y,y&&n<=H&&r.onRetry?.(t,n-1,e.error,e.response),y},C;try{let e=await _(async()=>{if(m?.aborted)throw r.onAbort?.(t),new b("Request was aborted by user");if(E?.aborted)throw r.onTimeout?.(t),new R("signal timed out");if(typeof h?.throwIfAborted=="function")h.throwIfAborted();else if(h?.aborted)throw m?.aborted?(r.onAbort?.(t),new b("Request was aborted by user")):E?.aborted?(r.onTimeout?.(t),new R("signal timed out")):new b("Request was aborted",new DOMException("Aborted","AbortError"));let y=new Request(t,{signal:h});try{let T=await(a.fetchHandler??D??fetch)(y);return C=T,l.metadata.retry.lastResponse=T,T}catch(s){throw l.metadata.retry.lastError=s,s instanceof DOMException&&s.name==="AbortError"?E?.aborted&&(!m||!m.aborted)?(r.onTimeout?.(t),new R("signal timed out",s)):m?.aborted?(r.onAbort?.(t),new b("Request was aborted by user")):new b("Request was aborted",new DOMException("Aborted","AbortError")):s instanceof TypeError&&/NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(s.message)?new O(s.message,s):s}},H,L,f,t,h);if(r.transformResponse&&(e=await r.transformResponse(e,t)),await r.after?.(t,e),await r.onComplete?.(t,e,void 0),$&&(e.status>=400&&e.status<500&&e.status!==429||e.status>=500||e.status===429)){let{HttpError:y}=await import("./error-7EEQP46E.min.js");throw new y(`HTTP error: ${e.status} ${e.statusText}`,e)}return e}catch(e){if(l.metadata.retry.lastError=e,C){let s=C;if($&&(s.status>=400&&s.status<500&&s.status!==429||s.status>=500||s.status===429)){let{HttpError:T}=await import("./error-7EEQP46E.min.js");throw new T(`HTTP error: ${s.status} ${s.statusText}`,s)}return s}if(e instanceof R)throw await r.onTimeout?.(t),await r.onError?.(t,e),await r.onComplete?.(t,void 0,e),e;if(e instanceof b)throw await r.onAbort?.(t),await r.onError?.(t,e),await r.onComplete?.(t,void 0,e),e;if(e instanceof O)throw await r.onError?.(t,e),await r.onComplete?.(t,void 0,e),e;let y=new M(typeof e=="object"&&e&&"message"in e&&typeof e.message=="string"?e.message:"Retry limit reached",e);throw await r.onError?.(t,y),await r.onComplete?.(t,void 0,y),y}},N=async()=>Q();for(let n=u.length-1;n>=0;n--){let f=u[n];f.wrapDispatch&&(N=f.wrapDispatch(N))}let B=N(l).then(async n=>{for(let f of u)await f.onSuccess?.(l,n);return n}).catch(async n=>{for(let f of u)await f.onError?.(l,n);throw n}),W={promise:B,request:t,controller:j};return d.push(W),B.finally(async()=>{for(let f of u)await f.onFinally?.(l);let n=d.indexOf(W);n>-1&&d.splice(n,1)})};return Object.defineProperty(S,"pendingRequests",{get(){return d},enumerable:!1,configurable:!1}),Object.defineProperty(S,"abortAll",{value:k,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperties(S,g),S}export{b as AbortError,I as CircuitOpenError,O as NetworkError,M as RetryLimitError,R as TimeoutError,V as createClient};
1
+ import{a as E,b as B,c as h,d as L,e as H,f as Y}from"./chunk-UP35S5ZH.min.js";var z=c=>{let a=c.response?.headers.get("Retry-After");if(a){let o=parseInt(a,10);if(!isNaN(o))return o*1e3;let w=Date.parse(a);if(!isNaN(w))return Math.max(0,w-Date.now())}return 2**c.attempt*200+Math.random()*100};function _(c,a){return c<=0?Promise.resolve():new Promise(o=>{if(!a){setTimeout(o,c);return}if(a.aborted){o();return}let w=()=>{clearTimeout(D),o()},D=setTimeout(()=>{a.removeEventListener("abort",w),o()},c);a.addEventListener("abort",w,{once:!0})})}async function G(c,a,o,w=()=>!0,D,F){let T,A;for(let b=0;b<=a;b++){let u={attempt:b+1,request:D,response:A,error:T};try{if(A=await c(),u.response=A,u.error=void 0,b<a&&w(u)){let m=typeof o=="function"?o(u):o;await _(m,F);continue}return A}catch(m){if(T=m,u.error=m,b===a||!w(u))throw m;let v=typeof o=="function"?o(u):o;await _(v,F)}}throw T}function J(c){let{error:a,response:o}=c;return a instanceof h||a instanceof B||a instanceof E?!1:o?o.status>=500||o.status===429:!0}function Z(c={}){let{timeout:a=5e3,retries:o=0,retryDelay:w=z,shouldRetry:D=J,hooks:F={},fetchHandler:T,plugins:A=[]}=c,b=Object.create(null),u=A.map((p,i)=>({plugin:p,index:i})).sort((p,i)=>{let R=p.plugin.order??0,d=i.plugin.order??0;return R!==d?R-d:p.index-i.index}).map(p=>p.plugin);for(let p of u)p.setup?.({defineExtension:(i,R)=>{let d=i;if(d in b)throw new Error(`Plugin extension collision for property "${String(d)}"`);if("get"in R){b[d]={get:R.get,enumerable:R.enumerable??!0,configurable:!1};return}b[d]={value:R.value,writable:!1,enumerable:R.enumerable??!0,configurable:!1}}});let m=[];function v(){for(let p of m)p.controller?.abort()}let O=(p,i={})=>{let d=(async()=>{let t=new Request(p,i),r={...F,...i.hooks||{}};r.transformRequest&&(t=await r.transformRequest(t)),await r.before?.(t);let j=i.retries??o,$=typeof i.retryDelay<"u"?i.retryDelay:w,Q=i.shouldRetry??D,N=i.timeout??a,y=i.signal,k=t.signal,l={request:t,init:i,state:Object.create(null),metadata:{startedAt:Date.now(),timeoutMs:N,signals:{user:y??void 0,transformed:k},retry:{configuredRetries:j,configuredDelay:$,attempt:0}}};for(let n of u)await n.preRequest?.(l);let W=typeof i.throwOnHttpError<"u"?i.throwOnHttpError:c.throwOnHttpError??!1;function V(n){if(typeof AbortSignal?.timeout=="function")return AbortSignal.timeout(n);let f=new AbortController,C=setTimeout(()=>f.abort(),n);return f.signal.addEventListener("abort",()=>clearTimeout(C),{once:!0}),f.signal}let x,P,I;N>0&&(x=V(N),l.metadata.signals.timeout=x);let q=[];if(y&&q.push(y),k&&k!==y&&q.push(k),x&&q.push(x),q.length===1)P=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.");P=AbortSignal.any(q),I=new AbortController}l.metadata.signals.combined=P;let X=async()=>{let n=0,f=e=>{n=e.attempt,l.metadata.retry.attempt=n,l.metadata.retry.lastError=e.error,l.metadata.retry.lastResponse=e.response;let g=Q(e);return l.metadata.retry.shouldRetryResult=g,g&&n<=j&&r.onRetry?.(t,n-1,e.error,e.response),g},C;try{let e=await G(async()=>{if(y?.aborted)throw r.onAbort?.(t),new h("Request was aborted by user");if(x?.aborted)throw r.onTimeout?.(t),new E("signal timed out");if(typeof P?.throwIfAborted=="function")P.throwIfAborted();else if(P?.aborted)throw y?.aborted?(r.onAbort?.(t),new h("Request was aborted by user")):x?.aborted?(r.onTimeout?.(t),new E("signal timed out")):new h("Request was aborted",new DOMException("Aborted","AbortError"));let g=new Request(t,{signal:P});try{let S=await(i.fetchHandler??T??fetch)(g);return C=S,l.metadata.retry.lastResponse=S,S}catch(s){throw l.metadata.retry.lastError=s,s instanceof DOMException&&s.name==="AbortError"?x?.aborted&&(!y||!y.aborted)?(r.onTimeout?.(t),new E("signal timed out",s)):y?.aborted?(r.onAbort?.(t),new h("Request was aborted by user")):new h("Request was aborted",new DOMException("Aborted","AbortError")):s instanceof TypeError&&/NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(s.message)?new H(s.message,s):s}},j,$,f,t,P);if(r.transformResponse&&(e=await r.transformResponse(e,t)),await r.after?.(t,e),await r.onComplete?.(t,e,void 0),W&&(e.status>=400&&e.status<500&&e.status!==429||e.status>=500||e.status===429)){let{HttpError:g}=await import("./error-7EEQP46E.min.js");throw new g(`HTTP error: ${e.status} ${e.statusText}`,e)}return e}catch(e){if(l.metadata.retry.lastError=e,C){let s=C;if(W&&(s.status>=400&&s.status<500&&s.status!==429||s.status>=500||s.status===429)){let{HttpError:S}=await import("./error-7EEQP46E.min.js");throw new S(`HTTP error: ${s.status} ${s.statusText}`,s)}return s}if(e instanceof E)throw await r.onTimeout?.(t),await r.onError?.(t,e),await r.onComplete?.(t,void 0,e),e;if(e instanceof h)throw await r.onAbort?.(t),await r.onError?.(t,e),await r.onComplete?.(t,void 0,e),e;if(e instanceof H)throw await r.onError?.(t,e),await r.onComplete?.(t,void 0,e),e;let g=new L(typeof e=="object"&&e&&"message"in e&&typeof e.message=="string"?e.message:"Retry limit reached",e);throw await r.onError?.(t,g),await r.onComplete?.(t,void 0,g),g}},M=async()=>X();for(let n=u.length-1;n>=0;n--){let f=u[n];f.wrapDispatch&&(M=f.wrapDispatch(M))}let K=M(l).then(async n=>{for(let f of u)await f.onSuccess?.(l,n);return n}).catch(async n=>{for(let f of u)await f.onError?.(l,n);throw n}),U={promise:K,request:t,controller:I};return m.push(U),K.finally(async()=>{for(let f of u)await f.onFinally?.(l);let n=m.indexOf(U);n>-1&&m.splice(n,1)})})();for(let t of u)t.decoratePromise&&(d=t.decoratePromise(d));return d};return Object.defineProperty(O,"pendingRequests",{get(){return m},enumerable:!1,configurable:!1}),Object.defineProperty(O,"abortAll",{value:v,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperties(O,b),O}export{h as AbortError,B as CircuitOpenError,Y as HttpError,H as NetworkError,L as RetryLimitError,E as TimeoutError,Z as createClient};
2
2
  //# sourceMappingURL=index.min.js.map
@@ -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 {\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 ClientPlugin,\n type PluginExtensionBase,\n} from './plugins.js'\nimport {\n TimeoutError,\n AbortError,\n RetryLimitError,\n NetworkError,\n} from './error.js'\n\nexport function createClient<\n TPlugins extends\n readonly ClientPlugin<PluginExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase>[],\n>(\n opts: FFetchOptions<TPlugins> = {} as FFetchOptions<TPlugins>\n): FFetch<PluginExtensions<TPlugins>> {\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 = async (\n input: RequestInfo | URL,\n init: FFetchRequestInit = {}\n ) => {\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 let attempt = 0\n const shouldRetryWithHook = (ctx: import('./types').RetryContext) => {\n attempt = ctx.attempt\n pluginContext.metadata.retry.attempt = attempt\n pluginContext.metadata.retry.lastError = ctx.error\n pluginContext.metadata.retry.lastResponse = ctx.response\n const retrying = effectiveShouldRetry(ctx)\n pluginContext.metadata.retry.shouldRetryResult = retrying\n if (retrying && attempt <= effectiveRetries) {\n effectiveHooks.onRetry?.(\n request,\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?.(request)\n throw new AbortError('Request was aborted by user')\n }\n if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(request)\n throw new TimeoutError('signal timed out')\n }\n if (typeof combinedSignal?.throwIfAborted === 'function') {\n combinedSignal.throwIfAborted()\n } else if (combinedSignal?.aborted) {\n if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(request)\n throw new AbortError('Request was aborted by user')\n } else if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(request)\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(request, {\n signal: combinedSignal,\n })\n try {\n const handler = init.fetchHandler ?? fetchHandler ?? fetch\n const response = await handler(reqWithSignal)\n lastResponse = response\n pluginContext.metadata.retry.lastResponse = response\n return response\n } catch (err) {\n pluginContext.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?.(request)\n throw new TimeoutError('signal timed out', err)\n } else if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(request)\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 request,\n combinedSignal\n )\n if (effectiveHooks.transformResponse) {\n res = await effectiveHooks.transformResponse(res, request)\n }\n await effectiveHooks.after?.(request, res)\n await effectiveHooks.onComplete?.(request, 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 pluginContext.metadata.retry.lastError = err\n if (lastResponse) {\n const resp = lastResponse as Response\n if (\n effectiveThrowOnHttpError &&\n ((resp.status >= 400 && resp.status < 500 && 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?.(request)\n await effectiveHooks.onError?.(request, err)\n await effectiveHooks.onComplete?.(request, undefined, err)\n throw err\n }\n if (err instanceof AbortError) {\n await effectiveHooks.onAbort?.(request)\n await effectiveHooks.onError?.(request, err)\n await effectiveHooks.onComplete?.(request, undefined, err)\n throw err\n }\n if (err instanceof NetworkError) {\n await effectiveHooks.onError?.(request, err)\n await effectiveHooks.onComplete?.(request, 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?.(request, retryErr)\n await effectiveHooks.onComplete?.(request, undefined, retryErr)\n throw retryErr\n }\n }\n\n const baseDispatch: PluginDispatch = async () => retryWithHooks()\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 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<PluginExtensions<TPlugins>>\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","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 {\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,4 +1,4 @@
1
- import { C as ClientPlugin } from '../plugins-9qcU31nU.cjs';
1
+ import { C as ClientPlugin } from '../plugins-DqBQVM4I.cjs';
2
2
 
3
3
  type CircuitPluginExtension = {
4
4
  circuitOpen: boolean;
@@ -1,4 +1,4 @@
1
- import { C as ClientPlugin } from '../plugins-9qcU31nU.js';
1
+ import { C as ClientPlugin } from '../plugins-DqBQVM4I.js';
2
2
 
3
3
  type CircuitPluginExtension = {
4
4
  circuitOpen: boolean;
@@ -1,4 +1,4 @@
1
- import { C as ClientPlugin } from '../plugins-9qcU31nU.cjs';
1
+ import { C as ClientPlugin } from '../plugins-DqBQVM4I.cjs';
2
2
 
3
3
  type DedupeHashParams = {
4
4
  method: string;
@@ -1,4 +1,4 @@
1
- import { C as ClientPlugin } from '../plugins-9qcU31nU.js';
1
+ import { C as ClientPlugin } from '../plugins-DqBQVM4I.js';
2
2
 
3
3
  type DedupeHashParams = {
4
4
  method: string;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/plugins/request-shortcuts.ts
21
+ var request_shortcuts_exports = {};
22
+ __export(request_shortcuts_exports, {
23
+ requestShortcutsPlugin: () => requestShortcutsPlugin
24
+ });
25
+ module.exports = __toCommonJS(request_shortcuts_exports);
26
+ function methodShortcut(method) {
27
+ return function requestShortcut(input, init = {}) {
28
+ if (typeof this !== "function") {
29
+ throw new TypeError(
30
+ "requestShortcutsPlugin methods must be called from a client instance"
31
+ );
32
+ }
33
+ const client = this;
34
+ return client(input, { ...init, method });
35
+ };
36
+ }
37
+ function requestShortcutsPlugin() {
38
+ return {
39
+ name: "request-shortcuts",
40
+ setup: ({ defineExtension }) => {
41
+ defineExtension("get", {
42
+ value: methodShortcut("GET"),
43
+ enumerable: false
44
+ });
45
+ defineExtension("post", {
46
+ value: methodShortcut("POST"),
47
+ enumerable: false
48
+ });
49
+ defineExtension("put", {
50
+ value: methodShortcut("PUT"),
51
+ enumerable: false
52
+ });
53
+ defineExtension("patch", {
54
+ value: methodShortcut("PATCH"),
55
+ enumerable: false
56
+ });
57
+ defineExtension("delete", {
58
+ value: methodShortcut("DELETE"),
59
+ enumerable: false
60
+ });
61
+ defineExtension("head", {
62
+ value: methodShortcut("HEAD"),
63
+ enumerable: false
64
+ });
65
+ defineExtension("options", {
66
+ value: methodShortcut("OPTIONS"),
67
+ enumerable: false
68
+ });
69
+ }
70
+ };
71
+ }
72
+ // Annotate the CommonJS export names for ESM import in node:
73
+ 0 && (module.exports = {
74
+ requestShortcutsPlugin
75
+ });
76
+ //# sourceMappingURL=request-shortcuts.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugins/request-shortcuts.ts"],"sourcesContent":["import type { FFetchRequestInit } from '../types.js'\nimport type { ClientPlugin } from '../plugins.js'\n\ntype RequestShortcut = <\n TThis extends (\n input: RequestInfo | URL,\n init?: FFetchRequestInit\n ) => Promise<Response>,\n>(\n this: TThis,\n input: RequestInfo | URL,\n init?: FFetchRequestInit\n) => ReturnType<TThis>\n\nexport type RequestShortcuts = {\n get: RequestShortcut\n post: RequestShortcut\n put: RequestShortcut\n patch: RequestShortcut\n delete: RequestShortcut\n head: RequestShortcut\n options: RequestShortcut\n}\n\nfunction methodShortcut(method: RequestInit['method']): RequestShortcut {\n return function requestShortcut<\n TThis extends (\n input: RequestInfo | URL,\n init?: FFetchRequestInit\n ) => Promise<Response>,\n >(\n this: TThis,\n input: RequestInfo | URL,\n init: FFetchRequestInit = {}\n ): ReturnType<TThis> {\n if (typeof this !== 'function') {\n throw new TypeError(\n 'requestShortcutsPlugin methods must be called from a client instance'\n )\n }\n\n const client = this as TThis\n\n return client(input, { ...init, method }) as ReturnType<TThis>\n }\n}\n\nexport function requestShortcutsPlugin(): ClientPlugin<RequestShortcuts> {\n return {\n name: 'request-shortcuts',\n setup: ({ defineExtension }) => {\n defineExtension('get', {\n value: methodShortcut('GET'),\n enumerable: false,\n })\n defineExtension('post', {\n value: methodShortcut('POST'),\n enumerable: false,\n })\n defineExtension('put', {\n value: methodShortcut('PUT'),\n enumerable: false,\n })\n defineExtension('patch', {\n value: methodShortcut('PATCH'),\n enumerable: false,\n })\n defineExtension('delete', {\n value: methodShortcut('DELETE'),\n enumerable: false,\n })\n defineExtension('head', {\n value: methodShortcut('HEAD'),\n enumerable: false,\n })\n defineExtension('options', {\n value: methodShortcut('OPTIONS'),\n enumerable: false,\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBA,SAAS,eAAe,QAAgD;AACtE,SAAO,SAAS,gBAOd,OACA,OAA0B,CAAC,GACR;AACnB,QAAI,OAAO,SAAS,YAAY;AAC9B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS;AAEf,WAAO,OAAO,OAAO,EAAE,GAAG,MAAM,OAAO,CAAC;AAAA,EAC1C;AACF;AAEO,SAAS,yBAAyD;AACvE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO,CAAC,EAAE,gBAAgB,MAAM;AAC9B,sBAAgB,OAAO;AAAA,QACrB,OAAO,eAAe,KAAK;AAAA,QAC3B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,QAAQ;AAAA,QACtB,OAAO,eAAe,MAAM;AAAA,QAC5B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,OAAO;AAAA,QACrB,OAAO,eAAe,KAAK;AAAA,QAC3B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,SAAS;AAAA,QACvB,OAAO,eAAe,OAAO;AAAA,QAC7B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,UAAU;AAAA,QACxB,OAAO,eAAe,QAAQ;AAAA,QAC9B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,QAAQ;AAAA,QACtB,OAAO,eAAe,MAAM;AAAA,QAC5B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,WAAW;AAAA,QACzB,OAAO,eAAe,SAAS;AAAA,QAC/B,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,16 @@
1
+ import { b as FFetchRequestInit } from '../types-DbmivXba.cjs';
2
+ import { C as ClientPlugin } from '../plugins-DqBQVM4I.cjs';
3
+
4
+ type RequestShortcut = <TThis extends (input: RequestInfo | URL, init?: FFetchRequestInit) => Promise<Response>>(this: TThis, input: RequestInfo | URL, init?: FFetchRequestInit) => ReturnType<TThis>;
5
+ type RequestShortcuts = {
6
+ get: RequestShortcut;
7
+ post: RequestShortcut;
8
+ put: RequestShortcut;
9
+ patch: RequestShortcut;
10
+ delete: RequestShortcut;
11
+ head: RequestShortcut;
12
+ options: RequestShortcut;
13
+ };
14
+ declare function requestShortcutsPlugin(): ClientPlugin<RequestShortcuts>;
15
+
16
+ export { type RequestShortcuts, requestShortcutsPlugin };
@@ -0,0 +1,16 @@
1
+ import { b as FFetchRequestInit } from '../types-DpHoyvhy.js';
2
+ import { C as ClientPlugin } from '../plugins-DqBQVM4I.js';
3
+
4
+ type RequestShortcut = <TThis extends (input: RequestInfo | URL, init?: FFetchRequestInit) => Promise<Response>>(this: TThis, input: RequestInfo | URL, init?: FFetchRequestInit) => ReturnType<TThis>;
5
+ type RequestShortcuts = {
6
+ get: RequestShortcut;
7
+ post: RequestShortcut;
8
+ put: RequestShortcut;
9
+ patch: RequestShortcut;
10
+ delete: RequestShortcut;
11
+ head: RequestShortcut;
12
+ options: RequestShortcut;
13
+ };
14
+ declare function requestShortcutsPlugin(): ClientPlugin<RequestShortcuts>;
15
+
16
+ export { type RequestShortcuts, requestShortcutsPlugin };
@@ -0,0 +1,51 @@
1
+ // src/plugins/request-shortcuts.ts
2
+ function methodShortcut(method) {
3
+ return function requestShortcut(input, init = {}) {
4
+ if (typeof this !== "function") {
5
+ throw new TypeError(
6
+ "requestShortcutsPlugin methods must be called from a client instance"
7
+ );
8
+ }
9
+ const client = this;
10
+ return client(input, { ...init, method });
11
+ };
12
+ }
13
+ function requestShortcutsPlugin() {
14
+ return {
15
+ name: "request-shortcuts",
16
+ setup: ({ defineExtension }) => {
17
+ defineExtension("get", {
18
+ value: methodShortcut("GET"),
19
+ enumerable: false
20
+ });
21
+ defineExtension("post", {
22
+ value: methodShortcut("POST"),
23
+ enumerable: false
24
+ });
25
+ defineExtension("put", {
26
+ value: methodShortcut("PUT"),
27
+ enumerable: false
28
+ });
29
+ defineExtension("patch", {
30
+ value: methodShortcut("PATCH"),
31
+ enumerable: false
32
+ });
33
+ defineExtension("delete", {
34
+ value: methodShortcut("DELETE"),
35
+ enumerable: false
36
+ });
37
+ defineExtension("head", {
38
+ value: methodShortcut("HEAD"),
39
+ enumerable: false
40
+ });
41
+ defineExtension("options", {
42
+ value: methodShortcut("OPTIONS"),
43
+ enumerable: false
44
+ });
45
+ }
46
+ };
47
+ }
48
+ export {
49
+ requestShortcutsPlugin
50
+ };
51
+ //# sourceMappingURL=request-shortcuts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugins/request-shortcuts.ts"],"sourcesContent":["import type { FFetchRequestInit } from '../types.js'\nimport type { ClientPlugin } from '../plugins.js'\n\ntype RequestShortcut = <\n TThis extends (\n input: RequestInfo | URL,\n init?: FFetchRequestInit\n ) => Promise<Response>,\n>(\n this: TThis,\n input: RequestInfo | URL,\n init?: FFetchRequestInit\n) => ReturnType<TThis>\n\nexport type RequestShortcuts = {\n get: RequestShortcut\n post: RequestShortcut\n put: RequestShortcut\n patch: RequestShortcut\n delete: RequestShortcut\n head: RequestShortcut\n options: RequestShortcut\n}\n\nfunction methodShortcut(method: RequestInit['method']): RequestShortcut {\n return function requestShortcut<\n TThis extends (\n input: RequestInfo | URL,\n init?: FFetchRequestInit\n ) => Promise<Response>,\n >(\n this: TThis,\n input: RequestInfo | URL,\n init: FFetchRequestInit = {}\n ): ReturnType<TThis> {\n if (typeof this !== 'function') {\n throw new TypeError(\n 'requestShortcutsPlugin methods must be called from a client instance'\n )\n }\n\n const client = this as TThis\n\n return client(input, { ...init, method }) as ReturnType<TThis>\n }\n}\n\nexport function requestShortcutsPlugin(): ClientPlugin<RequestShortcuts> {\n return {\n name: 'request-shortcuts',\n setup: ({ defineExtension }) => {\n defineExtension('get', {\n value: methodShortcut('GET'),\n enumerable: false,\n })\n defineExtension('post', {\n value: methodShortcut('POST'),\n enumerable: false,\n })\n defineExtension('put', {\n value: methodShortcut('PUT'),\n enumerable: false,\n })\n defineExtension('patch', {\n value: methodShortcut('PATCH'),\n enumerable: false,\n })\n defineExtension('delete', {\n value: methodShortcut('DELETE'),\n enumerable: false,\n })\n defineExtension('head', {\n value: methodShortcut('HEAD'),\n enumerable: false,\n })\n defineExtension('options', {\n value: methodShortcut('OPTIONS'),\n enumerable: false,\n })\n },\n }\n}\n"],"mappings":";AAwBA,SAAS,eAAe,QAAgD;AACtE,SAAO,SAAS,gBAOd,OACA,OAA0B,CAAC,GACR;AACnB,QAAI,OAAO,SAAS,YAAY;AAC9B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS;AAEf,WAAO,OAAO,OAAO,EAAE,GAAG,MAAM,OAAO,CAAC;AAAA,EAC1C;AACF;AAEO,SAAS,yBAAyD;AACvE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO,CAAC,EAAE,gBAAgB,MAAM;AAC9B,sBAAgB,OAAO;AAAA,QACrB,OAAO,eAAe,KAAK;AAAA,QAC3B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,QAAQ;AAAA,QACtB,OAAO,eAAe,MAAM;AAAA,QAC5B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,OAAO;AAAA,QACrB,OAAO,eAAe,KAAK;AAAA,QAC3B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,SAAS;AAAA,QACvB,OAAO,eAAe,OAAO;AAAA,QAC7B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,UAAU;AAAA,QACxB,OAAO,eAAe,QAAQ;AAAA,QAC9B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,QAAQ;AAAA,QACtB,OAAO,eAAe,MAAM;AAAA,QAC5B,YAAY;AAAA,MACd,CAAC;AACD,sBAAgB,WAAW;AAAA,QACzB,OAAO,eAAe,SAAS;AAAA,QAC/B,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/plugins/response-shortcuts.ts
21
+ var response_shortcuts_exports = {};
22
+ __export(response_shortcuts_exports, {
23
+ responseShortcutsPlugin: () => responseShortcutsPlugin
24
+ });
25
+ module.exports = __toCommonJS(response_shortcuts_exports);
26
+ function attachResponseShortcuts(promise) {
27
+ const decorated = promise;
28
+ if (decorated.__ffetchResponseShortcutsDecorated__) {
29
+ return decorated;
30
+ }
31
+ Object.defineProperties(decorated, {
32
+ json: {
33
+ value: function json() {
34
+ return this.then((response) => response.json());
35
+ },
36
+ writable: false,
37
+ enumerable: false,
38
+ configurable: false
39
+ },
40
+ text: {
41
+ value: function text() {
42
+ return this.then((response) => response.text());
43
+ },
44
+ writable: false,
45
+ enumerable: false,
46
+ configurable: false
47
+ },
48
+ blob: {
49
+ value: function blob() {
50
+ return this.then((response) => response.blob());
51
+ },
52
+ writable: false,
53
+ enumerable: false,
54
+ configurable: false
55
+ },
56
+ arrayBuffer: {
57
+ value: function arrayBuffer() {
58
+ return this.then((response) => response.arrayBuffer());
59
+ },
60
+ writable: false,
61
+ enumerable: false,
62
+ configurable: false
63
+ },
64
+ formData: {
65
+ value: function formData() {
66
+ return this.then((response) => response.formData());
67
+ },
68
+ writable: false,
69
+ enumerable: false,
70
+ configurable: false
71
+ },
72
+ __ffetchResponseShortcutsDecorated__: {
73
+ value: true,
74
+ writable: false,
75
+ enumerable: false,
76
+ configurable: false
77
+ }
78
+ });
79
+ return decorated;
80
+ }
81
+ function responseShortcutsPlugin() {
82
+ return {
83
+ name: "response-shortcuts",
84
+ decoratePromise: (promise) => attachResponseShortcuts(promise)
85
+ };
86
+ }
87
+ // Annotate the CommonJS export names for ESM import in node:
88
+ 0 && (module.exports = {
89
+ responseShortcutsPlugin
90
+ });
91
+ //# sourceMappingURL=response-shortcuts.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugins/response-shortcuts.ts"],"sourcesContent":["import type { ClientPlugin } from '../plugins.js'\r\n\r\nexport type ResponseShortcuts = {\r\n json: <T = unknown>() => Promise<T>\r\n text: () => Promise<string>\r\n blob: () => Promise<Blob>\r\n arrayBuffer: () => Promise<ArrayBuffer>\r\n formData: () => Promise<FormData>\r\n}\r\n\r\ntype ResponseShortcutsPromise = Promise<Response> & ResponseShortcuts\r\n\r\ntype DecoratedPromise = ResponseShortcutsPromise & {\r\n __ffetchResponseShortcutsDecorated__?: true\r\n}\r\n\r\nfunction attachResponseShortcuts(\r\n promise: Promise<Response>\r\n): ResponseShortcutsPromise {\r\n const decorated = promise as DecoratedPromise\r\n\r\n if (decorated.__ffetchResponseShortcutsDecorated__) {\r\n return decorated\r\n }\r\n\r\n Object.defineProperties(decorated, {\r\n json: {\r\n value: function json<T = unknown>(this: Promise<Response>) {\r\n return this.then((response) => response.json() as Promise<T>)\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n text: {\r\n value: function text(this: Promise<Response>) {\r\n return this.then((response) => response.text())\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n blob: {\r\n value: function blob(this: Promise<Response>) {\r\n return this.then((response) => response.blob())\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n arrayBuffer: {\r\n value: function arrayBuffer(this: Promise<Response>) {\r\n return this.then((response) => response.arrayBuffer())\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n formData: {\r\n value: function formData(this: Promise<Response>) {\r\n return this.then((response) => response.formData())\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n __ffetchResponseShortcutsDecorated__: {\r\n value: true,\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n })\r\n\r\n return decorated\r\n}\r\n\r\nexport function responseShortcutsPlugin(): ClientPlugin<\r\n Record<never, never>,\r\n ResponseShortcuts\r\n> {\r\n return {\r\n name: 'response-shortcuts',\r\n decoratePromise: (promise) => attachResponseShortcuts(promise),\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,SAAS,wBACP,SAC0B;AAC1B,QAAM,YAAY;AAElB,MAAI,UAAU,sCAAsC;AAClD,WAAO;AAAA,EACT;AAEA,SAAO,iBAAiB,WAAW;AAAA,IACjC,MAAM;AAAA,MACJ,OAAO,SAAS,OAA2C;AACzD,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,KAAK,CAAe;AAAA,MAC9D;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,MACJ,OAAO,SAAS,OAA8B;AAC5C,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,KAAK,CAAC;AAAA,MAChD;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,MACJ,OAAO,SAAS,OAA8B;AAC5C,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,KAAK,CAAC;AAAA,MAChD;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,aAAa;AAAA,MACX,OAAO,SAAS,cAAqC;AACnD,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,YAAY,CAAC;AAAA,MACvD;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,UAAU;AAAA,MACR,OAAO,SAAS,WAAkC;AAChD,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,SAAS,CAAC;AAAA,MACpD;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,sCAAsC;AAAA,MACpC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEO,SAAS,0BAGd;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,iBAAiB,CAAC,YAAY,wBAAwB,OAAO;AAAA,EAC/D;AACF;","names":[]}