@zayne-labs/callapi 1.10.3 → 1.10.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["$GlobalRequestInfoCache","validatedResultObject: Prettify<\n\t\tPick<CallApiExtraOptions, (typeof extraOptionsToBeValidated)[number]>\n\t>","validatedResultObject: Prettify<\n\t\tPick<CallApiRequestOptions, (typeof requestOptionsToBeValidated)[number]>\n\t>","resolvedHooks: Hooks","$GlobalRequestInfoCache: GlobalRequestInfoCache","$LocalRequestInfoCache: RequestInfoCache","callApi"],"sources":["../../src/result.ts","../../src/hooks.ts","../../src/stream.ts","../../src/dedupe.ts","../../src/validation.ts","../../src/plugins.ts","../../src/retry.ts","../../src/url.ts","../../src/createFetchClient.ts","../../src/defineHelpers.ts"],"sourcesContent":["import { extraOptionDefaults } from \"./constants/default-options\";\nimport type { HTTPError, ValidationError } from \"./error\";\nimport type { CallApiExtraOptions, ThrowOnErrorUnion } from \"./types\";\nimport type { DefaultDataType, DefaultThrowOnError } from \"./types/default-types\";\nimport type { AnyString, Awaitable, UnmaskType } from \"./types/type-helpers\";\nimport { isHTTPErrorInstance, isValidationErrorInstance } from \"./utils/guards\";\n\nexport type ResponseType = \"blob\" | \"json\" | \"text\";\n\ntype Parser<TData> = (responseString: string) => Awaitable<TData>;\n\nexport const getResponseType = <TResponse>(response: Response, parser: Parser<TResponse>) => ({\n\tarrayBuffer: () => response.arrayBuffer(),\n\tblob: () => response.blob(),\n\tformData: () => response.formData(),\n\tjson: async (): Promise<TResponse> => {\n\t\tconst text = await response.text();\n\t\treturn parser(text);\n\t},\n\tstream: () => response.body,\n\ttext: () => response.text(),\n});\n\ntype InitResponseTypeMap<TResponse = unknown> = ReturnType<typeof getResponseType<TResponse>>;\n\nexport type ResponseTypeUnion = keyof InitResponseTypeMap | null;\n\nexport type ResponseTypeMap<TResponse> = {\n\t[Key in keyof InitResponseTypeMap<TResponse>]: Awaited<ReturnType<InitResponseTypeMap<TResponse>[Key]>>;\n};\n\nexport type GetResponseType<\n\tTResponse,\n\tTResponseType extends ResponseTypeUnion,\n\tTComputedResponseTypeMap extends ResponseTypeMap<TResponse> = ResponseTypeMap<TResponse>,\n> =\n\tnull extends TResponseType ? TComputedResponseTypeMap[\"json\"]\n\t: TResponseType extends NonNullable<ResponseTypeUnion> ? TComputedResponseTypeMap[TResponseType]\n\t: never;\n\nconst textTypes = new Set([\"image/svg\", \"application/xml\", \"application/xhtml\", \"application/html\"]);\nconst JSON_REGEX = /^application\\/(?:[\\w!#$%&*.^`~-]*\\+)?json(;.+)?$/i;\n\nconst detectResponseType = (response: Response): Extract<ResponseTypeUnion, \"blob\" | \"json\" | \"text\"> => {\n\tconst initContentType = response.headers.get(\"content-type\");\n\n\tif (!initContentType) {\n\t\treturn extraOptionDefaults().responseType;\n\t}\n\n\tconst contentType = initContentType.split(\";\")[0] ?? \"\";\n\n\tif (JSON_REGEX.test(contentType)) {\n\t\treturn \"json\";\n\t}\n\n\tif (textTypes.has(contentType) || contentType.startsWith(\"text/\")) {\n\t\treturn \"text\";\n\t}\n\n\treturn \"blob\";\n};\n\nexport const resolveResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: ResponseTypeUnion | undefined,\n\tparser: Parser<TResponse> | undefined\n) => {\n\tconst selectedParser = parser ?? extraOptionDefaults().responseParser;\n\tconst selectedResponseType = responseType ?? detectResponseType(response);\n\n\tconst RESPONSE_TYPE_LOOKUP = getResponseType<TResponse>(response, selectedParser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, selectedResponseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[selectedResponseType]();\n};\n\nexport type CallApiResultSuccessVariant<TData> = {\n\tdata: NoInfer<TData>;\n\terror: null;\n\tresponse: Response;\n};\n\nexport type PossibleJavaScriptError = UnmaskType<{\n\terrorData: false;\n\tmessage: string;\n\tname: \"AbortError\" | \"Error\" | \"SyntaxError\" | \"TimeoutError\" | \"TypeError\" | AnyString;\n\toriginalError: DOMException | Error | SyntaxError | TypeError;\n}>;\n\nexport type PossibleHTTPError<TErrorData> = UnmaskType<{\n\terrorData: NoInfer<TErrorData>;\n\tmessage: string;\n\tname: \"HTTPError\";\n\toriginalError: HTTPError;\n}>;\n\nexport type PossibleValidationError = UnmaskType<{\n\terrorData: ValidationError[\"errorData\"];\n\tissueCause: ValidationError[\"issueCause\"];\n\tmessage: string;\n\tname: \"ValidationError\";\n\toriginalError: ValidationError;\n}>;\n\nexport type PossibleJavaScriptOrValidationError = UnmaskType<\n\tPossibleJavaScriptError | PossibleValidationError\n>;\n\nexport type CallApiResultErrorVariant<TErrorData> =\n\t| {\n\t\t\tdata: null;\n\t\t\terror: PossibleHTTPError<TErrorData>;\n\t\t\tresponse: Response;\n\t }\n\t| {\n\t\t\tdata: null;\n\t\t\terror: PossibleJavaScriptOrValidationError;\n\t\t\tresponse: Response | null;\n\t };\n\nexport type ResultModeMapWithoutException<\n\tTData,\n\tTErrorData,\n\tTResponseType extends ResponseTypeUnion,\n\tTComputedData = GetResponseType<TData, TResponseType>,\n\tTComputedErrorData = GetResponseType<TErrorData, TResponseType>,\n> = UnmaskType<{\n\tall: CallApiResultErrorVariant<TComputedErrorData> | CallApiResultSuccessVariant<TComputedData>;\n\n\tonlyData:\n\t\t| CallApiResultErrorVariant<TComputedErrorData>[\"data\"]\n\t\t| CallApiResultSuccessVariant<TComputedData>[\"data\"];\n}>;\n\ntype ResultModeMapWithException<\n\tTData,\n\tTResponseType extends ResponseTypeUnion,\n\tTComputedData = GetResponseType<TData, TResponseType>,\n> = {\n\tall: CallApiResultSuccessVariant<TComputedData>;\n\tonlyData: CallApiResultSuccessVariant<TComputedData>[\"data\"];\n};\n\nexport type ResultModeMap<\n\tTData = DefaultDataType,\n\tTErrorData = DefaultDataType,\n\tTResponseType extends ResponseTypeUnion = ResponseTypeUnion,\n\tTThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError,\n> =\n\tTThrowOnError extends true ? ResultModeMapWithException<TData, TResponseType>\n\t:\tResultModeMapWithoutException<TData, TErrorData, TResponseType>;\n\ntype ResultModePlaceholder = null;\n\n// eslint-disable-next-line perfectionist/sort-union-types -- Allow\nexport type ResultModeUnion = keyof ResultModeMap | ResultModePlaceholder;\n\nexport type GetCallApiResult<\n\tTData,\n\tTErrorData,\n\tTResultMode extends ResultModeUnion,\n\tTThrowOnError extends ThrowOnErrorUnion,\n\tTResponseType extends ResponseTypeUnion,\n> =\n\tTErrorData extends false ? ResultModeMapWithException<TData, TResponseType>[\"onlyData\"]\n\t: TErrorData extends false | undefined ? ResultModeMapWithException<TData, TResponseType>[\"onlyData\"]\n\t: ResultModePlaceholder extends TResultMode ?\n\t\tResultModeMap<TData, TErrorData, TResponseType, TThrowOnError>[\"all\"]\n\t: TResultMode extends Exclude<ResultModeUnion, ResultModePlaceholder> ?\n\t\tResultModeMap<TData, TErrorData, TResponseType, TThrowOnError>[TResultMode]\n\t:\tnever;\n\ntype SuccessInfo = {\n\tresponse: Response;\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\n};\n\ntype LazyResultModeMap = {\n\t[key in keyof ResultModeMap]: () => ResultModeMap[key];\n};\n\nconst getResultModeMap = (details: ResultModeMap[\"all\"]): LazyResultModeMap => {\n\treturn {\n\t\tall: () => details,\n\t\tonlyData: () => details.data,\n\t};\n};\n\ntype SuccessResult = CallApiResultSuccessVariant<unknown> | null;\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = (data: unknown, info: SuccessInfo): SuccessResult => {\n\tconst { response, resultMode } = info;\n\n\tconst details = {\n\t\tdata,\n\t\terror: null,\n\t\tresponse,\n\t} satisfies CallApiResultSuccessVariant<unknown>;\n\n\tconst resultModeMap = getResultModeMap(details);\n\n\tconst successResult = resultModeMap[resultMode ?? \"all\"]();\n\n\treturn successResult as SuccessResult;\n};\n\nexport type ErrorInfo = {\n\tcloneResponse: CallApiExtraOptions[\"cloneResponse\"];\n\tmessage?: string;\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\n};\n\ntype ErrorResult = {\n\terrorDetails: CallApiResultErrorVariant<unknown>;\n\tgeneralErrorResult: CallApiResultErrorVariant<unknown> | null;\n};\n\nexport const resolveErrorResult = (error: unknown, info: ErrorInfo): ErrorResult => {\n\tconst { cloneResponse, message: customErrorMessage, resultMode } = info;\n\n\tlet errorDetails = {\n\t\tdata: null,\n\t\terror: {\n\t\t\terrorData: false,\n\t\t\tmessage: customErrorMessage ?? (error as Error).message,\n\t\t\tname: (error as Error).name,\n\t\t\toriginalError: error as Error,\n\t\t},\n\t\tresponse: null,\n\t} satisfies CallApiResultErrorVariant<unknown> as CallApiResultErrorVariant<unknown>;\n\n\tif (isValidationErrorInstance(error)) {\n\t\tconst { errorData, message, response } = error;\n\n\t\terrorDetails = {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\terrorData,\n\t\t\t\tissueCause: error.issueCause,\n\t\t\t\tmessage,\n\t\t\t\tname: \"ValidationError\",\n\t\t\t\toriginalError: error,\n\t\t\t},\n\t\t\tresponse,\n\t\t};\n\t}\n\n\tif (isHTTPErrorInstance<never>(error)) {\n\t\tconst { errorData, message, name, response } = error;\n\n\t\terrorDetails = {\n\t\t\tdata: null,\n\t\t\terror: { errorData, message, name, originalError: error },\n\t\t\tresponse: cloneResponse ? response.clone() : response,\n\t\t};\n\t}\n\n\tconst resultModeMap = getResultModeMap(errorDetails);\n\n\tconst generalErrorResult = resultModeMap[resultMode ?? \"all\"]() as never;\n\n\treturn {\n\t\terrorDetails,\n\t\tgeneralErrorResult,\n\t};\n};\n\nexport const getCustomizedErrorResult = (\n\terrorResult: ErrorResult[\"generalErrorResult\"],\n\tcustomErrorInfo: { message: string | undefined }\n): ErrorResult[\"generalErrorResult\"] => {\n\tif (!errorResult) {\n\t\treturn null;\n\t}\n\n\tconst { message = errorResult.error.message } = customErrorInfo;\n\n\treturn {\n\t\t...errorResult,\n\t\terror: {\n\t\t\t...errorResult.error,\n\t\t\tmessage,\n\t\t} satisfies NonNullable<ErrorResult[\"generalErrorResult\"]>[\"error\"] as never,\n\t};\n};\n","import {\n\ttype CallApiResultErrorVariant,\n\ttype CallApiResultSuccessVariant,\n\ttype ErrorInfo,\n\ttype PossibleHTTPError,\n\ttype PossibleJavaScriptError,\n\ttype PossibleJavaScriptOrValidationError,\n\ttype PossibleValidationError,\n\tresolveErrorResult,\n} from \"./result\";\nimport type { StreamProgressEvent } from \"./stream\";\nimport type {\n\tBaseCallApiExtraOptions,\n\tCallApiExtraOptions,\n\tCallApiExtraOptionsForHooks,\n\tCallApiRequestOptions,\n\tCallApiRequestOptionsForHooks,\n} from \"./types/common\";\nimport type { DefaultDataType } from \"./types/default-types\";\nimport type { AnyFunction, Awaitable, Prettify, UnmaskType } from \"./types/type-helpers\";\n\nexport type PluginExtraOptions<TPluginOptions = unknown> = {\n\t/** Plugin-specific options passed to the plugin configuration */\n\toptions: Partial<TPluginOptions>;\n};\n\n/* eslint-disable perfectionist/sort-intersection-types -- Plugin options should come last */\nexport interface Hooks<TData = DefaultDataType, TErrorData = DefaultDataType, TPluginOptions = unknown> {\n\t/**\n\t * Hook called when any error occurs within the request/response lifecycle.\n\t *\n\t * This is a unified error handler that catches both request errors (network failures,\n\t * timeouts, etc.) and response errors (HTTP error status codes). It's essentially\n\t * a combination of `onRequestError` and `onResponseError` hooks.\n\t *\n\t * @param context - Error context containing error details, request info, and response (if available)\n\t * @returns Promise or void - Hook can be async or sync\n\t */\n\tonError?: (\n\t\tcontext: ErrorContext<TErrorData> & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called just before the HTTP request is sent.\n\t *\n\t * This is the ideal place to modify request headers, add authentication,\n\t * implement request logging, or perform any setup before the network call.\n\t *\n\t * @param context - Request context with mutable request object and configuration\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonRequest?: (context: RequestContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when an error occurs during the fetch request itself.\n\t *\n\t * This handles network-level errors like connection failures, timeouts,\n\t * DNS resolution errors, or other issues that prevent getting an HTTP response.\n\t * Note that HTTP error status codes (4xx, 5xx) are handled by `onResponseError`.\n\t *\n\t * @param context - Request error context with error details and null response\n\t * @returns Promise or void - Hook can be async or sync\n\t */\n\tonRequestError?: (\n\t\tcontext: RequestErrorContext & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called during upload stream progress tracking.\n\t *\n\t * This hook is triggered when uploading data (like file uploads) and provides\n\t * progress information about the upload. Useful for implementing progress bars\n\t * or upload status indicators.\n\t *\n\t * @param context - Request stream context with progress event and request instance\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonRequestStream?: (\n\t\tcontext: RequestStreamContext & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when any HTTP response is received from the API.\n\t *\n\t * This hook is triggered for both successful (2xx) and error (4xx, 5xx) responses.\n\t * It's useful for response logging, metrics collection, or any processing that\n\t * should happen regardless of response status.\n\t *\n\t * @param context - Response context with either success data or error information\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonResponse?: (\n\t\tcontext: ResponseContext<TData, TErrorData> & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when an HTTP error response (4xx, 5xx) is received from the API.\n\t *\n\t * This handles server-side errors where an HTTP response was successfully received\n\t * but indicates an error condition. Different from `onRequestError` which handles\n\t * network-level failures.\n\t *\n\t * @param context - Response error context with HTTP error details and response\n\t * @returns Promise or void - Hook can be async or sync\n\t */\n\tonResponseError?: (\n\t\tcontext: ResponseErrorContext<TErrorData> & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called during download stream progress tracking.\n\t *\n\t * This hook is triggered when downloading data (like file downloads) and provides\n\t * progress information about the download. Useful for implementing progress bars\n\t * or download status indicators.\n\t *\n\t * @param context - Response stream context with progress event and response\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonResponseStream?: (\n\t\tcontext: ResponseStreamContext & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when a request is being retried.\n\t *\n\t * This hook is triggered before each retry attempt, providing information about\n\t * the previous failure and the current retry attempt number. Useful for implementing\n\t * custom retry logic, exponential backoff, or retry logging.\n\t *\n\t * @param context - Retry context with error details and retry attempt count\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonRetry?: (\n\t\tresponse: RetryContext<TErrorData> & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when a successful response (2xx status) is received from the API.\n\t *\n\t * This hook is triggered only for successful responses and provides access to\n\t * the parsed response data. Ideal for success logging, caching, or post-processing\n\t * of successful API responses.\n\t *\n\t * @param context - Success context with parsed response data and response object\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonSuccess?: (context: SuccessContext<TData> & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when a validation error occurs.\n\t *\n\t * This hook is triggered when request or response data fails validation against\n\t * a defined schema. It provides access to the validation error details and can\n\t * be used for custom error handling, logging, or fallback behavior.\n\t *\n\t * @param context - Validation error context with error details and response (if available)\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonValidationError?: (\n\t\tcontext: ValidationErrorContext & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n}\n/* eslint-enable perfectionist/sort-intersection-types -- Plugin options should come last */\n\nexport type HooksOrHooksArray<\n\tTData = DefaultDataType,\n\tTErrorData = DefaultDataType,\n\tTMoreOptions = unknown,\n> = {\n\t[Key in keyof Hooks<TData, TErrorData, TMoreOptions>]:\n\t\t| Hooks<TData, TErrorData, TMoreOptions>[Key]\n\t\t// eslint-disable-next-line perfectionist/sort-union-types -- I need arrays to be last\n\t\t| Array<Hooks<TData, TErrorData, TMoreOptions>[Key]>;\n};\n\nexport interface HookConfigOptions {\n\t/**\n\t * Controls the execution mode of all composed hooks (main + plugin hooks).\n\t *\n\t * - **\"parallel\"**: All hooks execute simultaneously via Promise.all() for better performance\n\t * - **\"sequential\"**: All hooks execute one by one in registration order via await in a loop\n\t *\n\t * This affects how ALL hooks execute together, regardless of their source (main or plugin).\n\t *\n\t * Use `hookRegistrationOrder` to control the registration order of main vs plugin hooks.\n\t *\n\t * @default \"parallel\"\n\t *\n\t * @example\n\t * ```ts\n\t * // Parallel execution (default) - all hooks run simultaneously\n\t * hooksExecutionMode: \"parallel\"\n\t *\n\t * // Sequential execution - hooks run one after another\n\t * hooksExecutionMode: \"sequential\"\n\t *\n\t * // Use case: Hooks have dependencies and must run in order\n\t * const client = callApi.create({\n\t * hooksExecutionMode: \"sequential\",\n\t * hookRegistrationOrder: \"mainFirst\",\n\t * plugins: [transformPlugin],\n\t * onRequest: (ctx) => {\n\t * // This runs first, then transform plugin runs\n\t * ctx.request.headers[\"x-request-id\"] = generateId();\n\t * }\n\t * });\n\t *\n\t * // Use case: Independent operations can run in parallel for speed\n\t * const client = callApi.create({\n\t * hooksExecutionMode: \"parallel\", // Default\n\t * plugins: [metricsPlugin, cachePlugin, loggingPlugin],\n\t * onRequest: (ctx) => {\n\t * // All hooks (main + plugins) run simultaneously\n\t * addRequestTimestamp(ctx.request);\n\t * }\n\t * });\n\t *\n\t * // Use case: Error handling hooks that need sequential processing\n\t * const client = callApi.create({\n\t * hooksExecutionMode: \"sequential\",\n\t * onError: [\n\t * (ctx) => logError(ctx.error), // Log first\n\t * (ctx) => reportError(ctx.error), // Then report\n\t * (ctx) => cleanupResources(ctx) // Finally cleanup\n\t * ]\n\t * });\n\t * ```\n\t */\n\thooksExecutionMode?: \"parallel\" | \"sequential\";\n\n\t/**\n\t * Controls the registration order of main hooks relative to plugin hooks.\n\t *\n\t * - **\"pluginsFirst\"**: Plugin hooks register first, then main hooks (default)\n\t * - **\"mainFirst\"**: Main hooks register first, then plugin hooks\n\t *\n\t * This determines the order hooks are added to the registry, which affects\n\t * their execution sequence when using sequential execution mode.\n\t *\n\t * @default \"pluginsFirst\"\n\t *\n\t * @example\n\t * ```ts\n\t * // Plugin hooks register first (default behavior)\n\t * hookRegistrationOrder: \"pluginsFirst\"\n\t *\n\t * // Main hooks register first\n\t * hookRegistrationOrder: \"mainFirst\"\n\t *\n\t * // Use case: Main validation before plugin processing\n\t * const client = callApi.create({\n\t * hookRegistrationOrder: \"mainFirst\",\n\t * hooksExecutionMode: \"sequential\",\n\t * plugins: [transformPlugin],\n\t * onRequest: (ctx) => {\n\t * // This main hook runs first in sequential mode\n\t * if (!ctx.request.headers.authorization) {\n\t * throw new Error(\"Authorization required\");\n\t * }\n\t * }\n\t * });\n\t *\n\t * // Use case: Plugin setup before main logic (default)\n\t * const client = callApi.create({\n\t * hookRegistrationOrder: \"pluginsFirst\", // Default\n\t * hooksExecutionMode: \"sequential\",\n\t * plugins: [setupPlugin],\n\t * onRequest: (ctx) => {\n\t * // Plugin runs first, then this main hook\n\t * console.log(\"Request prepared:\", ctx.request.url);\n\t * }\n\t * });\n\t *\n\t * // Use case: Parallel mode (registration order less important)\n\t * const client = callApi.create({\n\t * hookRegistrationOrder: \"pluginsFirst\",\n\t * hooksExecutionMode: \"parallel\", // All run simultaneously\n\t * plugins: [metricsPlugin, cachePlugin],\n\t * onRequest: (ctx) => {\n\t * // All hooks run in parallel regardless of registration order\n\t * addRequestId(ctx.request);\n\t * }\n\t * });\n\t * ```\n\t */\n\thooksRegistrationOrder?: \"mainFirst\" | \"pluginsFirst\";\n}\n\nexport type RequestContext = {\n\t/**\n\t * Base configuration object passed to createFetchClient.\n\t *\n\t * Contains the foundational configuration that applies to all requests\n\t * made by this client instance, such as baseURL, default headers, and\n\t * global options.\n\t */\n\tbaseConfig: BaseCallApiExtraOptions & CallApiRequestOptions;\n\n\t/**\n\t * Instance-specific configuration object passed to the callApi instance.\n\t *\n\t * Contains configuration specific to this particular API call, which\n\t * can override or extend the base configuration.\n\t */\n\tconfig: CallApiExtraOptions & CallApiRequestOptions;\n\n\t/**\n\t * Merged options combining base config, instance config, and default options.\n\t *\n\t * This is the final resolved configuration that will be used for the request,\n\t * with proper precedence applied (instance > base > defaults).\n\t */\n\toptions: CallApiExtraOptionsForHooks;\n\n\t/**\n\t * Merged request object ready to be sent.\n\t *\n\t * Contains the final request configuration including URL, method, headers,\n\t * body, and other fetch options. This object can be modified in onRequest\n\t * hooks to customize the outgoing request.\n\t */\n\trequest: CallApiRequestOptionsForHooks;\n};\n\nexport type ValidationErrorContext = UnmaskType<\n\tRequestContext & {\n\t\t/** Validation error containing details about what failed validation */\n\t\terror: PossibleValidationError;\n\t\t/** HTTP response object if validation failed on response, null if on request */\n\t\tresponse: Response | null;\n\t}\n>;\n\nexport type SuccessContext<TData> = UnmaskType<\n\tRequestContext & {\n\t\t/** Parsed response data with the expected success type */\n\t\tdata: TData;\n\t\t/** HTTP response object for the successful request */\n\t\tresponse: Response;\n\t}\n>;\n\nexport type ResponseContext<TData, TErrorData> = UnmaskType<\n\tRequestContext\n\t\t& (\n\t\t\t| Prettify<CallApiResultSuccessVariant<TData>>\n\t\t\t| Prettify<\n\t\t\t\t\tExtract<CallApiResultErrorVariant<TErrorData>, { error: PossibleHTTPError<TErrorData> }>\n\t\t\t >\n\t\t)\n>;\n\nexport type RequestErrorContext = RequestContext & {\n\t/** Error that occurred during the request (network, timeout, etc.) */\n\terror: PossibleJavaScriptError;\n\t/** Always null for request errors since no response was received */\n\tresponse: null;\n};\n\nexport type ErrorContext<TErrorData> = UnmaskType<\n\tRequestContext\n\t\t& (\n\t\t\t| {\n\t\t\t\t\t/** HTTP error with response data */\n\t\t\t\t\terror: PossibleHTTPError<TErrorData>;\n\t\t\t\t\t/** HTTP response object containing error status */\n\t\t\t\t\tresponse: Response;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\t/** Request-level error (network, timeout, validation, etc.) */\n\t\t\t\t\terror: PossibleJavaScriptOrValidationError;\n\t\t\t\t\t/** Response object if available, null for request errors */\n\t\t\t\t\tresponse: Response | null;\n\t\t\t }\n\t\t)\n>;\n\nexport type ResponseErrorContext<TErrorData> = UnmaskType<\n\tExtract<ErrorContext<TErrorData>, { error: PossibleHTTPError<TErrorData> }> & RequestContext\n>;\n\nexport type RetryContext<TErrorData> = UnmaskType<\n\tErrorContext<TErrorData> & {\n\t\t/** Current retry attempt number (1-based, so 1 = first retry) */\n\t\tretryAttemptCount: number;\n\t}\n>;\n\nexport type RequestStreamContext = UnmaskType<\n\tRequestContext & {\n\t\t/** Progress event containing loaded/total bytes information */\n\t\tevent: StreamProgressEvent;\n\t\t/** The actual Request instance being uploaded */\n\t\trequestInstance: Request;\n\t}\n>;\n\nexport type ResponseStreamContext = UnmaskType<\n\tRequestContext & {\n\t\t/** Progress event containing loaded/total bytes information */\n\t\tevent: StreamProgressEvent;\n\t\t/** HTTP response object being downloaded */\n\t\tresponse: Response;\n\t}\n>;\n\ntype HookRegistries = Required<{\n\t[Key in keyof Hooks]: Set<Hooks[Key]>;\n}>;\n\nexport const getHookRegistries = (): HookRegistries => {\n\treturn {\n\t\tonError: new Set(),\n\t\tonRequest: new Set(),\n\t\tonRequestError: new Set(),\n\t\tonRequestStream: new Set(),\n\t\tonResponse: new Set(),\n\t\tonResponseError: new Set(),\n\t\tonResponseStream: new Set(),\n\t\tonRetry: new Set(),\n\t\tonSuccess: new Set(),\n\t\tonValidationError: new Set(),\n\t};\n};\n\nexport const composeAllHooks = (\n\thooksArray: Array<AnyFunction | undefined>,\n\thooksExecutionMode: CallApiExtraOptionsForHooks[\"hooksExecutionMode\"]\n) => {\n\tconst mergedHook = async (ctx: unknown) => {\n\t\tswitch (hooksExecutionMode) {\n\t\t\tcase \"parallel\": {\n\t\t\t\tawait Promise.all(hooksArray.map((uniqueHook) => uniqueHook?.(ctx)));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"sequential\": {\n\t\t\t\tfor (const hook of hooksArray) {\n\t\t\t\t\t// eslint-disable-next-line no-await-in-loop -- This is necessary in this case\n\t\t\t\t\tawait hook?.(ctx);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\thooksExecutionMode satisfies undefined;\n\t\t\t}\n\t\t}\n\t};\n\n\treturn mergedHook;\n};\n\nexport const executeHooksInTryBlock = async (...hookResultsOrPromise: Array<Awaitable<unknown>>) => {\n\tawait Promise.all(hookResultsOrPromise);\n};\n\nexport type ExecuteHookInfo = {\n\terrorInfo: ErrorInfo;\n\tshouldThrowOnError: boolean | undefined;\n};\n\nexport const executeHooksInCatchBlock = async (\n\thookResultsOrPromise: Array<Awaitable<unknown>>,\n\thookInfo: ExecuteHookInfo\n) => {\n\tconst { errorInfo, shouldThrowOnError } = hookInfo;\n\n\ttry {\n\t\tawait Promise.all(hookResultsOrPromise);\n\n\t\treturn null;\n\t} catch (hookError) {\n\t\tconst { generalErrorResult: hookErrorResult } = resolveErrorResult(hookError, errorInfo);\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow hookError;\n\t\t}\n\n\t\treturn hookErrorResult;\n\t}\n};\n","import {\n\texecuteHooksInTryBlock,\n\ttype RequestContext,\n\ttype RequestStreamContext,\n\ttype ResponseStreamContext,\n} from \"./hooks\";\nimport { isObject, isReadableStream } from \"./utils/guards\";\n\nexport type StreamProgressEvent = {\n\t/**\n\t * Current chunk of data being streamed\n\t */\n\tchunk: Uint8Array;\n\t/**\n\t * Progress in percentage\n\t */\n\tprogress: number;\n\t/**\n\t * Total size of data in bytes\n\t */\n\ttotalBytes: number;\n\t/**\n\t * Amount of data transferred so far\n\t */\n\ttransferredBytes: number;\n};\n\ndeclare global {\n\tinterface ReadableStream<R> {\n\t\t[Symbol.asyncIterator]: () => AsyncIterableIterator<R>;\n\t}\n}\n\nconst createProgressEvent = (options: {\n\tchunk: Uint8Array;\n\ttotalBytes: number;\n\ttransferredBytes: number;\n}): StreamProgressEvent => {\n\tconst { chunk, totalBytes, transferredBytes } = options;\n\n\treturn {\n\t\tchunk,\n\t\tprogress: Math.round((transferredBytes / totalBytes) * 100) || 0,\n\t\ttotalBytes,\n\t\ttransferredBytes,\n\t};\n};\n\nconst calculateTotalBytesFromBody = async (\n\trequestBody: Request[\"body\"] | null,\n\texistingTotalBytes: number\n) => {\n\tlet totalBytes = existingTotalBytes;\n\n\tif (!requestBody) {\n\t\treturn totalBytes;\n\t}\n\n\tfor await (const chunk of requestBody) {\n\t\ttotalBytes += chunk.byteLength;\n\t}\n\n\treturn totalBytes;\n};\n\ntype ToStreamableRequestContext = RequestContext;\n\nexport const toStreamableRequest = async (\n\tcontext: ToStreamableRequestContext\n): Promise<Request | RequestInit> => {\n\tconst { baseConfig, config, options, request } = context;\n\n\tif (!options.onRequestStream || !isReadableStream(request.body)) {\n\t\treturn request as RequestInit;\n\t}\n\n\tconst requestInstance = new Request(\n\t\toptions.fullURL as NonNullable<typeof options.fullURL>,\n\t\t{ ...request, duplex: \"half\" } as RequestInit\n\t);\n\n\tconst contentLength = requestInstance.headers.get(\"content-length\");\n\n\tlet totalBytes = Number(contentLength ?? 0);\n\n\tconst shouldForcefullyCalcStreamSize =\n\t\tisObject(options.forcefullyCalculateStreamSize) ?\n\t\t\toptions.forcefullyCalculateStreamSize.request\n\t\t:\toptions.forcefullyCalculateStreamSize;\n\n\t// == If no content length is present, we read the total bytes from the body\n\tif (!contentLength && shouldForcefullyCalcStreamSize) {\n\t\ttotalBytes = await calculateTotalBytesFromBody(requestInstance.clone().body, totalBytes);\n\t}\n\n\tlet transferredBytes = 0;\n\n\tconst stream = new ReadableStream({\n\t\tstart: async (controller) => {\n\t\t\tconst body = requestInstance.body;\n\n\t\t\tif (!body) return;\n\n\t\t\tconst requestStreamContext = {\n\t\t\t\tbaseConfig,\n\t\t\t\tconfig,\n\t\t\t\tevent: createProgressEvent({ chunk: new Uint8Array(), totalBytes, transferredBytes }),\n\t\t\t\toptions,\n\t\t\t\trequest,\n\t\t\t\trequestInstance,\n\t\t\t} satisfies RequestStreamContext;\n\n\t\t\tawait executeHooksInTryBlock(options.onRequestStream?.(requestStreamContext));\n\n\t\t\tfor await (const chunk of body) {\n\t\t\t\ttransferredBytes += chunk.byteLength;\n\n\t\t\t\ttotalBytes = Math.max(totalBytes, transferredBytes);\n\n\t\t\t\tawait executeHooksInTryBlock(\n\t\t\t\t\toptions.onRequestStream?.({\n\t\t\t\t\t\t...requestStreamContext,\n\t\t\t\t\t\tevent: createProgressEvent({ chunk, totalBytes, transferredBytes }),\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tcontroller.enqueue(chunk);\n\t\t\t}\n\n\t\t\tcontroller.close();\n\t\t},\n\t});\n\n\treturn new Request(requestInstance, { body: stream, duplex: \"half\" } as RequestInit);\n};\n\ntype StreamableResponseContext = RequestContext & { response: Response };\n\nexport const toStreamableResponse = async (context: StreamableResponseContext): Promise<Response> => {\n\tconst { baseConfig, config, options, request, response } = context;\n\n\tif (!options.onResponseStream || !response.body) {\n\t\treturn response;\n\t}\n\n\tconst contentLength = response.headers.get(\"content-length\");\n\n\tlet totalBytes = Number(contentLength ?? 0);\n\n\tconst shouldForceContentLengthCalc =\n\t\tisObject(options.forcefullyCalculateStreamSize) ?\n\t\t\toptions.forcefullyCalculateStreamSize.response\n\t\t:\toptions.forcefullyCalculateStreamSize;\n\n\t// == If no content length is present and `forceContentLengthCalculation` is enabled, we read the total bytes from the body\n\tif (!contentLength && shouldForceContentLengthCalc) {\n\t\ttotalBytes = await calculateTotalBytesFromBody(response.clone().body, totalBytes);\n\t}\n\n\tlet transferredBytes = 0;\n\n\tconst stream = new ReadableStream({\n\t\tstart: async (controller) => {\n\t\t\tconst body = response.body;\n\n\t\t\tif (!body) return;\n\n\t\t\tconst responseStreamContext = {\n\t\t\t\tbaseConfig,\n\t\t\t\tconfig,\n\t\t\t\tevent: createProgressEvent({ chunk: new Uint8Array(), totalBytes, transferredBytes }),\n\t\t\t\toptions,\n\t\t\t\trequest,\n\t\t\t\tresponse,\n\t\t\t} satisfies ResponseStreamContext;\n\n\t\t\tawait executeHooksInTryBlock(options.onResponseStream?.(responseStreamContext));\n\n\t\t\tfor await (const chunk of body) {\n\t\t\t\ttransferredBytes += chunk.byteLength;\n\n\t\t\t\ttotalBytes = Math.max(totalBytes, transferredBytes);\n\n\t\t\t\tawait executeHooksInTryBlock(\n\t\t\t\t\toptions.onResponseStream?.({\n\t\t\t\t\t\t...responseStreamContext,\n\t\t\t\t\t\tevent: createProgressEvent({ chunk, totalBytes, transferredBytes }),\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tcontroller.enqueue(chunk);\n\t\t\t}\n\n\t\t\tcontroller.close();\n\t\t},\n\t});\n\n\treturn new Response(stream, response);\n};\n","import { extraOptionDefaults } from \"./constants/default-options\";\nimport type { RequestContext } from \"./hooks\";\nimport { toStreamableRequest, toStreamableResponse } from \"./stream\";\nimport type { AnyString, UnmaskType } from \"./types/type-helpers\";\nimport { deterministicHashFn, getFetchImpl, waitFor } from \"./utils/common\";\nimport { isFunction } from \"./utils/guards\";\n\ntype RequestInfo = {\n\tcontroller: AbortController;\n\tresponsePromise: Promise<Response>;\n};\n\n/**\n * Cache that stores active request information for deduplication within a specific scope.\n *\n * Maps deduplication keys to their corresponding request information, including the abort controller\n * and response promise. A `null` key represents requests that don't participate in deduplication.\n *\n * **Internal Usage:**\n * This type is primarily used internally by the deduplication system. You typically won't need to\n * interact with it directly unless you're building custom deduplication logic or debugging.\n *\n * @example\n * ```ts\n * // This is handled internally, but conceptually:\n * const cache: RequestInfoCache = new Map([\n * [\"user-123\", { controller: abortController, responsePromise: fetchPromise }],\n * [\"config\", { controller: abortController2, responsePromise: fetchPromise2 }],\n * ]);\n * ```\n */\nexport type RequestInfoCache = Map<string | null, RequestInfo>;\n\n/**\n * Global cache that manages multiple request info caches, organized by scope keys.\n *\n * This enables the global deduplication feature by maintaining separate cache namespaces\n * for different scope keys. Each scope key gets its own `RequestInfoCache` instance.\n *\n * **Cache Lifecycle:**\n * - Caches are created on-demand when first accessed\n * - Automatic cleanup occurs when no references remain\n * - Each scope key maintains independent deduplication state\n *\n * **Memory Considerations:**\n * - Each scope key creates a separate cache instance\n * - Consider the number of different scope keys in your application\n * - Caches are cleaned up automatically when clients are garbage collected\n *\n * @example\n * ```ts\n * // This is managed internally, but conceptually:\n * const globalCache: GlobalRequestInfoCache = new Map([\n * [\"user-service\", new Map([...])], // Cache for user service requests\n * [\"analytics\", new Map([...])], // Cache for analytics requests\n * [\"default\", new Map([...])] // Default cache scope\n * ]);\n * ```\n */\nexport type GlobalRequestInfoCache = Map<DedupeOptions[\"dedupeCacheScopeKey\"], RequestInfoCache>;\n\ntype DedupeContext = RequestContext & {\n\t$GlobalRequestInfoCache: GlobalRequestInfoCache;\n\t$LocalRequestInfoCache: RequestInfoCache;\n\tnewFetchController: AbortController;\n};\n\nexport const createDedupeStrategy = async (context: DedupeContext) => {\n\tconst {\n\t\t$GlobalRequestInfoCache,\n\t\t$LocalRequestInfoCache,\n\t\tbaseConfig,\n\t\tconfig,\n\t\tnewFetchController,\n\t\toptions: globalOptions,\n\t\trequest: globalRequest,\n\t} = context;\n\n\tconst dedupeStrategy = globalOptions.dedupeStrategy ?? extraOptionDefaults().dedupeStrategy;\n\n\tconst resolvedDedupeStrategy = isFunction(dedupeStrategy) ? dedupeStrategy(context) : dedupeStrategy;\n\n\tconst getDedupeKey = () => {\n\t\tconst shouldHaveDedupeKey =\n\t\t\tresolvedDedupeStrategy === \"cancel\" || resolvedDedupeStrategy === \"defer\";\n\n\t\tif (!shouldHaveDedupeKey) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (globalOptions.dedupeKey) {\n\t\t\tconst resolvedDedupeKey =\n\t\t\t\tisFunction(globalOptions.dedupeKey) ?\n\t\t\t\t\tglobalOptions.dedupeKey(context)\n\t\t\t\t:\tglobalOptions.dedupeKey;\n\n\t\t\treturn resolvedDedupeKey;\n\t\t}\n\n\t\treturn `${globalOptions.fullURL}-${deterministicHashFn({ options: globalOptions, request: globalRequest })}`;\n\t};\n\n\tconst dedupeKey = getDedupeKey();\n\n\tconst dedupeCacheScope = globalOptions.dedupeCacheScope ?? extraOptionDefaults().dedupeCacheScope;\n\n\tconst dedupeCacheScopeKey =\n\t\tglobalOptions.dedupeCacheScopeKey ?? extraOptionDefaults().dedupeCacheScopeKey;\n\n\tif (dedupeCacheScope === \"global\" && !$GlobalRequestInfoCache.has(dedupeCacheScopeKey)) {\n\t\t$GlobalRequestInfoCache.set(dedupeCacheScopeKey, new Map());\n\t}\n\n\tconst $RequestInfoCache =\n\t\tdedupeCacheScope === \"global\" ?\n\t\t\t$GlobalRequestInfoCache.get(dedupeCacheScopeKey)\n\t\t:\t$LocalRequestInfoCache;\n\n\t// == This is to ensure cache operations only occur when key is available\n\tconst $RequestInfoCacheOrNull = dedupeKey !== null ? $RequestInfoCache : null;\n\n\t/******\n\t * == Add a small delay to the execution to ensure proper request deduplication when multiple requests with the same key start simultaneously.\n\t * == This gives time for the cache to be updated with the previous request info before the next request checks it.\n\t ******/\n\tif (dedupeKey !== null) {\n\t\tawait waitFor(0.1);\n\t}\n\n\tconst prevRequestInfo = $RequestInfoCacheOrNull?.get(dedupeKey);\n\n\tconst getAbortErrorMessage = () => {\n\t\tif (globalOptions.dedupeKey) {\n\t\t\treturn `Duplicate request detected - Aborted previous request with key '${dedupeKey}' as a new request was initiated`;\n\t\t}\n\n\t\treturn `Duplicate request detected - Aborted previous request to '${globalOptions.fullURL}' as a new request with identical options was initiated`;\n\t};\n\n\tconst handleRequestCancelStrategy = () => {\n\t\tconst shouldCancelRequest = prevRequestInfo && resolvedDedupeStrategy === \"cancel\";\n\n\t\tif (!shouldCancelRequest) return;\n\n\t\tconst message = getAbortErrorMessage();\n\n\t\tconst reason = new DOMException(message, \"AbortError\");\n\n\t\tprevRequestInfo.controller.abort(reason);\n\n\t\t// == Adding this just so that eslint forces me put await when calling the function (it looks better that way tbh)\n\t\treturn Promise.resolve();\n\t};\n\n\tconst handleRequestDeferStrategy = async (deferContext: {\n\t\toptions: DedupeContext[\"options\"];\n\t\trequest: DedupeContext[\"request\"];\n\t}) => {\n\t\t// == Local options and request are needed so that transformations are applied can be applied to both from call site\n\t\tconst { options: localOptions, request: localRequest } = deferContext;\n\n\t\tconst fetchApi = getFetchImpl(localOptions.customFetchImpl);\n\n\t\tconst shouldUsePromiseFromCache = prevRequestInfo && resolvedDedupeStrategy === \"defer\";\n\n\t\tconst streamableContext = {\n\t\t\tbaseConfig,\n\t\t\tconfig,\n\t\t\toptions: localOptions,\n\t\t\trequest: localRequest,\n\t\t} satisfies RequestContext;\n\n\t\tconst streamableRequest = await toStreamableRequest(streamableContext);\n\n\t\tconst responsePromise =\n\t\t\tshouldUsePromiseFromCache ?\n\t\t\t\tprevRequestInfo.responsePromise\n\t\t\t:\tfetchApi(localOptions.fullURL as NonNullable<typeof localOptions.fullURL>, streamableRequest);\n\n\t\t$RequestInfoCacheOrNull?.set(dedupeKey, { controller: newFetchController, responsePromise });\n\n\t\tconst streamableResponse = toStreamableResponse({\n\t\t\t...streamableContext,\n\t\t\tresponse: await responsePromise,\n\t\t});\n\n\t\treturn streamableResponse;\n\t};\n\n\tconst removeDedupeKeyFromCache = () => {\n\t\t$RequestInfoCacheOrNull?.delete(dedupeKey);\n\t};\n\n\treturn {\n\t\tgetAbortErrorMessage,\n\t\thandleRequestCancelStrategy,\n\t\thandleRequestDeferStrategy,\n\t\tremoveDedupeKeyFromCache,\n\t\tresolvedDedupeStrategy,\n\t};\n};\n\ntype DedupeStrategyUnion = UnmaskType<\"cancel\" | \"defer\" | \"none\">;\n\nexport type DedupeOptions = {\n\t/**\n\t * Controls the scope of request deduplication caching.\n\t *\n\t * - `\"global\"`: Shares deduplication cache across all `createFetchClient` instances with the same `dedupeCacheScopeKey`.\n\t * Useful for applications with multiple API clients that should share deduplication state.\n\t * - `\"local\"`: Limits deduplication to requests within the same `createFetchClient` instance.\n\t * Provides better isolation and is recommended for most use cases.\n\t *\n\t *\n\t * **Real-world Scenarios:**\n\t * - Use `\"global\"` when you have multiple API clients (user service, auth service, etc.) that might make overlapping requests\n\t * - Use `\"local\"` (default) for single-purpose clients or when you want strict isolation between different parts of your app\n\t *\n\t * @example\n\t * ```ts\n\t * // Local scope - each client has its own deduplication cache\n\t * const userClient = createFetchClient({ baseURL: \"/api/users\" });\n\t * const postClient = createFetchClient({ baseURL: \"/api/posts\" });\n\t * // These clients won't share deduplication state\n\t *\n\t * // Global scope - share cache across related clients\n\t * const userClient = createFetchClient({\n\t * baseURL: \"/api/users\",\n\t * dedupeCacheScope: \"global\",\n\t * });\n\t * const postClient = createFetchClient({\n\t * baseURL: \"/api/posts\",\n\t * dedupeCacheScope: \"global\",\n\t * });\n\t * // These clients will share deduplication state\n\t * ```\n\t *\n\t * @default \"local\"\n\t */\n\tdedupeCacheScope?: \"global\" | \"local\";\n\n\t/**\n\t * Unique namespace for the global deduplication cache when using `dedupeCacheScope: \"global\"`.\n\t *\n\t * This creates logical groupings of deduplication caches. All instances with the same key\n\t * will share the same cache namespace, allowing fine-grained control over which clients\n\t * share deduplication state.\n\t *\n\t * **Best Practices:**\n\t * - Use descriptive names that reflect the logical grouping (e.g., \"user-service\", \"analytics-api\")\n\t * - Keep scope keys consistent across related API clients\n\t * - Consider using different scope keys for different environments (dev, staging, prod)\n\t * - Avoid overly broad scope keys that might cause unintended cache sharing\n\t *\n\t * **Cache Management:**\n\t * - Each scope key maintains its own independent cache\n\t * - Caches are automatically cleaned up when no references remain\n\t * - Consider the memory implications of multiple global scopes\n\t *\n\t * @example\n\t * ```ts\n\t * // Group related API clients together\n\t * const userClient = createFetchClient({\n\t * baseURL: \"/api/users\",\n\t * dedupeCacheScope: \"global\",\n\t * dedupeCacheScopeKey: \"user-service\"\n\t * });\n\t * const profileClient = createFetchClient({\n\t * baseURL: \"/api/profiles\",\n\t * dedupeCacheScope: \"global\",\n\t * dedupeCacheScopeKey: \"user-service\" // Same scope - will share cache\n\t * });\n\t *\n\t * // Separate analytics client with its own cache\n\t * const analyticsClient = createFetchClient({\n\t * baseURL: \"/api/analytics\",\n\t * dedupeCacheScope: \"global\",\n\t * dedupeCacheScopeKey: \"analytics-service\" // Different scope\n\t * });\n\t *\n\t * // Environment-specific scoping\n\t * const apiClient = createFetchClient({\n\t * dedupeCacheScope: \"global\",\n\t * dedupeCacheScopeKey: `api-${process.env.NODE_ENV}` // \"api-development\", \"api-production\", etc.\n\t * });\n\t * ```\n\t *\n\t * @default \"default\"\n\t */\n\tdedupeCacheScopeKey?: \"default\" | AnyString;\n\n\t/**\n\t * Custom key generator for request deduplication.\n\t *\n\t * Override the default key generation strategy to control exactly which requests\n\t * are considered duplicates. The default key combines URL, method, body, and\n\t * relevant headers (excluding volatile ones like 'Date', 'Authorization', etc.).\n\t *\n\t * **Default Key Generation:**\n\t * The auto-generated key includes:\n\t * - Full request URL (including query parameters)\n\t * - HTTP method (GET, POST, etc.)\n\t * - Request body (for POST/PUT/PATCH requests)\n\t * - Stable headers (excludes Date, Authorization, User-Agent, etc.)\n\t *\n\t * **Custom Key Best Practices:**\n\t * - Include only the parts of the request that should affect deduplication\n\t * - Avoid including volatile data (timestamps, random IDs, etc.)\n\t * - Consider performance - simpler keys are faster to compute and compare\n\t * - Ensure keys are deterministic for the same logical request\n\t * - Use consistent key formats across your application\n\t *\n\t * **Performance Considerations:**\n\t * - Function-based keys are computed on every request - keep them lightweight\n\t * - String keys are fastest but least flexible\n\t * - Consider caching expensive key computations if needed\n\t *\n\t * @example\n\t * ```ts\n\t * import { callApi } from \"@zayne-labs/callapi\";\n\t *\n\t * // Simple static key - useful for singleton requests\n\t * const config = callApi(\"/api/config\", {\n\t * dedupeKey: \"app-config\",\n\t * dedupeStrategy: \"defer\" // Share the same config across all requests\n\t * });\n\t *\n\t * // URL and method only - ignore headers and body\n\t * const userData = callApi(\"/api/user/123\", {\n\t * dedupeKey: (context) => `${context.options.method}:${context.options.fullURL}`\n\t * });\n\t *\n\t * // Include specific headers in deduplication\n\t * const apiCall = callApi(\"/api/data\", {\n\t * dedupeKey: (context) => {\n\t * const authHeader = context.request.headers.get(\"Authorization\");\n\t * return `${context.options.fullURL}-${authHeader}`;\n\t * }\n\t * });\n\t *\n\t * // User-specific deduplication\n\t * const userSpecificCall = callApi(\"/api/dashboard\", {\n\t * dedupeKey: (context) => {\n\t * const userId = context.options.fullURL.match(/user\\/(\\d+)/)?.[1];\n\t * return `dashboard-${userId}`;\n\t * }\n\t * });\n\t *\n\t * // Ignore certain query parameters\n\t * const searchCall = callApi(\"/api/search?q=test&timestamp=123456\", {\n\t * dedupeKey: (context) => {\n\t * const url = new URL(context.options.fullURL);\n\t * url.searchParams.delete(\"timestamp\"); // Remove volatile param\n\t * return `search:${url.toString()}`;\n\t * }\n\t * });\n\t * ```\n\t *\n\t * @default Auto-generated from request details\n\t */\n\tdedupeKey?: string | ((context: RequestContext) => string);\n\n\t/**\n\t * Strategy for handling duplicate requests. Can be a static string or callback function.\n\t *\n\t * **Available Strategies:**\n\t * - `\"cancel\"`: Cancel previous request when new one starts (good for search)\n\t * - `\"defer\"`: Share response between duplicate requests (good for config loading)\n\t * - `\"none\"`: No deduplication, all requests execute independently\n\t *\n\t * @example\n\t * ```ts\n\t * // Static strategies\n\t * const searchClient = createFetchClient({\n\t * dedupeStrategy: \"cancel\" // Cancel previous searches\n\t * });\n\t *\n\t * const configClient = createFetchClient({\n\t * dedupeStrategy: \"defer\" // Share config across components\n\t * });\n\t *\n\t * // Dynamic strategy based on request\n\t * const smartClient = createFetchClient({\n\t * dedupeStrategy: (context) => {\n\t * return context.options.method === \"GET\" ? \"defer\" : \"cancel\";\n\t * }\n\t * });\n\t *\n\t * // Search-as-you-type with cancel strategy\n\t * const handleSearch = async (query: string) => {\n\t * try {\n\t * const { data } = await callApi(\"/api/search\", {\n\t * method: \"POST\",\n\t * body: { query },\n\t * dedupeStrategy: \"cancel\",\n\t * dedupeKey: \"search\" // Cancel previous searches, only latest one goes through\n\t * });\n\t *\n\t * updateSearchResults(data);\n\t * } catch (error) {\n\t * if (error.name === \"AbortError\") {\n\t * // Previous search cancelled - (expected behavior)\n\t * return;\n\t * }\n\t * console.error(\"Search failed:\", error);\n\t * }\n\t * };\n\t *\n\t * ```\n\t *\n\t * @default \"cancel\"\n\t */\n\tdedupeStrategy?: DedupeStrategyUnion | ((context: RequestContext) => DedupeStrategyUnion);\n};\n","import { ValidationError } from \"./error\";\nimport type {\n\tBaseCallApiExtraOptions,\n\tBody,\n\tCallApiExtraOptions,\n\tCallApiRequestOptions,\n\tGlobalMeta,\n\tHeadersOption,\n\tMethodUnion,\n} from \"./types\";\nimport type { StandardSchemaV1 } from \"./types/standard-schema\";\nimport {\n\ttype AnyFunction,\n\ttype AnyString,\n\ttype Awaitable,\n\tdefineEnum,\n\ttype Prettify,\n\ttype UnionToIntersection,\n} from \"./types/type-helpers\";\nimport type { Params, Query } from \"./url\";\nimport { toArray } from \"./utils/common\";\nimport { isFunction } from \"./utils/guards\";\n\ntype InferSchemaInput<TSchema extends CallApiSchema[keyof CallApiSchema]> =\n\tTSchema extends StandardSchemaV1 ? StandardSchemaV1.InferInput<TSchema> : never;\n\nexport type InferSchemaOutputResult<TSchema, TFallbackResult = unknown> =\n\t// == Checking for undefined first and returning fallback to avoid type errors when passing the config around (weird tbh)\n\tundefined extends TSchema ? TFallbackResult\n\t: TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema>\n\t: TSchema extends AnyFunction<infer TResult> ? Awaited<TResult>\n\t: TFallbackResult;\n\nexport type InferSchemaInputResult<TSchema, TFallbackResult = unknown> =\n\t// == Checking for undefined first and returning fallback to avoid type errors when passing the config around (weird tbh)\n\tundefined extends TSchema ? TFallbackResult\n\t: TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferInput<TSchema>\n\t: TSchema extends AnyFunction<infer TResult> ? Awaited<TResult>\n\t: TFallbackResult;\n\nconst handleValidatorFunction = async <TInput>(\n\tvalidator: Extract<CallApiSchema[keyof CallApiSchema], AnyFunction>,\n\tinputData: TInput\n): Promise<StandardSchemaV1.Result<TInput>> => {\n\ttry {\n\t\tconst result = await validator(inputData as never);\n\n\t\treturn { issues: undefined, value: result as never };\n\t} catch (error) {\n\t\treturn { issues: toArray(error) as never, value: undefined };\n\t}\n};\n\nexport const standardSchemaParser = async <\n\tTFullSchema extends CallApiSchema,\n\tTSchemaName extends keyof CallApiSchema,\n\tTSchema extends NonNullable<TFullSchema[TSchemaName]>,\n>(\n\tfullSchema: TFullSchema | undefined,\n\tschemaName: TSchemaName,\n\tinputData: InferSchemaInput<TSchema>,\n\tresponse?: Response | null\n): Promise<InferSchemaOutputResult<TSchema>> => {\n\tconst schema = fullSchema?.[schemaName];\n\n\tif (!schema) {\n\t\treturn inputData as never;\n\t}\n\n\tconst result =\n\t\tisFunction(schema) ?\n\t\t\tawait handleValidatorFunction(schema, inputData)\n\t\t:\tawait schema[\"~standard\"].validate(inputData);\n\n\t// == If the `issues` field exists, it means the validation failed\n\n\tif (result.issues) {\n\t\tthrow new ValidationError({\n\t\t\tissueCause: schemaName,\n\t\t\tissues: result.issues,\n\t\t\tresponse: response ?? null,\n\t\t});\n\t}\n\n\treturn result.value as never;\n};\n\nexport interface CallApiSchemaConfig {\n\t/**\n\t * The base url of the schema. By default it's the baseURL of the callApi instance.\n\t */\n\tbaseURL?: string;\n\n\t/**\n\t * Disables runtime validation for the schema.\n\t */\n\tdisableRuntimeValidation?: boolean;\n\n\t/**\n\t * If `true`, the original input value will be used instead of the transformed/validated output.\n\t *\n\t * This is useful when you want to validate the input but don't want any transformations\n\t * applied by the validation schema (e.g., type coercion, default values, etc).\n\t */\n\tdisableValidationOutputApplication?: boolean;\n\n\t/**\n\t * Optional url prefix that will be substituted for the `baseURL` of the schemaConfig at runtime.\n\t *\n\t * This allows you to reuse the same schema against different base URLs (for example,\n\t * swapping between `/api/v1` and `/api/v2`) without redefining the entire schema.\n\t */\n\tprefix?: string;\n\n\t/**\n\t * Controls the strictness of API route validation.\n\t *\n\t * When true:\n\t * - Only routes explicitly defined in the schema will be considered valid to typescript and the runtime.\n\t * - Attempting to call routes not defined in the schema will result in both type errors and runtime validation errors.\n\t * - Useful for ensuring API calls conform exactly to your schema definition\n\t *\n\t * When false or undefined (default):\n\t * - All routes will be allowed, whether they are defined in the schema or not\n\t */\n\tstrict?: boolean;\n}\n\nexport interface CallApiSchema {\n\t/**\n\t * The schema to use for validating the request body.\n\t */\n\tbody?: StandardSchemaV1<Body> | ((body: Body) => Awaitable<Body>);\n\n\t/**\n\t * The schema to use for validating the response data.\n\t */\n\tdata?: StandardSchemaV1 | ((data: unknown) => unknown);\n\n\t/**\n\t * The schema to use for validating the response error data.\n\t */\n\terrorData?: StandardSchemaV1 | ((errorData: unknown) => unknown);\n\n\t/**\n\t * The schema to use for validating the request headers.\n\t */\n\theaders?:\n\t\t| StandardSchemaV1<HeadersOption | undefined>\n\t\t| ((headers: HeadersOption) => Awaitable<HeadersOption | undefined>);\n\n\t/**\n\t * The schema to use for validating the meta option.\n\t */\n\tmeta?:\n\t\t| StandardSchemaV1<GlobalMeta | undefined>\n\t\t| ((meta: GlobalMeta) => Awaitable<GlobalMeta | undefined>);\n\n\t/**\n\t * The schema to use for validating the request method.\n\t */\n\tmethod?:\n\t\t| StandardSchemaV1<MethodUnion | undefined>\n\t\t| ((method: MethodUnion) => Awaitable<MethodUnion | undefined>);\n\n\t/**\n\t * The schema to use for validating the request url parameters.\n\t */\n\tparams?: StandardSchemaV1<Params | undefined> | ((params: Params) => Awaitable<Params | undefined>);\n\n\t/**\n\t * The schema to use for validating the request url queries.\n\t */\n\tquery?: StandardSchemaV1<Query | undefined> | ((query: Query) => Awaitable<Query | undefined>);\n}\n\nexport const routeKeyMethods = defineEnum([\"delete\", \"get\", \"patch\", \"post\", \"put\"]);\n\nexport type RouteKeyMethods = (typeof routeKeyMethods)[number];\n\nexport type RouteKeyMethodsURLUnion = `@${RouteKeyMethods}/`;\n\nexport type BaseCallApiSchemaRoutes = Partial<Record<AnyString | RouteKeyMethodsURLUnion, CallApiSchema>>;\n\nexport type BaseCallApiSchemaAndConfig = {\n\tconfig?: CallApiSchemaConfig;\n\troutes: BaseCallApiSchemaRoutes;\n};\n\ntype ValidationOptions<\n\tTSchema extends CallApiSchema[keyof CallApiSchema] = CallApiSchema[keyof CallApiSchema],\n> = {\n\tinputValue: InferSchemaInput<TSchema>;\n\tresponse?: Response | null;\n\tschemaConfig: CallApiSchemaConfig | undefined;\n};\n\nexport const handleSchemaValidation = async <\n\tTFullSchema extends CallApiSchema,\n\tTSchemaName extends keyof CallApiSchema,\n\tTSchema extends NonNullable<TFullSchema[TSchemaName]>,\n>(\n\tfullSchema: TFullSchema | undefined,\n\tschemaName: TSchemaName,\n\tvalidationOptions: ValidationOptions<TSchema>\n): Promise<InferSchemaOutputResult<TSchema>> => {\n\tconst { inputValue, response, schemaConfig } = validationOptions;\n\n\tif (schemaConfig?.disableRuntimeValidation) {\n\t\treturn inputValue as never;\n\t}\n\n\tconst validResult = await standardSchemaParser(fullSchema, schemaName, inputValue, response);\n\n\treturn validResult as never;\n};\n\ntype LastOf<TValue> =\n\tUnionToIntersection<TValue extends unknown ? () => TValue : never> extends () => infer R ? R : never;\n\ntype Push<TArray extends unknown[], TArrayItem> = [...TArray, TArrayItem];\n\ntype UnionToTuple<\n\tTUnion,\n\tTComputedLastUnion = LastOf<TUnion>,\n\tTComputedIsUnionEqualToNever = [TUnion] extends [never] ? true : false,\n> =\n\ttrue extends TComputedIsUnionEqualToNever ? []\n\t:\tPush<UnionToTuple<Exclude<TUnion, TComputedLastUnion>>, TComputedLastUnion>;\n\nexport type Tuple<TTuple, TArray extends TTuple[] = []> =\n\tUnionToTuple<TTuple>[\"length\"] extends TArray[\"length\"] ? [...TArray]\n\t:\tTuple<TTuple, [TTuple, ...TArray]>;\n\nconst extraOptionsToBeValidated = [\"meta\", \"params\", \"query\"] satisfies Tuple<\n\tExtract<keyof CallApiSchema, keyof CallApiExtraOptions>\n>;\n\ntype ExtraOptionsValidationOptions = {\n\toptions: CallApiExtraOptions;\n\tschema: CallApiSchema | undefined;\n\tschemaConfig: CallApiSchemaConfig | undefined;\n};\n\nconst handleExtraOptionsValidation = async (validationOptions: ExtraOptionsValidationOptions) => {\n\tconst { options, schema, schemaConfig } = validationOptions;\n\n\tconst validationResultArray = await Promise.all(\n\t\textraOptionsToBeValidated.map((schemaName) =>\n\t\t\thandleSchemaValidation(schema, schemaName, {\n\t\t\t\tinputValue: options[schemaName],\n\t\t\t\tschemaConfig,\n\t\t\t})\n\t\t)\n\t);\n\n\tconst validatedResultObject: Prettify<\n\t\tPick<CallApiExtraOptions, (typeof extraOptionsToBeValidated)[number]>\n\t> = {};\n\n\tfor (const [index, schemaName] of extraOptionsToBeValidated.entries()) {\n\t\tconst validationResult = validationResultArray[index];\n\n\t\tif (validationResult === undefined) continue;\n\n\t\tvalidatedResultObject[schemaName] = validationResult as never;\n\t}\n\n\treturn validatedResultObject;\n};\n\nconst requestOptionsToBeValidated = [\"body\", \"headers\", \"method\"] satisfies Tuple<\n\tExtract<keyof CallApiSchema, keyof CallApiRequestOptions>\n>;\n\ntype RequestOptionsValidationOptions = {\n\trequestOptions: CallApiRequestOptions;\n\tschema: CallApiSchema | undefined;\n\tschemaConfig: CallApiSchemaConfig | undefined;\n};\n\nconst handleRequestOptionsValidation = async (validationOptions: RequestOptionsValidationOptions) => {\n\tconst { requestOptions, schema, schemaConfig } = validationOptions;\n\n\tconst validationResultArray = await Promise.all(\n\t\trequestOptionsToBeValidated.map((schemaName) =>\n\t\t\thandleSchemaValidation(schema, schemaName, {\n\t\t\t\tinputValue: requestOptions[schemaName],\n\t\t\t\tschemaConfig,\n\t\t\t})\n\t\t)\n\t);\n\n\tconst validatedResultObject: Prettify<\n\t\tPick<CallApiRequestOptions, (typeof requestOptionsToBeValidated)[number]>\n\t> = {};\n\n\tfor (const [index, propertyKey] of requestOptionsToBeValidated.entries()) {\n\t\tconst validationResult = validationResultArray[index];\n\n\t\tif (validationResult === undefined) continue;\n\n\t\tvalidatedResultObject[propertyKey] = validationResult as never;\n\t}\n\n\treturn validatedResultObject;\n};\n\nexport const handleConfigValidation = async (\n\tvalidationOptions: GetResolvedSchemaContext\n\t\t& Omit<ExtraOptionsValidationOptions & RequestOptionsValidationOptions, \"schema\" | \"schemaConfig\">\n) => {\n\tconst { baseExtraOptions, currentRouteSchemaKey, extraOptions, options, requestOptions } =\n\t\tvalidationOptions;\n\n\tconst { currentRouteSchema, resolvedSchema } = getResolvedSchema({\n\t\tbaseExtraOptions,\n\t\tcurrentRouteSchemaKey,\n\t\textraOptions,\n\t});\n\n\tconst resolvedSchemaConfig = getResolvedSchemaConfig({ baseExtraOptions, extraOptions });\n\n\tif (resolvedSchemaConfig?.strict === true && !currentRouteSchema) {\n\t\tthrow new ValidationError({\n\t\t\tissueCause: \"schemaConfig-(strict)\",\n\t\t\tissues: [{ message: `Strict Mode - No schema found for route '${currentRouteSchemaKey}' ` }],\n\t\t\tresponse: null,\n\t\t});\n\t}\n\n\tif (resolvedSchemaConfig?.disableRuntimeValidation) {\n\t\treturn {\n\t\t\textraOptionsValidationResult: null,\n\t\t\trequestOptionsValidationResult: null,\n\t\t\tresolvedSchema,\n\t\t\tresolvedSchemaConfig,\n\t\t\tshouldApplySchemaOutput: false,\n\t\t};\n\t}\n\n\tconst [extraOptionsValidationResult, requestOptionsValidationResult] = await Promise.all([\n\t\thandleExtraOptionsValidation({\n\t\t\toptions,\n\t\t\tschema: resolvedSchema,\n\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t}),\n\t\thandleRequestOptionsValidation({\n\t\t\trequestOptions,\n\t\t\tschema: resolvedSchema,\n\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t}),\n\t]);\n\n\tconst shouldApplySchemaOutput =\n\t\t(Boolean(extraOptionsValidationResult) || Boolean(requestOptionsValidationResult))\n\t\t&& !resolvedSchemaConfig?.disableValidationOutputApplication;\n\n\treturn {\n\t\textraOptionsValidationResult,\n\t\trequestOptionsValidationResult,\n\t\tresolvedSchema,\n\t\tresolvedSchemaConfig,\n\t\tshouldApplySchemaOutput,\n\t};\n};\n\ntype GetResolvedSchemaContext = {\n\tbaseExtraOptions: BaseCallApiExtraOptions;\n\tcurrentRouteSchemaKey: string;\n\textraOptions: CallApiExtraOptions;\n};\n\nexport const fallBackRouteSchemaKey = \".\";\n\nexport type FallBackRouteSchemaKey = typeof fallBackRouteSchemaKey;\n\nexport const getResolvedSchema = (context: GetResolvedSchemaContext) => {\n\tconst { baseExtraOptions, currentRouteSchemaKey, extraOptions } = context;\n\n\tconst fallbackRouteSchema = baseExtraOptions.schema?.routes[fallBackRouteSchemaKey];\n\tconst currentRouteSchema = baseExtraOptions.schema?.routes[currentRouteSchemaKey];\n\n\tconst resolvedRouteSchema = {\n\t\t...fallbackRouteSchema,\n\t\t// == Current route schema takes precedence over fallback route schema\n\t\t...currentRouteSchema,\n\t} satisfies CallApiSchema as CallApiSchema | undefined;\n\n\tconst resolvedSchema =\n\t\tisFunction(extraOptions.schema) ?\n\t\t\textraOptions.schema({\n\t\t\t\tbaseSchemaRoutes: baseExtraOptions.schema?.routes ?? {},\n\t\t\t\tcurrentRouteSchema: resolvedRouteSchema ?? {},\n\t\t\t})\n\t\t:\t(extraOptions.schema ?? resolvedRouteSchema);\n\n\treturn { currentRouteSchema, resolvedSchema };\n};\n\nexport const getResolvedSchemaConfig = (\n\tcontext: Omit<GetResolvedSchemaContext, \"currentRouteSchemaKey\">\n) => {\n\tconst { baseExtraOptions, extraOptions } = context;\n\n\tconst resolvedSchemaConfig =\n\t\tisFunction(extraOptions.schemaConfig) ?\n\t\t\textraOptions.schemaConfig({ baseSchemaConfig: baseExtraOptions.schema?.config ?? {} })\n\t\t:\t(extraOptions.schemaConfig ?? baseExtraOptions.schema?.config);\n\n\treturn resolvedSchemaConfig;\n};\n\nexport const getCurrentRouteSchemaKeyAndMainInitURL = (\n\tcontext: Pick<GetResolvedSchemaContext, \"baseExtraOptions\" | \"extraOptions\"> & { initURL: string }\n) => {\n\tconst { baseExtraOptions, extraOptions, initURL } = context;\n\n\tconst schemaConfig = getResolvedSchemaConfig({ baseExtraOptions, extraOptions });\n\n\tlet currentRouteSchemaKey = initURL;\n\tlet mainInitURL = initURL;\n\n\tif (schemaConfig?.prefix && currentRouteSchemaKey.startsWith(schemaConfig.prefix)) {\n\t\tcurrentRouteSchemaKey = currentRouteSchemaKey.replace(schemaConfig.prefix, \"\");\n\n\t\tmainInitURL = mainInitURL.replace(schemaConfig.prefix, schemaConfig.baseURL ?? \"\");\n\t}\n\n\tif (schemaConfig?.baseURL && currentRouteSchemaKey.startsWith(schemaConfig.baseURL)) {\n\t\tcurrentRouteSchemaKey = currentRouteSchemaKey.replace(schemaConfig.baseURL, \"\");\n\t}\n\n\treturn { currentRouteSchemaKey, mainInitURL };\n};\n","import { extraOptionDefaults } from \"./constants/default-options\";\nimport {\n\tcomposeAllHooks,\n\tgetHookRegistries,\n\ttype Hooks,\n\ttype HooksOrHooksArray,\n\ttype PluginExtraOptions,\n\ttype RequestContext,\n} from \"./hooks\";\nimport type { CallApiRequestOptions, CallApiRequestOptionsForHooks } from \"./types/common\";\nimport type { Awaitable } from \"./types/type-helpers\";\nimport type { InitURLOrURLObject } from \"./url\";\nimport { isArray, isFunction, isPlainObject, isString } from \"./utils/guards\";\nimport { type BaseCallApiSchemaAndConfig, getCurrentRouteSchemaKeyAndMainInitURL } from \"./validation\";\n\nexport type PluginSetupContext<TPluginExtraOptions = unknown> = RequestContext // eslint-disable-next-line perfectionist/sort-intersection-types -- Allow\n\t& PluginExtraOptions<TPluginExtraOptions> & { initURL: string };\n\nexport type PluginInitResult = Partial<\n\tOmit<PluginSetupContext, \"initURL\" | \"request\"> & {\n\t\tinitURL: InitURLOrURLObject;\n\t\trequest: CallApiRequestOptions;\n\t}\n>;\n\nexport type PluginHooksWithMoreOptions<TMoreOptions = unknown> = HooksOrHooksArray<\n\tnever,\n\tnever,\n\tTMoreOptions\n>;\n\nexport type PluginHooks<TData = never, TErrorData = never, TMoreOptions = unknown> = HooksOrHooksArray<\n\tTData,\n\tTErrorData,\n\tTMoreOptions\n>;\n\nexport interface CallApiPlugin {\n\t/**\n\t * Defines additional options that can be passed to callApi\n\t */\n\tdefineExtraOptions?: (...params: never[]) => unknown;\n\n\t/**\n\t * A description for the plugin\n\t */\n\tdescription?: string;\n\n\t/**\n\t * Hooks / Interceptors for the plugin\n\t */\n\thooks?: PluginHooks;\n\n\t/**\n\t * A unique id for the plugin\n\t */\n\tid: string;\n\n\t/**\n\t * A name for the plugin\n\t */\n\tname: string;\n\n\t/**\n\t * Base schema for the client.\n\t */\n\tschema?: BaseCallApiSchemaAndConfig;\n\n\t/**\n\t * A function that will be called when the plugin is initialized. This will be called before the any of the other internal functions.\n\t */\n\tsetup?: (context: PluginSetupContext) => Awaitable<PluginInitResult> | Awaitable<void>;\n\n\t/**\n\t * A version for the plugin\n\t */\n\tversion?: string;\n}\n\nexport const getResolvedPlugins = (context: Pick<RequestContext, \"baseConfig\" | \"options\">) => {\n\tconst { baseConfig, options } = context;\n\n\tconst resolvedPlugins =\n\t\tisFunction(options.plugins) ?\n\t\t\toptions.plugins({ basePlugins: baseConfig.plugins ?? [] })\n\t\t:\t(options.plugins ?? []);\n\n\treturn resolvedPlugins;\n};\n\nexport const initializePlugins = async (context: PluginSetupContext) => {\n\tconst { baseConfig, config, initURL, options, request } = context;\n\n\tconst hookRegistries = getHookRegistries();\n\n\tconst hookRegistryKeyArray = Object.keys(hookRegistries) as Array<keyof Hooks>;\n\n\tconst addMainHooks = () => {\n\t\tfor (const key of hookRegistryKeyArray) {\n\t\t\tconst overriddenHook = options[key];\n\t\t\tconst baseHook = baseConfig[key];\n\t\t\tconst instanceHook = config[key];\n\n\t\t\t// == If the base hook is an array and instance hook is defined, we need to compose the base hook with the instance hook\n\t\t\tconst mainHook =\n\t\t\t\tisArray(baseHook) && Boolean(instanceHook) ? [baseHook, instanceHook].flat() : overriddenHook;\n\n\t\t\tif (!mainHook) continue;\n\n\t\t\thookRegistries[key].add(mainHook as never);\n\t\t}\n\t};\n\n\tconst addPluginHooks = (pluginHooks: Required<CallApiPlugin>[\"hooks\"]) => {\n\t\tfor (const key of hookRegistryKeyArray) {\n\t\t\tconst pluginHook = pluginHooks[key];\n\n\t\t\tif (!pluginHook) continue;\n\n\t\t\thookRegistries[key].add(pluginHook as never);\n\t\t}\n\t};\n\n\tconst hookRegistrationOrder =\n\t\toptions.hooksRegistrationOrder ?? extraOptionDefaults().hooksRegistrationOrder;\n\n\tif (hookRegistrationOrder === \"mainFirst\") {\n\t\taddMainHooks();\n\t}\n\n\tconst { currentRouteSchemaKey, mainInitURL } = getCurrentRouteSchemaKeyAndMainInitURL({\n\t\tbaseExtraOptions: baseConfig,\n\t\textraOptions: config,\n\t\tinitURL,\n\t});\n\n\tlet resolvedCurrentRouteSchemaKey = currentRouteSchemaKey;\n\tlet resolvedInitURL = mainInitURL;\n\tlet resolvedOptions = options;\n\tlet resolvedRequestOptions = request;\n\n\tconst executePluginSetupFn = async (pluginSetupFn: CallApiPlugin[\"setup\"]) => {\n\t\tif (!pluginSetupFn) return;\n\n\t\tconst initResult = await pluginSetupFn({\n\t\t\tbaseConfig,\n\t\t\tconfig,\n\t\t\tinitURL,\n\t\t\toptions,\n\t\t\trequest,\n\t\t});\n\n\t\tif (!isPlainObject(initResult)) return;\n\n\t\tconst urlString = initResult.initURL?.toString();\n\n\t\tif (isString(urlString)) {\n\t\t\tconst newResult = getCurrentRouteSchemaKeyAndMainInitURL({\n\t\t\t\tbaseExtraOptions: baseConfig,\n\t\t\t\textraOptions: config,\n\t\t\t\tinitURL: urlString,\n\t\t\t});\n\n\t\t\tresolvedCurrentRouteSchemaKey = newResult.currentRouteSchemaKey;\n\t\t\tresolvedInitURL = newResult.mainInitURL;\n\t\t}\n\n\t\tif (isPlainObject(initResult.request)) {\n\t\t\tresolvedRequestOptions = initResult.request as CallApiRequestOptionsForHooks;\n\t\t}\n\n\t\tif (isPlainObject(initResult.options)) {\n\t\t\tresolvedOptions = initResult.options;\n\t\t}\n\t};\n\n\tconst resolvedPlugins = getResolvedPlugins({ baseConfig, options });\n\n\tfor (const plugin of resolvedPlugins) {\n\t\t// eslint-disable-next-line no-await-in-loop -- Await is necessary in this case.\n\t\tawait executePluginSetupFn(plugin.setup);\n\n\t\tif (!plugin.hooks) continue;\n\n\t\taddPluginHooks(plugin.hooks);\n\t}\n\n\tif (hookRegistrationOrder === \"pluginsFirst\") {\n\t\taddMainHooks();\n\t}\n\n\tconst resolvedHooks: Hooks = {};\n\n\tfor (const [key, hookRegistry] of Object.entries(hookRegistries)) {\n\t\tif (hookRegistry.size === 0) continue;\n\n\t\t// == Flatten the hook registry to remove any nested arrays, incase an array of hooks is passed to any of the hooks\n\t\tconst flattenedHookArray = [...hookRegistry].flat();\n\n\t\tif (flattenedHookArray.length === 0) continue;\n\n\t\tconst hooksExecutionMode = options.hooksExecutionMode ?? extraOptionDefaults().hooksExecutionMode;\n\n\t\tconst composedHook = composeAllHooks(flattenedHookArray, hooksExecutionMode);\n\n\t\tresolvedHooks[key as keyof Hooks] = composedHook;\n\t}\n\n\treturn {\n\t\tresolvedCurrentRouteSchemaKey,\n\t\tresolvedHooks,\n\t\tresolvedInitURL,\n\t\tresolvedOptions,\n\t\tresolvedRequestOptions,\n\t};\n};\n","import { extraOptionDefaults } from \"./constants/default-options\";\nimport type { ErrorContext, RequestContext } from \"./hooks\";\nimport type { MethodUnion } from \"./types\";\nimport { type AnyNumber, type Awaitable, defineEnum, type UnmaskType } from \"./types/type-helpers\";\nimport { isBoolean, isFunction, isString } from \"./utils/guards\";\n\n// eslint-disable-next-line ts-eslint/no-unused-vars -- Ignore\nconst defaultRetryStatusCodesLookup = () =>\n\tdefineEnum({\n\t\t408: \"Request Timeout\",\n\t\t409: \"Conflict\",\n\t\t425: \"Too Early\",\n\t\t429: \"Too Many Requests\",\n\t\t500: \"Internal Server Error\",\n\t\t502: \"Bad Gateway\",\n\t\t503: \"Service Unavailable\",\n\t\t504: \"Gateway Timeout\",\n\t});\n\ntype RetryStatusCodes = UnmaskType<AnyNumber | keyof ReturnType<typeof defaultRetryStatusCodesLookup>>;\n\ntype RetryCondition<TErrorData> = (context: ErrorContext<TErrorData>) => Awaitable<boolean>;\n\ntype InnerRetryKeys<TErrorData> = Exclude<keyof RetryOptions<TErrorData>, \"~retryAttemptCount\" | \"retry\">;\n\ntype InnerRetryOptions<TErrorData> = {\n\t[Key in InnerRetryKeys<TErrorData> as Key extends `retry${infer TRest}` ?\n\t\tUncapitalize<TRest> extends \"attempts\" ?\n\t\t\tnever\n\t\t:\tUncapitalize<TRest>\n\t:\tKey]?: RetryOptions<TErrorData>[Key];\n} & {\n\tattempts: NonNullable<RetryOptions<TErrorData>[\"retryAttempts\"]>;\n};\n\nexport interface RetryOptions<TErrorData> {\n\t/**\n\t * Keeps track of the number of times the request has already been retried\n\t *\n\t * @deprecated **NOTE**: This property is used internally to track retries. Please abstain from modifying it.\n\t */\n\treadonly [\"~retryAttemptCount\"]?: number;\n\n\t/**\n\t * All retry options in a single object instead of separate properties\n\t */\n\tretry?: InnerRetryOptions<TErrorData>;\n\n\t/**\n\t * Number of allowed retry attempts on HTTP errors\n\t * @default 0\n\t */\n\tretryAttempts?: number;\n\n\t/**\n\t * Callback whose return value determines if a request should be retried or not\n\t */\n\tretryCondition?: RetryCondition<TErrorData>;\n\n\t/**\n\t * Delay between retries in milliseconds\n\t * @default 1000\n\t */\n\tretryDelay?: number | ((currentAttemptCount: number) => number);\n\n\t/**\n\t * Maximum delay in milliseconds. Only applies to exponential strategy\n\t * @default 10000\n\t */\n\tretryMaxDelay?: number;\n\n\t/**\n\t * HTTP methods that are allowed to retry\n\t * @default [\"GET\", \"POST\"]\n\t */\n\tretryMethods?: MethodUnion[];\n\n\t/**\n\t * HTTP status codes that trigger a retry\n\t */\n\tretryStatusCodes?: RetryStatusCodes[];\n\n\t/**\n\t * Strategy to use when retrying\n\t * @default \"linear\"\n\t */\n\tretryStrategy?: \"exponential\" | \"linear\";\n}\n\nconst getLinearDelay = (currentAttemptCount: number, options: RetryOptions<unknown>) => {\n\tconst retryDelay = options.retryDelay ?? options.retry?.delay;\n\n\tconst resolveRetryDelay =\n\t\t(isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay)\n\t\t?? extraOptionDefaults().retryDelay;\n\n\treturn resolveRetryDelay;\n};\n\nconst getExponentialDelay = (currentAttemptCount: number, options: RetryOptions<unknown>) => {\n\tconst retryDelay = options.retryDelay ?? options.retry?.delay ?? extraOptionDefaults().retryDelay;\n\n\tconst resolvedRetryDelay = isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay;\n\n\tconst maxDelay =\n\t\toptions.retryMaxDelay ?? options.retry?.maxDelay ?? extraOptionDefaults().retryMaxDelay;\n\n\tconst exponentialDelay = resolvedRetryDelay * 2 ** currentAttemptCount;\n\n\treturn Math.min(exponentialDelay, maxDelay);\n};\n\nexport const createRetryStrategy = (ctx: ErrorContext<unknown> & RequestContext) => {\n\tconst { options, request } = ctx;\n\n\t// eslint-disable-next-line ts-eslint/no-deprecated -- Allowed for internal use\n\tconst currentAttemptCount = options[\"~retryAttemptCount\"] ?? 1;\n\n\tconst retryStrategy =\n\t\toptions.retryStrategy ?? options.retry?.strategy ?? extraOptionDefaults().retryStrategy;\n\n\tconst getDelay = () => {\n\t\tswitch (retryStrategy) {\n\t\t\tcase \"exponential\": {\n\t\t\t\treturn getExponentialDelay(currentAttemptCount, options);\n\t\t\t}\n\t\t\tcase \"linear\": {\n\t\t\t\treturn getLinearDelay(currentAttemptCount, options);\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow new Error(`Invalid retry strategy: ${String(retryStrategy)}`);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst shouldAttemptRetry = async () => {\n\t\tif (isBoolean(request.signal) && request.signal.aborted) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst retryCondition =\n\t\t\toptions.retryCondition ?? options.retry?.condition ?? extraOptionDefaults().retryCondition;\n\n\t\tconst maximumRetryAttempts =\n\t\t\toptions.retryAttempts ?? options.retry?.attempts ?? extraOptionDefaults().retryAttempts;\n\n\t\tconst customRetryCondition = await retryCondition(ctx);\n\n\t\tconst baseShouldRetry = currentAttemptCount <= maximumRetryAttempts && customRetryCondition;\n\n\t\tif (!baseShouldRetry) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst retryMethods = new Set(\n\t\t\toptions.retryMethods ?? options.retry?.methods ?? extraOptionDefaults().retryMethods\n\t\t);\n\n\t\tconst includesMethod =\n\t\t\tisString(ctx.request.method) && retryMethods.size > 0 ?\n\t\t\t\tretryMethods.has(ctx.request.method)\n\t\t\t:\ttrue;\n\n\t\tconst retryStatusCodes = new Set(\n\t\t\toptions.retryStatusCodes ?? options.retry?.statusCodes ?? extraOptionDefaults().retryStatusCodes\n\t\t);\n\n\t\tconst includesStatusCodes =\n\t\t\tBoolean(ctx.response) && retryStatusCodes.size > 0 ?\n\t\t\t\tretryStatusCodes.has(ctx.response.status)\n\t\t\t:\ttrue;\n\n\t\tconst shouldRetry = includesMethod && includesStatusCodes;\n\n\t\treturn shouldRetry;\n\t};\n\n\treturn {\n\t\tcurrentAttemptCount,\n\t\tgetDelay,\n\t\tshouldAttemptRetry,\n\t};\n};\n","import { requestOptionDefaults } from \"./constants/default-options\";\nimport type { CallApiExtraOptions, CallApiRequestOptions } from \"./types/common\";\nimport type { AnyString, UnmaskType } from \"./types/type-helpers\";\nimport { toQueryString } from \"./utils\";\nimport { isArray } from \"./utils/guards\";\nimport { type CallApiSchemaConfig, type RouteKeyMethodsURLUnion, routeKeyMethods } from \"./validation\";\n\nconst slash = \"/\";\nconst colon = \":\";\nconst openBrace = \"{\";\nconst closeBrace = \"}\";\n\nconst mergeUrlWithParams = (url: string, params: CallApiExtraOptions[\"params\"]) => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tlet newUrl = url;\n\n\tif (isArray(params)) {\n\t\tconst urlParts = newUrl.split(slash);\n\n\t\t// == Find all parameters in order (both :param and {param} patterns)\n\t\tconst matchedParamsArray = urlParts.filter(\n\t\t\t(part) => part.startsWith(colon) || (part.startsWith(openBrace) && part.endsWith(closeBrace))\n\t\t);\n\n\t\tfor (const [paramIndex, matchedParam] of matchedParamsArray.entries()) {\n\t\t\tconst stringParamValue = String(params[paramIndex]);\n\t\t\tnewUrl = newUrl.replace(matchedParam, stringParamValue);\n\t\t}\n\n\t\treturn newUrl;\n\t}\n\n\t// == Handle object params - replace both :param and {param} patterns\n\tfor (const [paramKey, paramValue] of Object.entries(params)) {\n\t\tconst colonPattern = `${colon}${paramKey}` as const;\n\t\tconst bracePattern = `${openBrace}${paramKey}${closeBrace}` as const;\n\t\tconst stringValue = String(paramValue);\n\n\t\tnewUrl = newUrl.replace(colonPattern, stringValue);\n\t\tnewUrl = newUrl.replace(bracePattern, stringValue);\n\t}\n\n\treturn newUrl;\n};\n\nconst questionMark = \"?\";\nconst ampersand = \"&\";\nconst mergeUrlWithQuery = (url: string, query: CallApiExtraOptions[\"query\"]): string => {\n\tif (!query) {\n\t\treturn url;\n\t}\n\n\tconst queryString = toQueryString(query);\n\n\tif (queryString?.length === 0) {\n\t\treturn url;\n\t}\n\n\tif (url.endsWith(questionMark)) {\n\t\treturn `${url}${queryString}`;\n\t}\n\n\tif (url.includes(questionMark)) {\n\t\treturn `${url}${ampersand}${queryString}`;\n\t}\n\n\treturn `${url}${questionMark}${queryString}`;\n};\n\n/**\n * @description Extracts the HTTP method from method-prefixed route patterns.\n *\n * Analyzes URLs that start with method modifiers (e.g., \"@get/\", \"@post/\") and extracts\n * the HTTP method for use in API requests. This enables method specification directly\n * in route definitions.\n *\n * @param initURL - The URL string to analyze for method modifiers\n * @returns The extracted HTTP method (lowercase) if found, otherwise undefined\n *\n * @example\n * ```typescript\n * // Method extraction from prefixed routes\n * extractMethodFromURL(\"@get/users\"); // Returns: \"get\"\n * extractMethodFromURL(\"@post/users\"); // Returns: \"post\"\n * extractMethodFromURL(\"@put/users/:id\"); // Returns: \"put\"\n * extractMethodFromURL(\"@delete/users/:id\"); // Returns: \"delete\"\n * extractMethodFromURL(\"@patch/users/:id\"); // Returns: \"patch\"\n *\n * // No method modifier\n * extractMethodFromURL(\"/users\"); // Returns: undefined\n * extractMethodFromURL(\"users\"); // Returns: undefined\n *\n * // Invalid or unsupported methods\n * extractMethodFromURL(\"@invalid/users\"); // Returns: undefined\n * extractMethodFromURL(\"@/users\"); // Returns: undefined\n *\n * // Edge cases\n * extractMethodFromURL(undefined); // Returns: undefined\n * extractMethodFromURL(\"\"); // Returns: undefined\n * ```\n */\nexport const extractMethodFromURL = (initURL: string | undefined) => {\n\tif (!initURL?.startsWith(\"@\")) return;\n\n\tconst method = initURL.split(\"@\")[1]?.split(\"/\")[0];\n\n\tif (!method || !routeKeyMethods.includes(method)) return;\n\n\treturn method;\n};\n\nexport type GetMethodContext = {\n\t/** The URL string that may contain method modifiers like \"@get/\" or \"@post/\" */\n\tinitURL: string | undefined;\n\t/** Explicitly specified HTTP method */\n\tmethod: CallApiRequestOptions[\"method\"];\n\t/** Schema configuration that affects method resolution behavior */\n\tschemaConfig?: CallApiSchemaConfig;\n};\n\nexport const getMethod = (ctx: GetMethodContext) => {\n\tconst { initURL, method } = ctx;\n\n\treturn (\n\t\tmethod?.toUpperCase()\n\t\t?? extractMethodFromURL(initURL)?.toUpperCase()\n\t\t?? requestOptionDefaults().method\n\t);\n};\n\nconst normalizeURL = (initURL: string) => {\n\tconst methodFromURL = extractMethodFromURL(initURL);\n\n\tif (!methodFromURL) {\n\t\treturn initURL;\n\t}\n\n\tconst normalizedURL = initURL.replace(`@${methodFromURL}/`, \"/\");\n\n\treturn normalizedURL;\n};\n\ntype GetFullURLOptions = {\n\t/** Base URL to prepend to relative URLs */\n\tbaseURL: string | undefined;\n\t/** Initial URL pattern that may contain parameters and method modifiers */\n\tinitURL: string;\n\t/** Parameters to substitute into the URL path */\n\tparams: CallApiExtraOptions[\"params\"];\n\t/** Query parameters to append to the URL */\n\tquery: CallApiExtraOptions[\"query\"];\n};\n\nexport const getFullAndNormalizedURL = (options: GetFullURLOptions) => {\n\tconst { baseURL, initURL, params, query } = options;\n\n\tconst normalizedInitURL = normalizeURL(initURL);\n\n\tconst urlWithMergedParams = mergeUrlWithParams(normalizedInitURL, params);\n\n\tconst urlWithMergedQueryAndParams = mergeUrlWithQuery(urlWithMergedParams, query);\n\n\tconst shouldPrependBaseURL = !urlWithMergedQueryAndParams.startsWith(\"http\") && baseURL;\n\n\tconst fullURL =\n\t\tshouldPrependBaseURL ? `${baseURL}${urlWithMergedQueryAndParams}` : urlWithMergedQueryAndParams;\n\n\treturn {\n\t\tfullURL,\n\t\tnormalizedInitURL,\n\t};\n};\n\nexport type AllowedQueryParamValues = UnmaskType<boolean | number | string>;\n\nexport type RecordStyleParams = UnmaskType<Record<string, AllowedQueryParamValues>>;\n\nexport type TupleStyleParams = UnmaskType<AllowedQueryParamValues[]>;\n\nexport type Params = UnmaskType<RecordStyleParams | TupleStyleParams>;\n\nexport type Query = UnmaskType<Record<string, AllowedQueryParamValues>>;\n\nexport type InitURLOrURLObject = AnyString | RouteKeyMethodsURLUnion | URL;\n\nexport interface URLOptions {\n\t/**\n\t * Base URL for all API requests. Will only be prepended to relative URLs.\n\t *\n\t * Absolute URLs (starting with http/https) will not be prepended by the baseURL.\n\t *\n\t * @example\n\t * ```ts\n\t * // Set base URL for all requests\n\t * baseURL: \"https://api.example.com/v1\"\n\t *\n\t * // Then use relative URLs in requests\n\t * callApi(\"/users\") // → https://api.example.com/v1/users\n\t * callApi(\"/posts/123\") // → https://api.example.com/v1/posts/123\n\t *\n\t * // Environment-specific base URLs\n\t * baseURL: process.env.NODE_ENV === \"production\"\n\t * ? \"https://api.example.com\"\n\t * : \"http://localhost:3000/api\"\n\t * ```\n\t */\n\tbaseURL?: string;\n\n\t/**\n\t * Resolved request URL after processing baseURL, parameters, and query strings (readonly)\n\t *\n\t * This is the final URL that will be used for the HTTP request, computed from\n\t * baseURL, initURL, params, and query parameters.\n\t *\n\t */\n\treadonly fullURL?: string;\n\n\t/**\n\t * The original URL string passed to the callApi instance (readonly)\n\t *\n\t * This preserves the original URL as provided, including any method modifiers like \"@get/\" or \"@post/\".\n\t *\n\t */\n\treadonly initURL?: string;\n\n\t/**\n\t * The URL string after normalization, with method modifiers removed(readonly)\n\t *\n\t * Method modifiers like \"@get/\", \"@post/\" are stripped to create a clean URL\n\t * for parameter substitution and final URL construction.\n\t *\n\t */\n\treadonly initURLNormalized?: string;\n\n\t/**\n\t * Parameters to be substituted into URL path segments.\n\t *\n\t * Supports both object-style (named parameters) and array-style (positional parameters)\n\t * for flexible URL parameter substitution.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Object-style parameters (recommended)\n\t * const namedParams: URLOptions = {\n\t * initURL: \"/users/:userId/posts/:postId\",\n\t * params: { userId: \"123\", postId: \"456\" }\n\t * };\n\t * // Results in: /users/123/posts/456\n\t *\n\t * // Array-style parameters (positional)\n\t * const positionalParams: URLOptions = {\n\t * initURL: \"/users/:userId/posts/:postId\",\n\t * params: [\"123\", \"456\"] // Maps in order: userId=123, postId=456\n\t * };\n\t * // Results in: /users/123/posts/456\n\t *\n\t * // Single parameter\n\t * const singleParam: URLOptions = {\n\t * initURL: \"/users/:id\",\n\t * params: { id: \"user-123\" }\n\t * };\n\t * // Results in: /users/user-123\n\t * ```\n\t */\n\tparams?: Params;\n\n\t/**\n\t * Query parameters to append to the URL as search parameters.\n\t *\n\t * These will be serialized into the URL query string using standard\n\t * URL encoding practices.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Basic query parameters\n\t * const queryOptions: URLOptions = {\n\t * initURL: \"/users\",\n\t * query: {\n\t * page: 1,\n\t * limit: 10,\n\t * search: \"john doe\",\n\t * active: true\n\t * }\n\t * };\n\t * // Results in: /users?page=1&limit=10&search=john%20doe&active=true\n\t *\n\t * // Filtering and sorting\n\t * const filterOptions: URLOptions = {\n\t * initURL: \"/products\",\n\t * query: {\n\t * category: \"electronics\",\n\t * minPrice: 100,\n\t * maxPrice: 500,\n\t * sortBy: \"price\",\n\t * order: \"asc\"\n\t * }\n\t * };\n\t * // Results in: /products?category=electronics&minPrice=100&maxPrice=500&sortBy=price&order=asc\n\t * ```\n\t */\n\tquery?: Query;\n}\n","import { createDedupeStrategy, type GlobalRequestInfoCache, type RequestInfoCache } from \"./dedupe\";\nimport { HTTPError } from \"./error\";\nimport {\n\ttype ErrorContext,\n\ttype ExecuteHookInfo,\n\texecuteHooksInCatchBlock,\n\texecuteHooksInTryBlock,\n\ttype RetryContext,\n\ttype SuccessContext,\n} from \"./hooks\";\nimport { type CallApiPlugin, initializePlugins } from \"./plugins\";\nimport {\n\ttype ErrorInfo,\n\ttype GetResponseType,\n\tgetCustomizedErrorResult,\n\ttype ResponseTypeUnion,\n\ttype ResultModeUnion,\n\tresolveErrorResult,\n\tresolveResponseData,\n\tresolveSuccessResult,\n} from \"./result\";\nimport { createRetryStrategy } from \"./retry\";\nimport type {\n\tGetCurrentRouteSchema,\n\tGetCurrentRouteSchemaKey,\n\tInferHeadersOption,\n\tInferInitURL,\n\tThrowOnErrorUnion,\n} from \"./types\";\nimport type {\n\tBaseCallApiConfig,\n\tBaseCallApiExtraOptions,\n\tCallApiExtraOptions,\n\tCallApiExtraOptionsForHooks,\n\tCallApiParameters,\n\tCallApiRequestOptions,\n\tCallApiRequestOptionsForHooks,\n\tCallApiResult,\n} from \"./types/common\";\nimport type { DefaultDataType, DefaultPluginArray, DefaultThrowOnError } from \"./types/default-types\";\nimport type { AnyFunction, Writeable } from \"./types/type-helpers\";\nimport { getFullAndNormalizedURL, getMethod } from \"./url\";\nimport {\n\tcreateCombinedSignal,\n\tcreateTimeoutSignal,\n\tgetBody,\n\tgetHeaders,\n\tsplitBaseConfig,\n\tsplitConfig,\n\twaitFor,\n} from \"./utils/common\";\nimport { isFunction, isHTTPErrorInstance, isValidationErrorInstance } from \"./utils/guards\";\nimport {\n\ttype BaseCallApiSchemaAndConfig,\n\ttype BaseCallApiSchemaRoutes,\n\ttype CallApiSchema,\n\ttype CallApiSchemaConfig,\n\thandleConfigValidation,\n\thandleSchemaValidation,\n\ttype InferSchemaOutputResult,\n} from \"./validation\";\n\nconst $GlobalRequestInfoCache: GlobalRequestInfoCache = new Map();\n\nexport const createFetchClient = <\n\tTBaseData = DefaultDataType,\n\tTBaseErrorData = DefaultDataType,\n\tTBaseResultMode extends ResultModeUnion = ResultModeUnion,\n\tTBaseThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError,\n\tTBaseResponseType extends ResponseTypeUnion = ResponseTypeUnion,\n\tconst TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig,\n\tconst TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray,\n\tTComputedBaseSchemaConfig extends CallApiSchemaConfig = NonNullable<\n\t\tWriteable<TBaseSchemaAndConfig[\"config\"], \"deep\">\n\t>,\n\tTComputedBaseSchemaRoutes extends BaseCallApiSchemaRoutes = Writeable<\n\t\tTBaseSchemaAndConfig[\"routes\"],\n\t\t\"deep\"\n\t>,\n>(\n\tinitBaseConfig: BaseCallApiConfig<\n\t\tTBaseData,\n\t\tTBaseErrorData,\n\t\tTBaseResultMode,\n\t\tTBaseThrowOnError,\n\t\tTBaseResponseType,\n\t\tTBaseSchemaAndConfig,\n\t\tTBasePluginArray\n\t> = {} as never\n) => {\n\tconst $LocalRequestInfoCache: RequestInfoCache = new Map();\n\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t\tTThrowOnError extends ThrowOnErrorUnion = TBaseThrowOnError,\n\t\tTResponseType extends ResponseTypeUnion = TBaseResponseType,\n\t\tconst TSchemaConfig extends CallApiSchemaConfig = TComputedBaseSchemaConfig,\n\t\tTInitURL extends InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig> = InferInitURL<\n\t\t\tTComputedBaseSchemaRoutes,\n\t\t\tTSchemaConfig\n\t\t>,\n\t\tTCurrentRouteSchemaKey extends GetCurrentRouteSchemaKey<\n\t\t\tTSchemaConfig,\n\t\t\tTInitURL\n\t\t> = GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL>,\n\t\tconst TSchema extends CallApiSchema = GetCurrentRouteSchema<\n\t\t\tTComputedBaseSchemaRoutes,\n\t\t\tTCurrentRouteSchemaKey\n\t\t>,\n\t\tconst TPluginArray extends CallApiPlugin[] = TBasePluginArray,\n\t>(\n\t\t...parameters: CallApiParameters<\n\t\t\tInferSchemaOutputResult<TSchema[\"data\"], GetResponseType<TData, TResponseType>>,\n\t\t\tInferSchemaOutputResult<TSchema[\"errorData\"], GetResponseType<TErrorData, TResponseType>>,\n\t\t\tTResultMode,\n\t\t\tTThrowOnError,\n\t\t\tTResponseType,\n\t\t\tTComputedBaseSchemaRoutes,\n\t\t\tTSchema,\n\t\t\tTComputedBaseSchemaConfig,\n\t\t\tTSchemaConfig,\n\t\t\tTInitURL,\n\t\t\tTCurrentRouteSchemaKey,\n\t\t\tTBasePluginArray,\n\t\t\tTPluginArray\n\t\t>\n\t): CallApiResult<\n\t\tInferSchemaOutputResult<TSchema[\"data\"], TData>,\n\t\tInferSchemaOutputResult<TSchema[\"errorData\"], TErrorData>,\n\t\tTResultMode,\n\t\tTThrowOnError,\n\t\tTResponseType\n\t> => {\n\t\tconst [initURLOrURLObject, initConfig = {}] = parameters;\n\n\t\tconst [fetchOptions, extraOptions] = splitConfig(initConfig);\n\n\t\tconst resolvedBaseConfig =\n\t\t\tisFunction(initBaseConfig) ?\n\t\t\t\tinitBaseConfig({\n\t\t\t\t\tinitURL: initURLOrURLObject.toString(),\n\t\t\t\t\toptions: extraOptions,\n\t\t\t\t\trequest: fetchOptions,\n\t\t\t\t})\n\t\t\t:\tinitBaseConfig;\n\n\t\tconst baseConfig = resolvedBaseConfig as BaseCallApiExtraOptions & CallApiRequestOptions;\n\t\tconst config = initConfig as CallApiExtraOptions & CallApiRequestOptions;\n\n\t\tconst [baseFetchOptions, baseExtraOptions] = splitBaseConfig(baseConfig);\n\n\t\tconst shouldSkipAutoMergeForOptions =\n\t\t\tbaseExtraOptions.skipAutoMergeFor === \"all\" || baseExtraOptions.skipAutoMergeFor === \"options\";\n\n\t\tconst shouldSkipAutoMergeForRequest =\n\t\t\tbaseExtraOptions.skipAutoMergeFor === \"all\" || baseExtraOptions.skipAutoMergeFor === \"request\";\n\n\t\t// == Merged Extra Options\n\t\tconst mergedExtraOptions = {\n\t\t\t...baseExtraOptions,\n\t\t\t...(!shouldSkipAutoMergeForOptions && extraOptions),\n\t\t};\n\n\t\t// == Merged Request Options\n\t\tconst mergedRequestOptions = {\n\t\t\t// == Making sure headers is always an object\n\t\t\theaders: {},\n\t\t\t...baseFetchOptions,\n\t\t\t...(!shouldSkipAutoMergeForRequest && fetchOptions),\n\t\t} satisfies CallApiRequestOptions;\n\n\t\tconst {\n\t\t\tresolvedCurrentRouteSchemaKey,\n\t\t\tresolvedHooks,\n\t\t\tresolvedInitURL,\n\t\t\tresolvedOptions,\n\t\t\tresolvedRequestOptions,\n\t\t} = await initializePlugins({\n\t\t\tbaseConfig,\n\t\t\tconfig,\n\t\t\tinitURL: initURLOrURLObject.toString(),\n\t\t\toptions: mergedExtraOptions as CallApiExtraOptionsForHooks,\n\t\t\trequest: mergedRequestOptions as CallApiRequestOptionsForHooks,\n\t\t});\n\n\t\tconst { fullURL, normalizedInitURL } = getFullAndNormalizedURL({\n\t\t\tbaseURL: resolvedOptions.baseURL,\n\t\t\tinitURL: resolvedInitURL,\n\t\t\tparams: resolvedOptions.params,\n\t\t\tquery: resolvedOptions.query,\n\t\t});\n\n\t\tlet options = {\n\t\t\t...resolvedOptions,\n\t\t\t...resolvedHooks,\n\n\t\t\tfullURL,\n\t\t\tinitURL: resolvedInitURL,\n\t\t\tinitURLNormalized: normalizedInitURL,\n\t\t} satisfies CallApiExtraOptionsForHooks;\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tconst timeoutSignal = options.timeout != null ? createTimeoutSignal(options.timeout) : null;\n\n\t\tconst combinedSignal = createCombinedSignal(\n\t\t\tresolvedRequestOptions.signal,\n\t\t\ttimeoutSignal,\n\t\t\tnewFetchController.signal\n\t\t);\n\n\t\tlet request = {\n\t\t\t...resolvedRequestOptions,\n\n\t\t\tsignal: combinedSignal,\n\t\t} satisfies CallApiRequestOptionsForHooks;\n\n\t\tconst {\n\t\t\tgetAbortErrorMessage,\n\t\t\thandleRequestCancelStrategy,\n\t\t\thandleRequestDeferStrategy,\n\t\t\tremoveDedupeKeyFromCache,\n\t\t\tresolvedDedupeStrategy,\n\t\t} = await createDedupeStrategy({\n\t\t\t$GlobalRequestInfoCache,\n\t\t\t$LocalRequestInfoCache,\n\t\t\tbaseConfig,\n\t\t\tconfig,\n\t\t\tnewFetchController,\n\t\t\toptions,\n\t\t\trequest,\n\t\t});\n\n\t\ttry {\n\t\t\tawait handleRequestCancelStrategy();\n\n\t\t\tawait executeHooksInTryBlock(options.onRequest?.({ baseConfig, config, options, request }));\n\n\t\t\tconst {\n\t\t\t\textraOptionsValidationResult,\n\t\t\t\trequestOptionsValidationResult,\n\t\t\t\tresolvedSchema,\n\t\t\t\tresolvedSchemaConfig,\n\t\t\t\tshouldApplySchemaOutput,\n\t\t\t} = await handleConfigValidation({\n\t\t\t\tbaseExtraOptions,\n\t\t\t\tcurrentRouteSchemaKey: resolvedCurrentRouteSchemaKey,\n\t\t\t\textraOptions,\n\t\t\t\toptions,\n\t\t\t\trequestOptions: request,\n\t\t\t});\n\n\t\t\t// == Apply Schema Output for Extra Options\n\t\t\tif (shouldApplySchemaOutput) {\n\t\t\t\toptions = { ...options, ...extraOptionsValidationResult };\n\t\t\t}\n\n\t\t\t// == Apply Schema Output for Request Options\n\t\t\tconst rawBody = shouldApplySchemaOutput ? requestOptionsValidationResult?.body : request.body;\n\n\t\t\tconst validBody = getBody({\n\t\t\t\tbody: rawBody,\n\t\t\t\tbodySerializer: options.bodySerializer,\n\t\t\t});\n\n\t\t\ttype HeaderFn = Extract<InferHeadersOption<CallApiSchema>[\"headers\"], AnyFunction>;\n\n\t\t\tconst resolvedHeaders =\n\t\t\t\tisFunction<HeaderFn>(fetchOptions.headers) ?\n\t\t\t\t\tfetchOptions.headers({ baseHeaders: baseFetchOptions.headers ?? {} })\n\t\t\t\t:\t(fetchOptions.headers ?? baseFetchOptions.headers);\n\n\t\t\tconst validHeaders = await getHeaders({\n\t\t\t\tauth: options.auth,\n\t\t\t\tbody: rawBody,\n\t\t\t\theaders: shouldApplySchemaOutput ? requestOptionsValidationResult?.headers : resolvedHeaders,\n\t\t\t});\n\n\t\t\tconst validMethod = getMethod({\n\t\t\t\tinitURL: resolvedInitURL,\n\t\t\t\tmethod: shouldApplySchemaOutput ? requestOptionsValidationResult?.method : request.method,\n\t\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t\t});\n\n\t\t\trequest = {\n\t\t\t\t...request,\n\t\t\t\t...(Boolean(validBody) && { body: validBody }),\n\t\t\t\t...(Boolean(validHeaders) && { headers: validHeaders }),\n\t\t\t\t...(Boolean(validMethod) && { method: validMethod }),\n\t\t\t};\n\n\t\t\tconst response = await handleRequestDeferStrategy({ options, request });\n\n\t\t\t// == Also clone response when dedupeStrategy is set to \"defer\" to avoid error thrown from reading response.(whatever) more than once\n\t\t\tconst shouldCloneResponse = resolvedDedupeStrategy === \"defer\" || options.cloneResponse;\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await resolveResponseData(\n\t\t\t\t\tshouldCloneResponse ? response.clone() : response,\n\t\t\t\t\toptions.responseType,\n\t\t\t\t\toptions.responseParser\n\t\t\t\t);\n\n\t\t\t\tconst validErrorData = await handleSchemaValidation(resolvedSchema, \"errorData\", {\n\t\t\t\t\tinputValue: errorData,\n\t\t\t\t\tresponse,\n\t\t\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t\t\t});\n\n\t\t\t\t// == Push all error handling responsibilities to the catch block if not retrying\n\t\t\t\tthrow new HTTPError(\n\t\t\t\t\t{\n\t\t\t\t\t\tdefaultHTTPErrorMessage: options.defaultHTTPErrorMessage,\n\t\t\t\t\t\terrorData: validErrorData,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t},\n\t\t\t\t\t{ cause: validErrorData }\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst successData = await resolveResponseData(\n\t\t\t\tshouldCloneResponse ? response.clone() : response,\n\t\t\t\toptions.responseType,\n\t\t\t\toptions.responseParser\n\t\t\t);\n\n\t\t\tconst validSuccessData = await handleSchemaValidation(resolvedSchema, \"data\", {\n\t\t\t\tinputValue: successData,\n\t\t\t\tresponse,\n\t\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t\t});\n\n\t\t\tconst successContext = {\n\t\t\t\tbaseConfig,\n\t\t\t\tconfig,\n\t\t\t\tdata: validSuccessData,\n\t\t\t\toptions,\n\t\t\t\trequest,\n\t\t\t\tresponse,\n\t\t\t} satisfies SuccessContext<unknown>;\n\n\t\t\tawait executeHooksInTryBlock(\n\t\t\t\toptions.onSuccess?.(successContext),\n\n\t\t\t\toptions.onResponse?.({ ...successContext, error: null })\n\t\t\t);\n\n\t\t\tconst successResult = resolveSuccessResult(successContext.data, {\n\t\t\t\tresponse: successContext.response,\n\t\t\t\tresultMode: options.resultMode,\n\t\t\t});\n\n\t\t\treturn successResult as never;\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst errorInfo = {\n\t\t\t\tcloneResponse: options.cloneResponse,\n\t\t\t\tresultMode: options.resultMode,\n\t\t\t} satisfies ErrorInfo;\n\n\t\t\tconst { errorDetails, generalErrorResult } = resolveErrorResult(error, errorInfo);\n\n\t\t\tconst errorContext = {\n\t\t\t\tbaseConfig,\n\t\t\t\tconfig,\n\t\t\t\terror: errorDetails.error as never,\n\t\t\t\toptions,\n\t\t\t\trequest,\n\t\t\t\tresponse: errorDetails.response as never,\n\t\t\t} satisfies ErrorContext<unknown>;\n\n\t\t\tconst shouldThrowOnError = Boolean(\n\t\t\t\tisFunction(options.throwOnError) ? options.throwOnError(errorContext) : options.throwOnError\n\t\t\t);\n\n\t\t\tconst hookInfo = {\n\t\t\t\terrorInfo,\n\t\t\t\tshouldThrowOnError,\n\t\t\t} satisfies ExecuteHookInfo;\n\n\t\t\tconst handleRetryOrGetErrorResult = async () => {\n\t\t\t\tconst { currentAttemptCount, getDelay, shouldAttemptRetry } =\n\t\t\t\t\tcreateRetryStrategy(errorContext);\n\n\t\t\t\tconst shouldRetry = await shouldAttemptRetry();\n\n\t\t\t\tif (shouldRetry) {\n\t\t\t\t\tconst retryContext = {\n\t\t\t\t\t\t...errorContext,\n\t\t\t\t\t\tretryAttemptCount: currentAttemptCount,\n\t\t\t\t\t} satisfies RetryContext<unknown>;\n\n\t\t\t\t\tconst hookError = await executeHooksInCatchBlock(\n\t\t\t\t\t\t[options.onRetry?.(retryContext)],\n\t\t\t\t\t\thookInfo\n\t\t\t\t\t);\n\n\t\t\t\t\tif (hookError) {\n\t\t\t\t\t\treturn hookError;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst delay = getDelay();\n\n\t\t\t\t\tawait waitFor(delay);\n\n\t\t\t\t\tconst updatedOptions = {\n\t\t\t\t\t\t...config,\n\t\t\t\t\t\t\"~retryAttemptCount\": currentAttemptCount + 1,\n\t\t\t\t\t} satisfies typeof config;\n\n\t\t\t\t\treturn callApi(initURLOrURLObject as never, updatedOptions as never) as never;\n\t\t\t\t}\n\n\t\t\t\tif (shouldThrowOnError) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\n\t\t\t\treturn generalErrorResult;\n\t\t\t};\n\n\t\t\tif (isValidationErrorInstance(error)) {\n\t\t\t\tconst hookError = await executeHooksInCatchBlock(\n\t\t\t\t\t[options.onValidationError?.(errorContext), options.onError?.(errorContext)],\n\t\t\t\t\thookInfo\n\t\t\t\t);\n\n\t\t\t\treturn (hookError ?? (await handleRetryOrGetErrorResult())) as never;\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst hookError = await executeHooksInCatchBlock(\n\t\t\t\t\t[\n\t\t\t\t\t\toptions.onResponseError?.(errorContext),\n\t\t\t\t\t\toptions.onError?.(errorContext),\n\t\t\t\t\t\toptions.onResponse?.({ ...errorContext, data: null }),\n\t\t\t\t\t],\n\t\t\t\t\thookInfo\n\t\t\t\t);\n\n\t\t\t\treturn (hookError ?? (await handleRetryOrGetErrorResult())) as never;\n\t\t\t}\n\n\t\t\tlet message = (error as Error | undefined)?.message;\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tmessage = getAbortErrorMessage();\n\n\t\t\t\t!shouldThrowOnError && console.error(`${error.name}:`, message);\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tmessage = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\t!shouldThrowOnError && console.error(`${error.name}:`, message);\n\t\t\t}\n\n\t\t\tconst hookError = await executeHooksInCatchBlock(\n\t\t\t\t[options.onRequestError?.(errorContext), options.onError?.(errorContext)],\n\t\t\t\thookInfo\n\t\t\t);\n\n\t\t\treturn (hookError\n\t\t\t\t?? getCustomizedErrorResult(await handleRetryOrGetErrorResult(), { message })) as never;\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tremoveDedupeKeyFromCache();\n\t\t}\n\t};\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n","import type { CallApiPlugin } from \"./plugins\";\nimport type { ResponseTypeUnion, ResultModeUnion } from \"./result\";\nimport type {\n\tBaseCallApiConfig,\n\tCallApiExtraOptions,\n\tCallApiParameters,\n\tInferInitURL,\n\tThrowOnErrorUnion,\n} from \"./types\";\nimport type { DefaultDataType, DefaultPluginArray, DefaultThrowOnError } from \"./types/default-types\";\nimport type { AnyFunction, Writeable } from \"./types/type-helpers\";\nimport type {\n\tBaseCallApiSchemaAndConfig,\n\tBaseCallApiSchemaRoutes,\n\tCallApiSchema,\n\tCallApiSchemaConfig,\n} from \"./validation\";\n\nexport const defineSchema = <\n\tconst TBaseSchemaRoutes extends BaseCallApiSchemaRoutes,\n\tconst TSchemaConfig extends CallApiSchemaConfig,\n>(\n\troutes: TBaseSchemaRoutes,\n\tconfig?: TSchemaConfig\n) => {\n\treturn {\n\t\tconfig: defineSchemaConfig(config),\n\t\troutes: defineSchemaRoutes(routes),\n\t} satisfies BaseCallApiSchemaAndConfig;\n};\n\nexport const defineSchemaConfig = <const TConfig extends CallApiExtraOptions[\"schemaConfig\"]>(\n\tconfig: TConfig\n) => {\n\treturn config as NonNullable<Writeable<typeof config, \"deep\">>;\n};\n\nexport const defineSchemaRoutes = <const TBaseSchemaRoutes extends BaseCallApiSchemaRoutes>(\n\troutes: TBaseSchemaRoutes\n) => {\n\treturn routes as Writeable<typeof routes, \"deep\">;\n};\n\nexport const definePlugin = <\n\t// eslint-disable-next-line perfectionist/sort-union-types -- Let the first one be first\n\tconst TPlugin extends CallApiPlugin | AnyFunction<CallApiPlugin>,\n>(\n\tplugin: TPlugin\n) => {\n\treturn plugin as Writeable<TPlugin, \"deep\">;\n};\n\nexport const defineBaseConfig = <const TBaseConfig extends BaseCallApiConfig>(baseConfig: TBaseConfig) => {\n\treturn baseConfig as Writeable<typeof baseConfig, \"deep\">;\n};\n\nexport const defineParameters = <\n\tTData = DefaultDataType,\n\tTErrorData = DefaultDataType,\n\tTResultMode extends ResultModeUnion = ResultModeUnion,\n\tTThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError,\n\tTResponseType extends ResponseTypeUnion = ResponseTypeUnion,\n\tTBaseSchemaRoutes extends BaseCallApiSchemaRoutes = BaseCallApiSchemaRoutes,\n\tTSchema extends CallApiSchema = CallApiSchema,\n\tTBaseSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig,\n\tTSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig,\n\tTInitURL extends InferInitURL<BaseCallApiSchemaRoutes, TSchemaConfig> = InferInitURL<\n\t\tBaseCallApiSchemaRoutes,\n\t\tTSchemaConfig\n\t>,\n\tTCurrentRouteSchemaKey extends string = string,\n\tTBasePluginArray extends CallApiPlugin[] = DefaultPluginArray,\n\tTPluginArray extends CallApiPlugin[] = DefaultPluginArray,\n>(\n\t...parameters: CallApiParameters<\n\t\tTData,\n\t\tTErrorData,\n\t\tTResultMode,\n\t\tTThrowOnError,\n\t\tTResponseType,\n\t\tTBaseSchemaRoutes,\n\t\tTSchema,\n\t\tTBaseSchemaConfig,\n\t\tTSchemaConfig,\n\t\tTInitURL,\n\t\tTCurrentRouteSchemaKey,\n\t\tTBasePluginArray,\n\t\tTPluginArray\n\t>\n) => {\n\treturn parameters;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["$GlobalRequestInfoCache","resolvedHooks: Hooks","$GlobalRequestInfoCache: GlobalRequestInfoCache","$LocalRequestInfoCache: RequestInfoCache","callApi"],"sources":["../../src/result.ts","../../src/hooks.ts","../../src/stream.ts","../../src/dedupe.ts","../../src/plugins.ts","../../src/retry.ts","../../src/createFetchClient.ts","../../src/defineHelpers.ts"],"sourcesContent":["import { extraOptionDefaults } from \"./constants/default-options\";\nimport type { HTTPError, ValidationError } from \"./error\";\nimport type { CallApiExtraOptions, ThrowOnErrorUnion } from \"./types\";\nimport type { DefaultDataType, DefaultThrowOnError } from \"./types/default-types\";\nimport type { AnyString, Awaitable, UnmaskType } from \"./types/type-helpers\";\nimport { isHTTPErrorInstance, isValidationErrorInstance } from \"./utils/guards\";\n\nexport type ResponseType = \"blob\" | \"json\" | \"text\";\n\ntype Parser<TData> = (responseString: string) => Awaitable<TData>;\n\nexport const getResponseType = <TResponse>(response: Response, parser: Parser<TResponse>) => ({\n\tarrayBuffer: () => response.arrayBuffer(),\n\tblob: () => response.blob(),\n\tformData: () => response.formData(),\n\tjson: async (): Promise<TResponse> => {\n\t\tconst text = await response.text();\n\t\treturn parser(text);\n\t},\n\tstream: () => response.body,\n\ttext: () => response.text(),\n});\n\ntype InitResponseTypeMap<TResponse = unknown> = ReturnType<typeof getResponseType<TResponse>>;\n\nexport type ResponseTypeUnion = keyof InitResponseTypeMap | null;\n\nexport type ResponseTypeMap<TResponse> = {\n\t[Key in keyof InitResponseTypeMap<TResponse>]: Awaited<ReturnType<InitResponseTypeMap<TResponse>[Key]>>;\n};\n\nexport type GetResponseType<\n\tTResponse,\n\tTResponseType extends ResponseTypeUnion,\n\tTComputedResponseTypeMap extends ResponseTypeMap<TResponse> = ResponseTypeMap<TResponse>,\n> =\n\tnull extends TResponseType ? TComputedResponseTypeMap[\"json\"]\n\t: TResponseType extends NonNullable<ResponseTypeUnion> ? TComputedResponseTypeMap[TResponseType]\n\t: never;\n\nconst textTypes = new Set([\"image/svg\", \"application/xml\", \"application/xhtml\", \"application/html\"]);\nconst JSON_REGEX = /^application\\/(?:[\\w!#$%&*.^`~-]*\\+)?json(;.+)?$/i;\n\nconst detectResponseType = (response: Response): Extract<ResponseTypeUnion, \"blob\" | \"json\" | \"text\"> => {\n\tconst initContentType = response.headers.get(\"content-type\");\n\n\tif (!initContentType) {\n\t\treturn extraOptionDefaults().responseType;\n\t}\n\n\tconst contentType = initContentType.split(\";\")[0] ?? \"\";\n\n\tif (JSON_REGEX.test(contentType)) {\n\t\treturn \"json\";\n\t}\n\n\tif (textTypes.has(contentType) || contentType.startsWith(\"text/\")) {\n\t\treturn \"text\";\n\t}\n\n\treturn \"blob\";\n};\n\nexport const resolveResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: ResponseTypeUnion | undefined,\n\tparser: Parser<TResponse> | undefined\n) => {\n\tconst selectedParser = parser ?? extraOptionDefaults().responseParser;\n\tconst selectedResponseType = responseType ?? detectResponseType(response);\n\n\tconst RESPONSE_TYPE_LOOKUP = getResponseType<TResponse>(response, selectedParser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, selectedResponseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[selectedResponseType]();\n};\n\nexport type CallApiResultSuccessVariant<TData> = {\n\tdata: NoInfer<TData>;\n\terror: null;\n\tresponse: Response;\n};\n\nexport type PossibleJavaScriptError = UnmaskType<{\n\terrorData: false;\n\tmessage: string;\n\tname: \"AbortError\" | \"Error\" | \"SyntaxError\" | \"TimeoutError\" | \"TypeError\" | AnyString;\n\toriginalError: DOMException | Error | SyntaxError | TypeError;\n}>;\n\nexport type PossibleHTTPError<TErrorData> = UnmaskType<{\n\terrorData: NoInfer<TErrorData>;\n\tmessage: string;\n\tname: \"HTTPError\";\n\toriginalError: HTTPError;\n}>;\n\nexport type PossibleValidationError = UnmaskType<{\n\terrorData: ValidationError[\"errorData\"];\n\tissueCause: ValidationError[\"issueCause\"];\n\tmessage: string;\n\tname: \"ValidationError\";\n\toriginalError: ValidationError;\n}>;\n\nexport type PossibleJavaScriptOrValidationError = UnmaskType<\n\tPossibleJavaScriptError | PossibleValidationError\n>;\n\nexport type CallApiResultErrorVariant<TErrorData> =\n\t| {\n\t\t\tdata: null;\n\t\t\terror: PossibleHTTPError<TErrorData>;\n\t\t\tresponse: Response;\n\t }\n\t| {\n\t\t\tdata: null;\n\t\t\terror: PossibleJavaScriptOrValidationError;\n\t\t\tresponse: Response | null;\n\t };\n\nexport type ResultModeMapWithoutException<\n\tTData,\n\tTErrorData,\n\tTResponseType extends ResponseTypeUnion,\n\tTComputedData = GetResponseType<TData, TResponseType>,\n\tTComputedErrorData = GetResponseType<TErrorData, TResponseType>,\n> = UnmaskType<{\n\tall: CallApiResultErrorVariant<TComputedErrorData> | CallApiResultSuccessVariant<TComputedData>;\n\n\tonlyData:\n\t\t| CallApiResultErrorVariant<TComputedErrorData>[\"data\"]\n\t\t| CallApiResultSuccessVariant<TComputedData>[\"data\"];\n}>;\n\ntype ResultModeMapWithException<\n\tTData,\n\tTResponseType extends ResponseTypeUnion,\n\tTComputedData = GetResponseType<TData, TResponseType>,\n> = {\n\tall: CallApiResultSuccessVariant<TComputedData>;\n\tonlyData: CallApiResultSuccessVariant<TComputedData>[\"data\"];\n};\n\nexport type ResultModeMap<\n\tTData = DefaultDataType,\n\tTErrorData = DefaultDataType,\n\tTResponseType extends ResponseTypeUnion = ResponseTypeUnion,\n\tTThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError,\n> =\n\tTThrowOnError extends true ? ResultModeMapWithException<TData, TResponseType>\n\t:\tResultModeMapWithoutException<TData, TErrorData, TResponseType>;\n\ntype ResultModePlaceholder = null;\n\n// eslint-disable-next-line perfectionist/sort-union-types -- Allow\nexport type ResultModeUnion = keyof ResultModeMap | ResultModePlaceholder;\n\nexport type GetCallApiResult<\n\tTData,\n\tTErrorData,\n\tTResultMode extends ResultModeUnion,\n\tTThrowOnError extends ThrowOnErrorUnion,\n\tTResponseType extends ResponseTypeUnion,\n> =\n\tTErrorData extends false ? ResultModeMapWithException<TData, TResponseType>[\"onlyData\"]\n\t: TErrorData extends false | undefined ? ResultModeMapWithException<TData, TResponseType>[\"onlyData\"]\n\t: ResultModePlaceholder extends TResultMode ?\n\t\tResultModeMap<TData, TErrorData, TResponseType, TThrowOnError>[\"all\"]\n\t: TResultMode extends Exclude<ResultModeUnion, ResultModePlaceholder> ?\n\t\tResultModeMap<TData, TErrorData, TResponseType, TThrowOnError>[TResultMode]\n\t:\tnever;\n\ntype SuccessInfo = {\n\tresponse: Response;\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\n};\n\ntype LazyResultModeMap = {\n\t[key in keyof ResultModeMap]: () => ResultModeMap[key];\n};\n\nconst getResultModeMap = (details: ResultModeMap[\"all\"]): LazyResultModeMap => {\n\treturn {\n\t\tall: () => details,\n\t\tonlyData: () => details.data,\n\t};\n};\n\ntype SuccessResult = CallApiResultSuccessVariant<unknown> | null;\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = (data: unknown, info: SuccessInfo): SuccessResult => {\n\tconst { response, resultMode } = info;\n\n\tconst details = {\n\t\tdata,\n\t\terror: null,\n\t\tresponse,\n\t} satisfies CallApiResultSuccessVariant<unknown>;\n\n\tconst resultModeMap = getResultModeMap(details);\n\n\tconst successResult = resultModeMap[resultMode ?? \"all\"]();\n\n\treturn successResult as SuccessResult;\n};\n\nexport type ErrorInfo = {\n\tcloneResponse: CallApiExtraOptions[\"cloneResponse\"];\n\tmessage?: string;\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\n};\n\ntype ErrorResult = {\n\terrorDetails: CallApiResultErrorVariant<unknown>;\n\tgeneralErrorResult: CallApiResultErrorVariant<unknown> | null;\n};\n\nexport const resolveErrorResult = (error: unknown, info: ErrorInfo): ErrorResult => {\n\tconst { cloneResponse, message: customErrorMessage, resultMode } = info;\n\n\tlet errorDetails = {\n\t\tdata: null,\n\t\terror: {\n\t\t\terrorData: false,\n\t\t\tmessage: customErrorMessage ?? (error as Error).message,\n\t\t\tname: (error as Error).name,\n\t\t\toriginalError: error as Error,\n\t\t},\n\t\tresponse: null,\n\t} satisfies CallApiResultErrorVariant<unknown> as CallApiResultErrorVariant<unknown>;\n\n\tif (isValidationErrorInstance(error)) {\n\t\tconst { errorData, message, response } = error;\n\n\t\terrorDetails = {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\terrorData,\n\t\t\t\tissueCause: error.issueCause,\n\t\t\t\tmessage,\n\t\t\t\tname: \"ValidationError\",\n\t\t\t\toriginalError: error,\n\t\t\t},\n\t\t\tresponse,\n\t\t};\n\t}\n\n\tif (isHTTPErrorInstance<never>(error)) {\n\t\tconst { errorData, message, name, response } = error;\n\n\t\terrorDetails = {\n\t\t\tdata: null,\n\t\t\terror: { errorData, message, name, originalError: error },\n\t\t\tresponse: cloneResponse ? response.clone() : response,\n\t\t};\n\t}\n\n\tconst resultModeMap = getResultModeMap(errorDetails);\n\n\tconst generalErrorResult = resultModeMap[resultMode ?? \"all\"]() as never;\n\n\treturn {\n\t\terrorDetails,\n\t\tgeneralErrorResult,\n\t};\n};\n\nexport const getCustomizedErrorResult = (\n\terrorResult: ErrorResult[\"generalErrorResult\"],\n\tcustomErrorInfo: { message: string | undefined }\n): ErrorResult[\"generalErrorResult\"] => {\n\tif (!errorResult) {\n\t\treturn null;\n\t}\n\n\tconst { message = errorResult.error.message } = customErrorInfo;\n\n\treturn {\n\t\t...errorResult,\n\t\terror: {\n\t\t\t...errorResult.error,\n\t\t\tmessage,\n\t\t} satisfies NonNullable<ErrorResult[\"generalErrorResult\"]>[\"error\"] as never,\n\t};\n};\n","import {\n\ttype CallApiResultErrorVariant,\n\ttype CallApiResultSuccessVariant,\n\ttype ErrorInfo,\n\ttype PossibleHTTPError,\n\ttype PossibleJavaScriptError,\n\ttype PossibleJavaScriptOrValidationError,\n\ttype PossibleValidationError,\n\tresolveErrorResult,\n} from \"./result\";\nimport type { StreamProgressEvent } from \"./stream\";\nimport type {\n\tBaseCallApiExtraOptions,\n\tCallApiExtraOptions,\n\tCallApiExtraOptionsForHooks,\n\tCallApiRequestOptions,\n\tCallApiRequestOptionsForHooks,\n} from \"./types/common\";\nimport type { DefaultDataType } from \"./types/default-types\";\nimport type { AnyFunction, Awaitable, Prettify, UnmaskType } from \"./types/type-helpers\";\n\nexport type PluginExtraOptions<TPluginOptions = unknown> = {\n\t/** Plugin-specific options passed to the plugin configuration */\n\toptions: Partial<TPluginOptions>;\n};\n\n/* eslint-disable perfectionist/sort-intersection-types -- Plugin options should come last */\nexport interface Hooks<TData = DefaultDataType, TErrorData = DefaultDataType, TPluginOptions = unknown> {\n\t/**\n\t * First hook in the request lifecycle, executed before any internal processing begins.\n\t *\n\t * This is the earliest point to intercept requests - ideal for initial setup, logging,\n\t * or modifying the request before any other processing occurs.\n\t *\n\t * @param context - Request context with mutable request object and configuration\n\t */\n\tonBeforeRequest?: (context: RequestContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when any error occurs within the request/response lifecycle.\n\t *\n\t * This is a unified error handler that catches both request errors (network failures,\n\t * timeouts, etc.) and response errors (HTTP error status codes). It's essentially\n\t * a combination of `onRequestError` and `onResponseError` hooks.\n\t *\n\t * @param context - Error context containing error details, request info, and response (if available)\n\t * @returns Promise or void - Hook can be async or sync\n\t */\n\tonError?: (\n\t\tcontext: ErrorContext<TErrorData> & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called just before the HTTP request is sent.\n\t *\n\t * This is the ideal place to modify request headers, add authentication,\n\t * implement request logging, or perform any setup before the network call.\n\t *\n\t * @param context - Request context with mutable request object and configuration\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonRequest?: (context: RequestContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when an error occurs during the fetch request itself.\n\t *\n\t * This handles network-level errors like connection failures, timeouts,\n\t * DNS resolution errors, or other issues that prevent getting an HTTP response.\n\t * Note that HTTP error status codes (4xx, 5xx) are handled by `onResponseError`.\n\t *\n\t * @param context - Request error context with error details and null response\n\t * @returns Promise or void - Hook can be async or sync\n\t */\n\tonRequestError?: (\n\t\tcontext: RequestErrorContext & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called during upload stream progress tracking.\n\t *\n\t * This hook is triggered when uploading data (like file uploads) and provides\n\t * progress information about the upload. Useful for implementing progress bars\n\t * or upload status indicators.\n\t *\n\t * @param context - Request stream context with progress event and request instance\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonRequestStream?: (\n\t\tcontext: RequestStreamContext & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when any HTTP response is received from the API.\n\t *\n\t * This hook is triggered for both successful (2xx) and error (4xx, 5xx) responses.\n\t * It's useful for response logging, metrics collection, or any processing that\n\t * should happen regardless of response status.\n\t *\n\t * @param context - Response context with either success data or error information\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonResponse?: (\n\t\tcontext: ResponseContext<TData, TErrorData> & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when an HTTP error response (4xx, 5xx) is received from the API.\n\t *\n\t * This handles server-side errors where an HTTP response was successfully received\n\t * but indicates an error condition. Different from `onRequestError` which handles\n\t * network-level failures.\n\t *\n\t * @param context - Response error context with HTTP error details and response\n\t * @returns Promise or void - Hook can be async or sync\n\t */\n\tonResponseError?: (\n\t\tcontext: ResponseErrorContext<TErrorData> & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called during download stream progress tracking.\n\t *\n\t * This hook is triggered when downloading data (like file downloads) and provides\n\t * progress information about the download. Useful for implementing progress bars\n\t * or download status indicators.\n\t *\n\t * @param context - Response stream context with progress event and response\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonResponseStream?: (\n\t\tcontext: ResponseStreamContext & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when a request is being retried.\n\t *\n\t * This hook is triggered before each retry attempt, providing information about\n\t * the previous failure and the current retry attempt number. Useful for implementing\n\t * custom retry logic, exponential backoff, or retry logging.\n\t *\n\t * @param context - Retry context with error details and retry attempt count\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonRetry?: (\n\t\tresponse: RetryContext<TErrorData> & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when a successful response (2xx status) is received from the API.\n\t *\n\t * This hook is triggered only for successful responses and provides access to\n\t * the parsed response data. Ideal for success logging, caching, or post-processing\n\t * of successful API responses.\n\t *\n\t * @param context - Success context with parsed response data and response object\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonSuccess?: (context: SuccessContext<TData> & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;\n\n\t/**\n\t * Hook called when a validation error occurs.\n\t *\n\t * This hook is triggered when request or response data fails validation against\n\t * a defined schema. It provides access to the validation error details and can\n\t * be used for custom error handling, logging, or fallback behavior.\n\t *\n\t * @param context - Validation error context with error details and response (if available)\n\t * @returns Promise or void - Hook can be async or sync\n\t *\n\t */\n\tonValidationError?: (\n\t\tcontext: ValidationErrorContext & PluginExtraOptions<TPluginOptions>\n\t) => Awaitable<unknown>;\n}\n/* eslint-enable perfectionist/sort-intersection-types -- Plugin options should come last */\n\nexport type HooksOrHooksArray<\n\tTData = DefaultDataType,\n\tTErrorData = DefaultDataType,\n\tTMoreOptions = unknown,\n> = {\n\t[Key in keyof Hooks<TData, TErrorData, TMoreOptions>]:\n\t\t| Hooks<TData, TErrorData, TMoreOptions>[Key]\n\t\t// eslint-disable-next-line perfectionist/sort-union-types -- I need arrays to be last\n\t\t| Array<Hooks<TData, TErrorData, TMoreOptions>[Key]>;\n};\n\nexport interface HookConfigOptions {\n\t/**\n\t * Controls the execution mode of all composed hooks (main + plugin hooks).\n\t *\n\t * - **\"parallel\"**: All hooks execute simultaneously via Promise.all() for better performance\n\t * - **\"sequential\"**: All hooks execute one by one in registration order via await in a loop\n\t *\n\t * This affects how ALL hooks execute together, regardless of their source (main or plugin).\n\t *\n\t * Use `hookRegistrationOrder` to control the registration order of main vs plugin hooks.\n\t *\n\t * @default \"parallel\"\n\t *\n\t * @example\n\t * ```ts\n\t * // Parallel execution (default) - all hooks run simultaneously\n\t * hooksExecutionMode: \"parallel\"\n\t *\n\t * // Sequential execution - hooks run one after another\n\t * hooksExecutionMode: \"sequential\"\n\t *\n\t * // Use case: Hooks have dependencies and must run in order\n\t * const client = callApi.create({\n\t * hooksExecutionMode: \"sequential\",\n\t * hookRegistrationOrder: \"mainFirst\",\n\t * plugins: [transformPlugin],\n\t * onRequest: (ctx) => {\n\t * // This runs first, then transform plugin runs\n\t * ctx.request.headers[\"x-request-id\"] = generateId();\n\t * }\n\t * });\n\t *\n\t * // Use case: Independent operations can run in parallel for speed\n\t * const client = callApi.create({\n\t * hooksExecutionMode: \"parallel\", // Default\n\t * plugins: [metricsPlugin, cachePlugin, loggingPlugin],\n\t * onRequest: (ctx) => {\n\t * // All hooks (main + plugins) run simultaneously\n\t * addRequestTimestamp(ctx.request);\n\t * }\n\t * });\n\t *\n\t * // Use case: Error handling hooks that need sequential processing\n\t * const client = callApi.create({\n\t * hooksExecutionMode: \"sequential\",\n\t * onError: [\n\t * (ctx) => logError(ctx.error), // Log first\n\t * (ctx) => reportError(ctx.error), // Then report\n\t * (ctx) => cleanupResources(ctx) // Finally cleanup\n\t * ]\n\t * });\n\t * ```\n\t */\n\thooksExecutionMode?: \"parallel\" | \"sequential\";\n\n\t/**\n\t * Controls the registration order of main hooks relative to plugin hooks.\n\t *\n\t * - **\"pluginsFirst\"**: Plugin hooks register first, then main hooks (default)\n\t * - **\"mainFirst\"**: Main hooks register first, then plugin hooks\n\t *\n\t * This determines the order hooks are added to the registry, which affects\n\t * their execution sequence when using sequential execution mode.\n\t *\n\t * @default \"pluginsFirst\"\n\t *\n\t * @example\n\t * ```ts\n\t * // Plugin hooks register first (default behavior)\n\t * hookRegistrationOrder: \"pluginsFirst\"\n\t *\n\t * // Main hooks register first\n\t * hookRegistrationOrder: \"mainFirst\"\n\t *\n\t * // Use case: Main validation before plugin processing\n\t * const client = callApi.create({\n\t * hookRegistrationOrder: \"mainFirst\",\n\t * hooksExecutionMode: \"sequential\",\n\t * plugins: [transformPlugin],\n\t * onRequest: (ctx) => {\n\t * // This main hook runs first in sequential mode\n\t * if (!ctx.request.headers.authorization) {\n\t * throw new Error(\"Authorization required\");\n\t * }\n\t * }\n\t * });\n\t *\n\t * // Use case: Plugin setup before main logic (default)\n\t * const client = callApi.create({\n\t * hookRegistrationOrder: \"pluginsFirst\", // Default\n\t * hooksExecutionMode: \"sequential\",\n\t * plugins: [setupPlugin],\n\t * onRequest: (ctx) => {\n\t * // Plugin runs first, then this main hook\n\t * console.log(\"Request prepared:\", ctx.request.url);\n\t * }\n\t * });\n\t *\n\t * // Use case: Parallel mode (registration order less important)\n\t * const client = callApi.create({\n\t * hookRegistrationOrder: \"pluginsFirst\",\n\t * hooksExecutionMode: \"parallel\", // All run simultaneously\n\t * plugins: [metricsPlugin, cachePlugin],\n\t * onRequest: (ctx) => {\n\t * // All hooks run in parallel regardless of registration order\n\t * addRequestId(ctx.request);\n\t * }\n\t * });\n\t * ```\n\t */\n\thooksRegistrationOrder?: \"mainFirst\" | \"pluginsFirst\";\n}\n\nexport type RequestContext = {\n\t/**\n\t * Base configuration object passed to createFetchClient.\n\t *\n\t * Contains the foundational configuration that applies to all requests\n\t * made by this client instance, such as baseURL, default headers, and\n\t * global options.\n\t */\n\tbaseConfig: BaseCallApiExtraOptions & CallApiRequestOptions;\n\n\t/**\n\t * Instance-specific configuration object passed to the callApi instance.\n\t *\n\t * Contains configuration specific to this particular API call, which\n\t * can override or extend the base configuration.\n\t */\n\tconfig: CallApiExtraOptions & CallApiRequestOptions;\n\n\t/**\n\t * Merged options combining base config, instance config, and default options.\n\t *\n\t * This is the final resolved configuration that will be used for the request,\n\t * with proper precedence applied (instance > base > defaults).\n\t */\n\toptions: CallApiExtraOptionsForHooks;\n\n\t/**\n\t * Merged request object ready to be sent.\n\t *\n\t * Contains the final request configuration including URL, method, headers,\n\t * body, and other fetch options. This object can be modified in onRequest\n\t * hooks to customize the outgoing request.\n\t */\n\trequest: CallApiRequestOptionsForHooks;\n};\n\nexport type ValidationErrorContext = UnmaskType<\n\tRequestContext & {\n\t\t/** Validation error containing details about what failed validation */\n\t\terror: PossibleValidationError;\n\t\t/** HTTP response object if validation failed on response, null if on request */\n\t\tresponse: Response | null;\n\t}\n>;\n\nexport type SuccessContext<TData> = UnmaskType<\n\tRequestContext & {\n\t\t/** Parsed response data with the expected success type */\n\t\tdata: TData;\n\t\t/** HTTP response object for the successful request */\n\t\tresponse: Response;\n\t}\n>;\n\nexport type ResponseContext<TData, TErrorData> = UnmaskType<\n\tRequestContext\n\t\t& (\n\t\t\t| Prettify<CallApiResultSuccessVariant<TData>>\n\t\t\t| Prettify<\n\t\t\t\t\tExtract<CallApiResultErrorVariant<TErrorData>, { error: PossibleHTTPError<TErrorData> }>\n\t\t\t >\n\t\t)\n>;\n\nexport type RequestErrorContext = RequestContext & {\n\t/** Error that occurred during the request (network, timeout, etc.) */\n\terror: PossibleJavaScriptError;\n\t/** Always null for request errors since no response was received */\n\tresponse: null;\n};\n\nexport type ErrorContext<TErrorData> = UnmaskType<\n\tRequestContext\n\t\t& (\n\t\t\t| {\n\t\t\t\t\t/** HTTP error with response data */\n\t\t\t\t\terror: PossibleHTTPError<TErrorData>;\n\t\t\t\t\t/** HTTP response object containing error status */\n\t\t\t\t\tresponse: Response;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\t/** Request-level error (network, timeout, validation, etc.) */\n\t\t\t\t\terror: PossibleJavaScriptOrValidationError;\n\t\t\t\t\t/** Response object if available, null for request errors */\n\t\t\t\t\tresponse: Response | null;\n\t\t\t }\n\t\t)\n>;\n\nexport type ResponseErrorContext<TErrorData> = UnmaskType<\n\tExtract<ErrorContext<TErrorData>, { error: PossibleHTTPError<TErrorData> }> & RequestContext\n>;\n\nexport type RetryContext<TErrorData> = UnmaskType<\n\tErrorContext<TErrorData> & {\n\t\t/** Current retry attempt number (1-based, so 1 = first retry) */\n\t\tretryAttemptCount: number;\n\t}\n>;\n\nexport type RequestStreamContext = UnmaskType<\n\tRequestContext & {\n\t\t/** Progress event containing loaded/total bytes information */\n\t\tevent: StreamProgressEvent;\n\t\t/** The actual Request instance being uploaded */\n\t\trequestInstance: Request;\n\t}\n>;\n\nexport type ResponseStreamContext = UnmaskType<\n\tRequestContext & {\n\t\t/** Progress event containing loaded/total bytes information */\n\t\tevent: StreamProgressEvent;\n\t\t/** HTTP response object being downloaded */\n\t\tresponse: Response;\n\t}\n>;\n\ntype HookRegistries = Required<{\n\t[Key in keyof Hooks]: Set<Hooks[Key]>;\n}>;\n\nexport const getHookRegistries = (): HookRegistries => {\n\treturn {\n\t\tonBeforeRequest: new Set(),\n\t\tonError: new Set(),\n\t\tonRequest: new Set(),\n\t\tonRequestError: new Set(),\n\t\tonRequestStream: new Set(),\n\t\tonResponse: new Set(),\n\t\tonResponseError: new Set(),\n\t\tonResponseStream: new Set(),\n\t\tonRetry: new Set(),\n\t\tonSuccess: new Set(),\n\t\tonValidationError: new Set(),\n\t};\n};\n\nexport const composeAllHooks = (\n\thooksArray: Array<AnyFunction | undefined>,\n\thooksExecutionMode: CallApiExtraOptionsForHooks[\"hooksExecutionMode\"]\n) => {\n\tconst mergedHook = async (ctx: unknown) => {\n\t\tswitch (hooksExecutionMode) {\n\t\t\tcase \"parallel\": {\n\t\t\t\tawait Promise.all(hooksArray.map((uniqueHook) => uniqueHook?.(ctx)));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"sequential\": {\n\t\t\t\tfor (const hook of hooksArray) {\n\t\t\t\t\t// eslint-disable-next-line no-await-in-loop -- This is necessary in this case\n\t\t\t\t\tawait hook?.(ctx);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\thooksExecutionMode satisfies undefined;\n\t\t\t}\n\t\t}\n\t};\n\n\treturn mergedHook;\n};\n\nexport const executeHooksInTryBlock = async (...hookResultsOrPromise: Array<Awaitable<unknown>>) => {\n\tawait Promise.all(hookResultsOrPromise);\n};\n\nexport type ExecuteHookInfo = {\n\terrorInfo: ErrorInfo;\n\tshouldThrowOnError: boolean | undefined;\n};\n\nexport const executeHooksInCatchBlock = async (\n\thookResultsOrPromise: Array<Awaitable<unknown>>,\n\thookInfo: ExecuteHookInfo\n) => {\n\tconst { errorInfo, shouldThrowOnError } = hookInfo;\n\n\ttry {\n\t\tawait Promise.all(hookResultsOrPromise);\n\n\t\treturn null;\n\t} catch (hookError) {\n\t\tconst { generalErrorResult: hookErrorResult } = resolveErrorResult(hookError, errorInfo);\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow hookError;\n\t\t}\n\n\t\treturn hookErrorResult;\n\t}\n};\n","import {\n\texecuteHooksInTryBlock,\n\ttype RequestContext,\n\ttype RequestStreamContext,\n\ttype ResponseStreamContext,\n} from \"./hooks\";\nimport { isObject, isReadableStream } from \"./utils/guards\";\n\nexport type StreamProgressEvent = {\n\t/**\n\t * Current chunk of data being streamed\n\t */\n\tchunk: Uint8Array;\n\t/**\n\t * Progress in percentage\n\t */\n\tprogress: number;\n\t/**\n\t * Total size of data in bytes\n\t */\n\ttotalBytes: number;\n\t/**\n\t * Amount of data transferred so far\n\t */\n\ttransferredBytes: number;\n};\n\ndeclare global {\n\tinterface ReadableStream<R> {\n\t\t[Symbol.asyncIterator]: () => AsyncIterableIterator<R>;\n\t}\n}\n\nconst createProgressEvent = (options: {\n\tchunk: Uint8Array;\n\ttotalBytes: number;\n\ttransferredBytes: number;\n}): StreamProgressEvent => {\n\tconst { chunk, totalBytes, transferredBytes } = options;\n\n\treturn {\n\t\tchunk,\n\t\tprogress: Math.round((transferredBytes / totalBytes) * 100) || 0,\n\t\ttotalBytes,\n\t\ttransferredBytes,\n\t};\n};\n\nconst calculateTotalBytesFromBody = async (\n\trequestBody: Request[\"body\"] | null,\n\texistingTotalBytes: number\n) => {\n\tlet totalBytes = existingTotalBytes;\n\n\tif (!requestBody) {\n\t\treturn totalBytes;\n\t}\n\n\tfor await (const chunk of requestBody) {\n\t\ttotalBytes += chunk.byteLength;\n\t}\n\n\treturn totalBytes;\n};\n\ntype ToStreamableRequestContext = RequestContext;\n\nexport const toStreamableRequest = async (\n\tcontext: ToStreamableRequestContext\n): Promise<Request | RequestInit> => {\n\tconst { baseConfig, config, options, request } = context;\n\n\tif (!options.onRequestStream || !isReadableStream(request.body)) {\n\t\treturn request as RequestInit;\n\t}\n\n\tconst requestInstance = new Request(\n\t\toptions.fullURL as NonNullable<typeof options.fullURL>,\n\t\t{ ...request, duplex: \"half\" } as RequestInit\n\t);\n\n\tconst contentLength = requestInstance.headers.get(\"content-length\");\n\n\tlet totalBytes = Number(contentLength ?? 0);\n\n\tconst shouldForcefullyCalcStreamSize =\n\t\tisObject(options.forcefullyCalculateStreamSize) ?\n\t\t\toptions.forcefullyCalculateStreamSize.request\n\t\t:\toptions.forcefullyCalculateStreamSize;\n\n\t// == If no content length is present, we read the total bytes from the body\n\tif (!contentLength && shouldForcefullyCalcStreamSize) {\n\t\ttotalBytes = await calculateTotalBytesFromBody(requestInstance.clone().body, totalBytes);\n\t}\n\n\tlet transferredBytes = 0;\n\n\tconst stream = new ReadableStream({\n\t\tstart: async (controller) => {\n\t\t\tconst body = requestInstance.body;\n\n\t\t\tif (!body) return;\n\n\t\t\tconst requestStreamContext = {\n\t\t\t\tbaseConfig,\n\t\t\t\tconfig,\n\t\t\t\tevent: createProgressEvent({ chunk: new Uint8Array(), totalBytes, transferredBytes }),\n\t\t\t\toptions,\n\t\t\t\trequest,\n\t\t\t\trequestInstance,\n\t\t\t} satisfies RequestStreamContext;\n\n\t\t\tawait executeHooksInTryBlock(options.onRequestStream?.(requestStreamContext));\n\n\t\t\tfor await (const chunk of body) {\n\t\t\t\ttransferredBytes += chunk.byteLength;\n\n\t\t\t\ttotalBytes = Math.max(totalBytes, transferredBytes);\n\n\t\t\t\tawait executeHooksInTryBlock(\n\t\t\t\t\toptions.onRequestStream?.({\n\t\t\t\t\t\t...requestStreamContext,\n\t\t\t\t\t\tevent: createProgressEvent({ chunk, totalBytes, transferredBytes }),\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tcontroller.enqueue(chunk);\n\t\t\t}\n\n\t\t\tcontroller.close();\n\t\t},\n\t});\n\n\treturn new Request(requestInstance, { body: stream, duplex: \"half\" } as RequestInit);\n};\n\ntype StreamableResponseContext = RequestContext & { response: Response };\n\nexport const toStreamableResponse = async (context: StreamableResponseContext): Promise<Response> => {\n\tconst { baseConfig, config, options, request, response } = context;\n\n\tif (!options.onResponseStream || !response.body) {\n\t\treturn response;\n\t}\n\n\tconst contentLength = response.headers.get(\"content-length\");\n\n\tlet totalBytes = Number(contentLength ?? 0);\n\n\tconst shouldForceContentLengthCalc =\n\t\tisObject(options.forcefullyCalculateStreamSize) ?\n\t\t\toptions.forcefullyCalculateStreamSize.response\n\t\t:\toptions.forcefullyCalculateStreamSize;\n\n\t// == If no content length is present and `forceContentLengthCalculation` is enabled, we read the total bytes from the body\n\tif (!contentLength && shouldForceContentLengthCalc) {\n\t\ttotalBytes = await calculateTotalBytesFromBody(response.clone().body, totalBytes);\n\t}\n\n\tlet transferredBytes = 0;\n\n\tconst stream = new ReadableStream({\n\t\tstart: async (controller) => {\n\t\t\tconst body = response.body;\n\n\t\t\tif (!body) return;\n\n\t\t\tconst responseStreamContext = {\n\t\t\t\tbaseConfig,\n\t\t\t\tconfig,\n\t\t\t\tevent: createProgressEvent({ chunk: new Uint8Array(), totalBytes, transferredBytes }),\n\t\t\t\toptions,\n\t\t\t\trequest,\n\t\t\t\tresponse,\n\t\t\t} satisfies ResponseStreamContext;\n\n\t\t\tawait executeHooksInTryBlock(options.onResponseStream?.(responseStreamContext));\n\n\t\t\tfor await (const chunk of body) {\n\t\t\t\ttransferredBytes += chunk.byteLength;\n\n\t\t\t\ttotalBytes = Math.max(totalBytes, transferredBytes);\n\n\t\t\t\tawait executeHooksInTryBlock(\n\t\t\t\t\toptions.onResponseStream?.({\n\t\t\t\t\t\t...responseStreamContext,\n\t\t\t\t\t\tevent: createProgressEvent({ chunk, totalBytes, transferredBytes }),\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tcontroller.enqueue(chunk);\n\t\t\t}\n\n\t\t\tcontroller.close();\n\t\t},\n\t});\n\n\treturn new Response(stream, response);\n};\n","import { extraOptionDefaults } from \"./constants/default-options\";\nimport type { RequestContext } from \"./hooks\";\nimport { toStreamableRequest, toStreamableResponse } from \"./stream\";\nimport type { AnyString, UnmaskType } from \"./types/type-helpers\";\nimport { deterministicHashFn, getFetchImpl, waitFor } from \"./utils/common\";\nimport { isFunction } from \"./utils/guards\";\n\ntype RequestInfo = {\n\tcontroller: AbortController;\n\tresponsePromise: Promise<Response>;\n};\n\n/**\n * Cache that stores active request information for deduplication within a specific scope.\n *\n * Maps deduplication keys to their corresponding request information, including the abort controller\n * and response promise. A `null` key represents requests that don't participate in deduplication.\n *\n * **Internal Usage:**\n * This type is primarily used internally by the deduplication system. You typically won't need to\n * interact with it directly unless you're building custom deduplication logic or debugging.\n *\n * @example\n * ```ts\n * // This is handled internally, but conceptually:\n * const cache: RequestInfoCache = new Map([\n * [\"user-123\", { controller: abortController, responsePromise: fetchPromise }],\n * [\"config\", { controller: abortController2, responsePromise: fetchPromise2 }],\n * ]);\n * ```\n */\nexport type RequestInfoCache = Map<string | null, RequestInfo>;\n\n/**\n * Global cache that manages multiple request info caches, organized by scope keys.\n *\n * This enables the global deduplication feature by maintaining separate cache namespaces\n * for different scope keys. Each scope key gets its own `RequestInfoCache` instance.\n *\n * **Cache Lifecycle:**\n * - Caches are created on-demand when first accessed\n * - Automatic cleanup occurs when no references remain\n * - Each scope key maintains independent deduplication state\n *\n * **Memory Considerations:**\n * - Each scope key creates a separate cache instance\n * - Consider the number of different scope keys in your application\n * - Caches are cleaned up automatically when clients are garbage collected\n *\n * @example\n * ```ts\n * // This is managed internally, but conceptually:\n * const globalCache: GlobalRequestInfoCache = new Map([\n * [\"user-service\", new Map([...])], // Cache for user service requests\n * [\"analytics\", new Map([...])], // Cache for analytics requests\n * [\"default\", new Map([...])] // Default cache scope\n * ]);\n * ```\n */\nexport type GlobalRequestInfoCache = Map<DedupeOptions[\"dedupeCacheScopeKey\"], RequestInfoCache>;\n\ntype DedupeContext = RequestContext & {\n\t$GlobalRequestInfoCache: GlobalRequestInfoCache;\n\t$LocalRequestInfoCache: RequestInfoCache;\n\tnewFetchController: AbortController;\n};\n\nexport const createDedupeStrategy = async (context: DedupeContext) => {\n\tconst {\n\t\t$GlobalRequestInfoCache,\n\t\t$LocalRequestInfoCache,\n\t\tbaseConfig,\n\t\tconfig,\n\t\tnewFetchController,\n\t\toptions: globalOptions,\n\t\trequest: globalRequest,\n\t} = context;\n\n\tconst dedupeStrategy = globalOptions.dedupeStrategy ?? extraOptionDefaults().dedupeStrategy;\n\n\tconst resolvedDedupeStrategy = isFunction(dedupeStrategy) ? dedupeStrategy(context) : dedupeStrategy;\n\n\tconst getDedupeKey = () => {\n\t\tconst shouldHaveDedupeKey =\n\t\t\tresolvedDedupeStrategy === \"cancel\" || resolvedDedupeStrategy === \"defer\";\n\n\t\tif (!shouldHaveDedupeKey) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (globalOptions.dedupeKey) {\n\t\t\tconst resolvedDedupeKey =\n\t\t\t\tisFunction(globalOptions.dedupeKey) ?\n\t\t\t\t\tglobalOptions.dedupeKey(context)\n\t\t\t\t:\tglobalOptions.dedupeKey;\n\n\t\t\treturn resolvedDedupeKey;\n\t\t}\n\n\t\treturn `${globalOptions.fullURL}-${deterministicHashFn({ options: globalOptions, request: globalRequest })}`;\n\t};\n\n\tconst dedupeKey = getDedupeKey();\n\n\tconst dedupeCacheScope = globalOptions.dedupeCacheScope ?? extraOptionDefaults().dedupeCacheScope;\n\n\tconst dedupeCacheScopeKey =\n\t\tglobalOptions.dedupeCacheScopeKey ?? extraOptionDefaults().dedupeCacheScopeKey;\n\n\tif (dedupeCacheScope === \"global\" && !$GlobalRequestInfoCache.has(dedupeCacheScopeKey)) {\n\t\t$GlobalRequestInfoCache.set(dedupeCacheScopeKey, new Map());\n\t}\n\n\tconst $RequestInfoCache =\n\t\tdedupeCacheScope === \"global\" ?\n\t\t\t$GlobalRequestInfoCache.get(dedupeCacheScopeKey)\n\t\t:\t$LocalRequestInfoCache;\n\n\t// == This is to ensure cache operations only occur when key is available\n\tconst $RequestInfoCacheOrNull = dedupeKey !== null ? $RequestInfoCache : null;\n\n\t/******\n\t * == Add a small delay to the execution to ensure proper request deduplication when multiple requests with the same key start simultaneously.\n\t * == This gives time for the cache to be updated with the previous request info before the next request checks it.\n\t ******/\n\tif (dedupeKey !== null) {\n\t\tawait waitFor(0.1);\n\t}\n\n\tconst prevRequestInfo = $RequestInfoCacheOrNull?.get(dedupeKey);\n\n\tconst getAbortErrorMessage = () => {\n\t\tif (globalOptions.dedupeKey) {\n\t\t\treturn `Duplicate request detected - Aborted previous request with key '${dedupeKey}' as a new request was initiated`;\n\t\t}\n\n\t\treturn `Duplicate request detected - Aborted previous request to '${globalOptions.fullURL}' as a new request with identical options was initiated`;\n\t};\n\n\tconst handleRequestCancelStrategy = () => {\n\t\tconst shouldCancelRequest = prevRequestInfo && resolvedDedupeStrategy === \"cancel\";\n\n\t\tif (!shouldCancelRequest) return;\n\n\t\tconst message = getAbortErrorMessage();\n\n\t\tconst reason = new DOMException(message, \"AbortError\");\n\n\t\tprevRequestInfo.controller.abort(reason);\n\n\t\t// == Adding this just so that eslint forces me put await when calling the function (it looks better that way tbh)\n\t\treturn Promise.resolve();\n\t};\n\n\tconst handleRequestDeferStrategy = async (deferContext: {\n\t\toptions: DedupeContext[\"options\"];\n\t\trequest: DedupeContext[\"request\"];\n\t}) => {\n\t\t// == Local options and request are needed so that transformations are applied can be applied to both from call site\n\t\tconst { options: localOptions, request: localRequest } = deferContext;\n\n\t\tconst fetchApi = getFetchImpl(localOptions.customFetchImpl);\n\n\t\tconst shouldUsePromiseFromCache = prevRequestInfo && resolvedDedupeStrategy === \"defer\";\n\n\t\tconst streamableContext = {\n\t\t\tbaseConfig,\n\t\t\tconfig,\n\t\t\toptions: localOptions,\n\t\t\trequest: localRequest,\n\t\t} satisfies RequestContext;\n\n\t\tconst streamableRequest = await toStreamableRequest(streamableContext);\n\n\t\tconst responsePromise =\n\t\t\tshouldUsePromiseFromCache ?\n\t\t\t\tprevRequestInfo.responsePromise\n\t\t\t:\tfetchApi(localOptions.fullURL as NonNullable<typeof localOptions.fullURL>, streamableRequest);\n\n\t\t$RequestInfoCacheOrNull?.set(dedupeKey, { controller: newFetchController, responsePromise });\n\n\t\tconst streamableResponse = toStreamableResponse({\n\t\t\t...streamableContext,\n\t\t\tresponse: await responsePromise,\n\t\t});\n\n\t\treturn streamableResponse;\n\t};\n\n\tconst removeDedupeKeyFromCache = () => {\n\t\t$RequestInfoCacheOrNull?.delete(dedupeKey);\n\t};\n\n\treturn {\n\t\tgetAbortErrorMessage,\n\t\thandleRequestCancelStrategy,\n\t\thandleRequestDeferStrategy,\n\t\tremoveDedupeKeyFromCache,\n\t\tresolvedDedupeStrategy,\n\t};\n};\n\ntype DedupeStrategyUnion = UnmaskType<\"cancel\" | \"defer\" | \"none\">;\n\nexport type DedupeOptions = {\n\t/**\n\t * Controls the scope of request deduplication caching.\n\t *\n\t * - `\"global\"`: Shares deduplication cache across all `createFetchClient` instances with the same `dedupeCacheScopeKey`.\n\t * Useful for applications with multiple API clients that should share deduplication state.\n\t * - `\"local\"`: Limits deduplication to requests within the same `createFetchClient` instance.\n\t * Provides better isolation and is recommended for most use cases.\n\t *\n\t *\n\t * **Real-world Scenarios:**\n\t * - Use `\"global\"` when you have multiple API clients (user service, auth service, etc.) that might make overlapping requests\n\t * - Use `\"local\"` (default) for single-purpose clients or when you want strict isolation between different parts of your app\n\t *\n\t * @example\n\t * ```ts\n\t * // Local scope - each client has its own deduplication cache\n\t * const userClient = createFetchClient({ baseURL: \"/api/users\" });\n\t * const postClient = createFetchClient({ baseURL: \"/api/posts\" });\n\t * // These clients won't share deduplication state\n\t *\n\t * // Global scope - share cache across related clients\n\t * const userClient = createFetchClient({\n\t * baseURL: \"/api/users\",\n\t * dedupeCacheScope: \"global\",\n\t * });\n\t * const postClient = createFetchClient({\n\t * baseURL: \"/api/posts\",\n\t * dedupeCacheScope: \"global\",\n\t * });\n\t * // These clients will share deduplication state\n\t * ```\n\t *\n\t * @default \"local\"\n\t */\n\tdedupeCacheScope?: \"global\" | \"local\";\n\n\t/**\n\t * Unique namespace for the global deduplication cache when using `dedupeCacheScope: \"global\"`.\n\t *\n\t * This creates logical groupings of deduplication caches. All instances with the same key\n\t * will share the same cache namespace, allowing fine-grained control over which clients\n\t * share deduplication state.\n\t *\n\t * **Best Practices:**\n\t * - Use descriptive names that reflect the logical grouping (e.g., \"user-service\", \"analytics-api\")\n\t * - Keep scope keys consistent across related API clients\n\t * - Consider using different scope keys for different environments (dev, staging, prod)\n\t * - Avoid overly broad scope keys that might cause unintended cache sharing\n\t *\n\t * **Cache Management:**\n\t * - Each scope key maintains its own independent cache\n\t * - Caches are automatically cleaned up when no references remain\n\t * - Consider the memory implications of multiple global scopes\n\t *\n\t * @example\n\t * ```ts\n\t * // Group related API clients together\n\t * const userClient = createFetchClient({\n\t * baseURL: \"/api/users\",\n\t * dedupeCacheScope: \"global\",\n\t * dedupeCacheScopeKey: \"user-service\"\n\t * });\n\t * const profileClient = createFetchClient({\n\t * baseURL: \"/api/profiles\",\n\t * dedupeCacheScope: \"global\",\n\t * dedupeCacheScopeKey: \"user-service\" // Same scope - will share cache\n\t * });\n\t *\n\t * // Separate analytics client with its own cache\n\t * const analyticsClient = createFetchClient({\n\t * baseURL: \"/api/analytics\",\n\t * dedupeCacheScope: \"global\",\n\t * dedupeCacheScopeKey: \"analytics-service\" // Different scope\n\t * });\n\t *\n\t * // Environment-specific scoping\n\t * const apiClient = createFetchClient({\n\t * dedupeCacheScope: \"global\",\n\t * dedupeCacheScopeKey: `api-${process.env.NODE_ENV}` // \"api-development\", \"api-production\", etc.\n\t * });\n\t * ```\n\t *\n\t * @default \"default\"\n\t */\n\tdedupeCacheScopeKey?: \"default\" | AnyString;\n\n\t/**\n\t * Custom key generator for request deduplication.\n\t *\n\t * Override the default key generation strategy to control exactly which requests\n\t * are considered duplicates. The default key combines URL, method, body, and\n\t * relevant headers (excluding volatile ones like 'Date', 'Authorization', etc.).\n\t *\n\t * **Default Key Generation:**\n\t * The auto-generated key includes:\n\t * - Full request URL (including query parameters)\n\t * - HTTP method (GET, POST, etc.)\n\t * - Request body (for POST/PUT/PATCH requests)\n\t * - Stable headers (excludes Date, Authorization, User-Agent, etc.)\n\t *\n\t * **Custom Key Best Practices:**\n\t * - Include only the parts of the request that should affect deduplication\n\t * - Avoid including volatile data (timestamps, random IDs, etc.)\n\t * - Consider performance - simpler keys are faster to compute and compare\n\t * - Ensure keys are deterministic for the same logical request\n\t * - Use consistent key formats across your application\n\t *\n\t * **Performance Considerations:**\n\t * - Function-based keys are computed on every request - keep them lightweight\n\t * - String keys are fastest but least flexible\n\t * - Consider caching expensive key computations if needed\n\t *\n\t * @example\n\t * ```ts\n\t * import { callApi } from \"@zayne-labs/callapi\";\n\t *\n\t * // Simple static key - useful for singleton requests\n\t * const config = callApi(\"/api/config\", {\n\t * dedupeKey: \"app-config\",\n\t * dedupeStrategy: \"defer\" // Share the same config across all requests\n\t * });\n\t *\n\t * // URL and method only - ignore headers and body\n\t * const userData = callApi(\"/api/user/123\", {\n\t * dedupeKey: (context) => `${context.options.method}:${context.options.fullURL}`\n\t * });\n\t *\n\t * // Include specific headers in deduplication\n\t * const apiCall = callApi(\"/api/data\", {\n\t * dedupeKey: (context) => {\n\t * const authHeader = context.request.headers.get(\"Authorization\");\n\t * return `${context.options.fullURL}-${authHeader}`;\n\t * }\n\t * });\n\t *\n\t * // User-specific deduplication\n\t * const userSpecificCall = callApi(\"/api/dashboard\", {\n\t * dedupeKey: (context) => {\n\t * const userId = context.options.fullURL.match(/user\\/(\\d+)/)?.[1];\n\t * return `dashboard-${userId}`;\n\t * }\n\t * });\n\t *\n\t * // Ignore certain query parameters\n\t * const searchCall = callApi(\"/api/search?q=test&timestamp=123456\", {\n\t * dedupeKey: (context) => {\n\t * const url = new URL(context.options.fullURL);\n\t * url.searchParams.delete(\"timestamp\"); // Remove volatile param\n\t * return `search:${url.toString()}`;\n\t * }\n\t * });\n\t * ```\n\t *\n\t * @default Auto-generated from request details\n\t */\n\tdedupeKey?: string | ((context: RequestContext) => string);\n\n\t/**\n\t * Strategy for handling duplicate requests. Can be a static string or callback function.\n\t *\n\t * **Available Strategies:**\n\t * - `\"cancel\"`: Cancel previous request when new one starts (good for search)\n\t * - `\"defer\"`: Share response between duplicate requests (good for config loading)\n\t * - `\"none\"`: No deduplication, all requests execute independently\n\t *\n\t * @example\n\t * ```ts\n\t * // Static strategies\n\t * const searchClient = createFetchClient({\n\t * dedupeStrategy: \"cancel\" // Cancel previous searches\n\t * });\n\t *\n\t * const configClient = createFetchClient({\n\t * dedupeStrategy: \"defer\" // Share config across components\n\t * });\n\t *\n\t * // Dynamic strategy based on request\n\t * const smartClient = createFetchClient({\n\t * dedupeStrategy: (context) => {\n\t * return context.options.method === \"GET\" ? \"defer\" : \"cancel\";\n\t * }\n\t * });\n\t *\n\t * // Search-as-you-type with cancel strategy\n\t * const handleSearch = async (query: string) => {\n\t * try {\n\t * const { data } = await callApi(\"/api/search\", {\n\t * method: \"POST\",\n\t * body: { query },\n\t * dedupeStrategy: \"cancel\",\n\t * dedupeKey: \"search\" // Cancel previous searches, only latest one goes through\n\t * });\n\t *\n\t * updateSearchResults(data);\n\t * } catch (error) {\n\t * if (error.name === \"AbortError\") {\n\t * // Previous search cancelled - (expected behavior)\n\t * return;\n\t * }\n\t * console.error(\"Search failed:\", error);\n\t * }\n\t * };\n\t *\n\t * ```\n\t *\n\t * @default \"cancel\"\n\t */\n\tdedupeStrategy?: DedupeStrategyUnion | ((context: RequestContext) => DedupeStrategyUnion);\n};\n","import { extraOptionDefaults } from \"./constants/default-options\";\nimport {\n\tcomposeAllHooks,\n\tgetHookRegistries,\n\ttype Hooks,\n\ttype HooksOrHooksArray,\n\ttype PluginExtraOptions,\n\ttype RequestContext,\n} from \"./hooks\";\nimport type { CallApiRequestOptions, CallApiRequestOptionsForHooks } from \"./types/common\";\nimport type { Awaitable } from \"./types/type-helpers\";\nimport type { InitURLOrURLObject } from \"./url\";\nimport { isArray, isFunction, isPlainObject, isString } from \"./utils/guards\";\nimport { type BaseCallApiSchemaAndConfig, getCurrentRouteSchemaKeyAndMainInitURL } from \"./validation\";\n\nexport type PluginSetupContext<TPluginExtraOptions = unknown> = RequestContext // eslint-disable-next-line perfectionist/sort-intersection-types -- Allow\n\t& PluginExtraOptions<TPluginExtraOptions> & { initURL: string };\n\nexport type PluginInitResult = Partial<\n\tOmit<PluginSetupContext, \"initURL\" | \"request\"> & {\n\t\tinitURL: InitURLOrURLObject;\n\t\trequest: CallApiRequestOptions;\n\t}\n>;\n\nexport type PluginHooksWithMoreOptions<TMoreOptions = unknown> = HooksOrHooksArray<\n\tnever,\n\tnever,\n\tTMoreOptions\n>;\n\nexport type PluginHooks<TData = never, TErrorData = never, TMoreOptions = unknown> = HooksOrHooksArray<\n\tTData,\n\tTErrorData,\n\tTMoreOptions\n>;\n\nexport interface CallApiPlugin {\n\t/**\n\t * Defines additional options that can be passed to callApi\n\t */\n\tdefineExtraOptions?: (...params: never[]) => unknown;\n\n\t/**\n\t * A description for the plugin\n\t */\n\tdescription?: string;\n\n\t/**\n\t * Hooks / Interceptors for the plugin\n\t */\n\thooks?: PluginHooks;\n\n\t/**\n\t * A unique id for the plugin\n\t */\n\tid: string;\n\n\t/**\n\t * A name for the plugin\n\t */\n\tname: string;\n\n\t/**\n\t * Base schema for the client.\n\t */\n\tschema?: BaseCallApiSchemaAndConfig;\n\n\t/**\n\t * A function that will be called when the plugin is initialized. This will be called before the any of the other internal functions.\n\t */\n\tsetup?: (context: PluginSetupContext) => Awaitable<PluginInitResult> | Awaitable<void>;\n\n\t/**\n\t * A version for the plugin\n\t */\n\tversion?: string;\n}\n\nexport const getResolvedPlugins = (context: Pick<RequestContext, \"baseConfig\" | \"options\">) => {\n\tconst { baseConfig, options } = context;\n\n\tconst resolvedPlugins =\n\t\tisFunction(options.plugins) ?\n\t\t\toptions.plugins({ basePlugins: baseConfig.plugins ?? [] })\n\t\t:\t(options.plugins ?? []);\n\n\treturn resolvedPlugins;\n};\n\nexport const initializePlugins = async (context: PluginSetupContext) => {\n\tconst { baseConfig, config, initURL, options, request } = context;\n\n\tconst hookRegistries = getHookRegistries();\n\n\tconst hookRegistryKeyArray = Object.keys(hookRegistries) as Array<keyof Hooks>;\n\n\tconst addMainHooks = () => {\n\t\tfor (const key of hookRegistryKeyArray) {\n\t\t\tconst overriddenHook = options[key];\n\t\t\tconst baseHook = baseConfig[key];\n\t\t\tconst instanceHook = config[key];\n\n\t\t\t// == If the base hook is an array and instance hook is defined, we need to compose the base hook with the instance hook\n\t\t\tconst mainHook =\n\t\t\t\tisArray(baseHook) && Boolean(instanceHook) ? [baseHook, instanceHook].flat() : overriddenHook;\n\n\t\t\tif (!mainHook) continue;\n\n\t\t\thookRegistries[key].add(mainHook as never);\n\t\t}\n\t};\n\n\tconst addPluginHooks = (pluginHooks: Required<CallApiPlugin>[\"hooks\"]) => {\n\t\tfor (const key of hookRegistryKeyArray) {\n\t\t\tconst pluginHook = pluginHooks[key];\n\n\t\t\tif (!pluginHook) continue;\n\n\t\t\thookRegistries[key].add(pluginHook as never);\n\t\t}\n\t};\n\n\tconst hookRegistrationOrder =\n\t\toptions.hooksRegistrationOrder ?? extraOptionDefaults().hooksRegistrationOrder;\n\n\tif (hookRegistrationOrder === \"mainFirst\") {\n\t\taddMainHooks();\n\t}\n\n\tconst { currentRouteSchemaKey, mainInitURL } = getCurrentRouteSchemaKeyAndMainInitURL({\n\t\tbaseExtraOptions: baseConfig,\n\t\textraOptions: config,\n\t\tinitURL,\n\t});\n\n\tlet resolvedCurrentRouteSchemaKey = currentRouteSchemaKey;\n\tlet resolvedInitURL = mainInitURL;\n\tlet resolvedOptions = options;\n\tlet resolvedRequestOptions = request;\n\n\tconst executePluginSetupFn = async (pluginSetupFn: CallApiPlugin[\"setup\"]) => {\n\t\tif (!pluginSetupFn) return;\n\n\t\tconst initResult = await pluginSetupFn({\n\t\t\tbaseConfig,\n\t\t\tconfig,\n\t\t\tinitURL,\n\t\t\toptions,\n\t\t\trequest,\n\t\t});\n\n\t\tif (!isPlainObject(initResult)) return;\n\n\t\tconst urlString = initResult.initURL?.toString();\n\n\t\tif (isString(urlString)) {\n\t\t\tconst newResult = getCurrentRouteSchemaKeyAndMainInitURL({\n\t\t\t\tbaseExtraOptions: baseConfig,\n\t\t\t\textraOptions: config,\n\t\t\t\tinitURL: urlString,\n\t\t\t});\n\n\t\t\tresolvedCurrentRouteSchemaKey = newResult.currentRouteSchemaKey;\n\t\t\tresolvedInitURL = newResult.mainInitURL;\n\t\t}\n\n\t\tif (isPlainObject(initResult.request)) {\n\t\t\tresolvedRequestOptions = initResult.request as CallApiRequestOptionsForHooks;\n\t\t}\n\n\t\tif (isPlainObject(initResult.options)) {\n\t\t\tresolvedOptions = initResult.options;\n\t\t}\n\t};\n\n\tconst resolvedPlugins = getResolvedPlugins({ baseConfig, options });\n\n\tfor (const plugin of resolvedPlugins) {\n\t\t// eslint-disable-next-line no-await-in-loop -- Await is necessary in this case.\n\t\tawait executePluginSetupFn(plugin.setup);\n\n\t\tif (!plugin.hooks) continue;\n\n\t\taddPluginHooks(plugin.hooks);\n\t}\n\n\tif (hookRegistrationOrder === \"pluginsFirst\") {\n\t\taddMainHooks();\n\t}\n\n\tconst resolvedHooks: Hooks = {};\n\n\tfor (const [key, hookRegistry] of Object.entries(hookRegistries)) {\n\t\tif (hookRegistry.size === 0) continue;\n\n\t\t// == Flatten the hook registry to remove any nested arrays, incase an array of hooks is passed to any of the hooks\n\t\tconst flattenedHookArray = [...hookRegistry].flat();\n\n\t\tif (flattenedHookArray.length === 0) continue;\n\n\t\tconst hooksExecutionMode = options.hooksExecutionMode ?? extraOptionDefaults().hooksExecutionMode;\n\n\t\tconst composedHook = composeAllHooks(flattenedHookArray, hooksExecutionMode);\n\n\t\tresolvedHooks[key as keyof Hooks] = composedHook;\n\t}\n\n\treturn {\n\t\tresolvedCurrentRouteSchemaKey,\n\t\tresolvedHooks,\n\t\tresolvedInitURL,\n\t\tresolvedOptions,\n\t\tresolvedRequestOptions,\n\t};\n};\n","import { extraOptionDefaults } from \"./constants/default-options\";\nimport type { ErrorContext, RequestContext } from \"./hooks\";\nimport type { MethodUnion } from \"./types\";\nimport { type AnyNumber, type Awaitable, defineEnum, type UnmaskType } from \"./types/type-helpers\";\nimport { isBoolean, isFunction, isString } from \"./utils/guards\";\n\n// eslint-disable-next-line ts-eslint/no-unused-vars -- Ignore\nconst defaultRetryStatusCodesLookup = () =>\n\tdefineEnum({\n\t\t408: \"Request Timeout\",\n\t\t409: \"Conflict\",\n\t\t425: \"Too Early\",\n\t\t429: \"Too Many Requests\",\n\t\t500: \"Internal Server Error\",\n\t\t502: \"Bad Gateway\",\n\t\t503: \"Service Unavailable\",\n\t\t504: \"Gateway Timeout\",\n\t});\n\ntype RetryStatusCodes = UnmaskType<AnyNumber | keyof ReturnType<typeof defaultRetryStatusCodesLookup>>;\n\ntype RetryCondition<TErrorData> = (context: ErrorContext<TErrorData>) => Awaitable<boolean>;\n\ntype InnerRetryKeys<TErrorData> = Exclude<keyof RetryOptions<TErrorData>, \"~retryAttemptCount\" | \"retry\">;\n\ntype InnerRetryOptions<TErrorData> = {\n\t[Key in InnerRetryKeys<TErrorData> as Key extends `retry${infer TRest}` ?\n\t\tUncapitalize<TRest> extends \"attempts\" ?\n\t\t\tnever\n\t\t:\tUncapitalize<TRest>\n\t:\tKey]?: RetryOptions<TErrorData>[Key];\n} & {\n\tattempts: NonNullable<RetryOptions<TErrorData>[\"retryAttempts\"]>;\n};\n\nexport interface RetryOptions<TErrorData> {\n\t/**\n\t * Keeps track of the number of times the request has already been retried\n\t *\n\t * @deprecated **NOTE**: This property is used internally to track retries. Please abstain from modifying it.\n\t */\n\treadonly [\"~retryAttemptCount\"]?: number;\n\n\t/**\n\t * All retry options in a single object instead of separate properties\n\t */\n\tretry?: InnerRetryOptions<TErrorData>;\n\n\t/**\n\t * Number of allowed retry attempts on HTTP errors\n\t * @default 0\n\t */\n\tretryAttempts?: number;\n\n\t/**\n\t * Callback whose return value determines if a request should be retried or not\n\t */\n\tretryCondition?: RetryCondition<TErrorData>;\n\n\t/**\n\t * Delay between retries in milliseconds\n\t * @default 1000\n\t */\n\tretryDelay?: number | ((currentAttemptCount: number) => number);\n\n\t/**\n\t * Maximum delay in milliseconds. Only applies to exponential strategy\n\t * @default 10000\n\t */\n\tretryMaxDelay?: number;\n\n\t/**\n\t * HTTP methods that are allowed to retry\n\t * @default [\"GET\", \"POST\"]\n\t */\n\tretryMethods?: MethodUnion[];\n\n\t/**\n\t * HTTP status codes that trigger a retry\n\t */\n\tretryStatusCodes?: RetryStatusCodes[];\n\n\t/**\n\t * Strategy to use when retrying\n\t * @default \"linear\"\n\t */\n\tretryStrategy?: \"exponential\" | \"linear\";\n}\n\nconst getLinearDelay = (currentAttemptCount: number, options: RetryOptions<unknown>) => {\n\tconst retryDelay = options.retryDelay ?? options.retry?.delay;\n\n\tconst resolveRetryDelay =\n\t\t(isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay)\n\t\t?? extraOptionDefaults().retryDelay;\n\n\treturn resolveRetryDelay;\n};\n\nconst getExponentialDelay = (currentAttemptCount: number, options: RetryOptions<unknown>) => {\n\tconst retryDelay = options.retryDelay ?? options.retry?.delay ?? extraOptionDefaults().retryDelay;\n\n\tconst resolvedRetryDelay = isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay;\n\n\tconst maxDelay =\n\t\toptions.retryMaxDelay ?? options.retry?.maxDelay ?? extraOptionDefaults().retryMaxDelay;\n\n\tconst exponentialDelay = resolvedRetryDelay * 2 ** currentAttemptCount;\n\n\treturn Math.min(exponentialDelay, maxDelay);\n};\n\nexport const createRetryStrategy = (ctx: ErrorContext<unknown> & RequestContext) => {\n\tconst { options, request } = ctx;\n\n\t// eslint-disable-next-line ts-eslint/no-deprecated -- Allowed for internal use\n\tconst currentAttemptCount = options[\"~retryAttemptCount\"] ?? 1;\n\n\tconst retryStrategy =\n\t\toptions.retryStrategy ?? options.retry?.strategy ?? extraOptionDefaults().retryStrategy;\n\n\tconst getDelay = () => {\n\t\tswitch (retryStrategy) {\n\t\t\tcase \"exponential\": {\n\t\t\t\treturn getExponentialDelay(currentAttemptCount, options);\n\t\t\t}\n\t\t\tcase \"linear\": {\n\t\t\t\treturn getLinearDelay(currentAttemptCount, options);\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow new Error(`Invalid retry strategy: ${String(retryStrategy)}`);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst shouldAttemptRetry = async () => {\n\t\tif (isBoolean(request.signal) && request.signal.aborted) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst retryCondition =\n\t\t\toptions.retryCondition ?? options.retry?.condition ?? extraOptionDefaults().retryCondition;\n\n\t\tconst maximumRetryAttempts =\n\t\t\toptions.retryAttempts ?? options.retry?.attempts ?? extraOptionDefaults().retryAttempts;\n\n\t\tconst customRetryCondition = await retryCondition(ctx);\n\n\t\tconst baseShouldRetry = currentAttemptCount <= maximumRetryAttempts && customRetryCondition;\n\n\t\tif (!baseShouldRetry) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst retryMethods = new Set(\n\t\t\toptions.retryMethods ?? options.retry?.methods ?? extraOptionDefaults().retryMethods\n\t\t);\n\n\t\tconst includesMethod =\n\t\t\tisString(ctx.request.method) && retryMethods.size > 0 ?\n\t\t\t\tretryMethods.has(ctx.request.method)\n\t\t\t:\ttrue;\n\n\t\tconst retryStatusCodes = new Set(\n\t\t\toptions.retryStatusCodes ?? options.retry?.statusCodes ?? extraOptionDefaults().retryStatusCodes\n\t\t);\n\n\t\tconst includesStatusCodes =\n\t\t\tctx.response != null && retryStatusCodes.size > 0 ?\n\t\t\t\tretryStatusCodes.has(ctx.response.status)\n\t\t\t:\ttrue;\n\n\t\tconst shouldRetry = includesMethod && includesStatusCodes;\n\n\t\treturn shouldRetry;\n\t};\n\n\treturn {\n\t\tcurrentAttemptCount,\n\t\tgetDelay,\n\t\tshouldAttemptRetry,\n\t};\n};\n","import { createDedupeStrategy, type GlobalRequestInfoCache, type RequestInfoCache } from \"./dedupe\";\nimport { HTTPError } from \"./error\";\nimport {\n\ttype ErrorContext,\n\ttype ExecuteHookInfo,\n\texecuteHooksInCatchBlock,\n\texecuteHooksInTryBlock,\n\ttype RetryContext,\n\ttype SuccessContext,\n} from \"./hooks\";\nimport { type CallApiPlugin, initializePlugins } from \"./plugins\";\nimport {\n\ttype ErrorInfo,\n\ttype GetResponseType,\n\tgetCustomizedErrorResult,\n\ttype ResponseTypeUnion,\n\ttype ResultModeUnion,\n\tresolveErrorResult,\n\tresolveResponseData,\n\tresolveSuccessResult,\n} from \"./result\";\nimport { createRetryStrategy } from \"./retry\";\nimport type {\n\tGetCurrentRouteSchema,\n\tGetCurrentRouteSchemaKey,\n\tInferHeadersOption,\n\tInferInitURL,\n\tThrowOnErrorUnion,\n} from \"./types\";\nimport type {\n\tBaseCallApiConfig,\n\tBaseCallApiExtraOptions,\n\tCallApiExtraOptions,\n\tCallApiExtraOptionsForHooks,\n\tCallApiParameters,\n\tCallApiRequestOptions,\n\tCallApiRequestOptionsForHooks,\n\tCallApiResult,\n} from \"./types/common\";\nimport type { DefaultDataType, DefaultPluginArray, DefaultThrowOnError } from \"./types/default-types\";\nimport type { AnyFunction, Writeable } from \"./types/type-helpers\";\nimport { getFullAndNormalizedURL } from \"./url\";\nimport {\n\tcreateCombinedSignal,\n\tcreateTimeoutSignal,\n\tgetBody,\n\tgetHeaders,\n\tgetMethod,\n\tsplitBaseConfig,\n\tsplitConfig,\n\twaitFor,\n} from \"./utils/common\";\nimport { isFunction, isHTTPErrorInstance, isValidationErrorInstance } from \"./utils/guards\";\nimport {\n\ttype BaseCallApiSchemaAndConfig,\n\ttype BaseCallApiSchemaRoutes,\n\ttype CallApiSchema,\n\ttype CallApiSchemaConfig,\n\thandleConfigValidation,\n\thandleSchemaValidation,\n\ttype InferSchemaOutputResult,\n} from \"./validation\";\n\nconst $GlobalRequestInfoCache: GlobalRequestInfoCache = new Map();\n\nexport const createFetchClient = <\n\tTBaseData = DefaultDataType,\n\tTBaseErrorData = DefaultDataType,\n\tTBaseResultMode extends ResultModeUnion = ResultModeUnion,\n\tTBaseThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError,\n\tTBaseResponseType extends ResponseTypeUnion = ResponseTypeUnion,\n\tconst TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig,\n\tconst TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray,\n\tTComputedBaseSchemaConfig extends CallApiSchemaConfig = NonNullable<\n\t\tWriteable<TBaseSchemaAndConfig[\"config\"], \"deep\">\n\t>,\n\tTComputedBaseSchemaRoutes extends BaseCallApiSchemaRoutes = Writeable<\n\t\tTBaseSchemaAndConfig[\"routes\"],\n\t\t\"deep\"\n\t>,\n>(\n\tinitBaseConfig: BaseCallApiConfig<\n\t\tTBaseData,\n\t\tTBaseErrorData,\n\t\tTBaseResultMode,\n\t\tTBaseThrowOnError,\n\t\tTBaseResponseType,\n\t\tTBaseSchemaAndConfig,\n\t\tTBasePluginArray\n\t> = {} as never\n) => {\n\tconst $LocalRequestInfoCache: RequestInfoCache = new Map();\n\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t\tTThrowOnError extends ThrowOnErrorUnion = TBaseThrowOnError,\n\t\tTResponseType extends ResponseTypeUnion = TBaseResponseType,\n\t\tconst TSchemaConfig extends CallApiSchemaConfig = TComputedBaseSchemaConfig,\n\t\tTInitURL extends InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig> = InferInitURL<\n\t\t\tTComputedBaseSchemaRoutes,\n\t\t\tTSchemaConfig\n\t\t>,\n\t\tTCurrentRouteSchemaKey extends GetCurrentRouteSchemaKey<\n\t\t\tTSchemaConfig,\n\t\t\tTInitURL\n\t\t> = GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL>,\n\t\tconst TSchema extends CallApiSchema = GetCurrentRouteSchema<\n\t\t\tTComputedBaseSchemaRoutes,\n\t\t\tTCurrentRouteSchemaKey\n\t\t>,\n\t\tconst TPluginArray extends CallApiPlugin[] = TBasePluginArray,\n\t>(\n\t\t...parameters: CallApiParameters<\n\t\t\tInferSchemaOutputResult<TSchema[\"data\"], GetResponseType<TData, TResponseType>>,\n\t\t\tInferSchemaOutputResult<TSchema[\"errorData\"], GetResponseType<TErrorData, TResponseType>>,\n\t\t\tTResultMode,\n\t\t\tTThrowOnError,\n\t\t\tTResponseType,\n\t\t\tTComputedBaseSchemaRoutes,\n\t\t\tTSchema,\n\t\t\tTComputedBaseSchemaConfig,\n\t\t\tTSchemaConfig,\n\t\t\tTInitURL,\n\t\t\tTCurrentRouteSchemaKey,\n\t\t\tTBasePluginArray,\n\t\t\tTPluginArray\n\t\t>\n\t): CallApiResult<\n\t\tInferSchemaOutputResult<TSchema[\"data\"], TData>,\n\t\tInferSchemaOutputResult<TSchema[\"errorData\"], TErrorData>,\n\t\tTResultMode,\n\t\tTThrowOnError,\n\t\tTResponseType\n\t> => {\n\t\tconst [initURLOrURLObject, initConfig = {}] = parameters;\n\n\t\tconst [fetchOptions, extraOptions] = splitConfig(initConfig);\n\n\t\tconst resolvedBaseConfig =\n\t\t\tisFunction(initBaseConfig) ?\n\t\t\t\tinitBaseConfig({\n\t\t\t\t\tinitURL: initURLOrURLObject.toString(),\n\t\t\t\t\toptions: extraOptions,\n\t\t\t\t\trequest: fetchOptions,\n\t\t\t\t})\n\t\t\t:\tinitBaseConfig;\n\n\t\tconst baseConfig = resolvedBaseConfig as BaseCallApiExtraOptions & CallApiRequestOptions;\n\t\tconst config = initConfig as CallApiExtraOptions & CallApiRequestOptions;\n\n\t\tconst [baseFetchOptions, baseExtraOptions] = splitBaseConfig(baseConfig);\n\n\t\tconst shouldSkipAutoMergeForOptions =\n\t\t\tbaseExtraOptions.skipAutoMergeFor === \"all\" || baseExtraOptions.skipAutoMergeFor === \"options\";\n\n\t\tconst shouldSkipAutoMergeForRequest =\n\t\t\tbaseExtraOptions.skipAutoMergeFor === \"all\" || baseExtraOptions.skipAutoMergeFor === \"request\";\n\n\t\t// == Merged Extra Options\n\t\tconst mergedExtraOptions = {\n\t\t\t...baseExtraOptions,\n\t\t\t...(!shouldSkipAutoMergeForOptions && extraOptions),\n\t\t};\n\n\t\t// == Merged Request Options\n\t\tconst mergedRequestOptions = {\n\t\t\t// == Making sure headers is always an object\n\t\t\theaders: {},\n\t\t\t...baseFetchOptions,\n\t\t\t...(!shouldSkipAutoMergeForRequest && fetchOptions),\n\t\t} satisfies CallApiRequestOptions;\n\n\t\tconst {\n\t\t\tresolvedCurrentRouteSchemaKey,\n\t\t\tresolvedHooks,\n\t\t\tresolvedInitURL,\n\t\t\tresolvedOptions,\n\t\t\tresolvedRequestOptions,\n\t\t} = await initializePlugins({\n\t\t\tbaseConfig,\n\t\t\tconfig,\n\t\t\tinitURL: initURLOrURLObject.toString(),\n\t\t\toptions: mergedExtraOptions as CallApiExtraOptionsForHooks,\n\t\t\trequest: mergedRequestOptions as CallApiRequestOptionsForHooks,\n\t\t});\n\n\t\tconst { fullURL, normalizedInitURL } = getFullAndNormalizedURL({\n\t\t\tbaseURL: resolvedOptions.baseURL,\n\t\t\tinitURL: resolvedInitURL,\n\t\t\tparams: resolvedOptions.params,\n\t\t\tquery: resolvedOptions.query,\n\t\t});\n\n\t\tlet options = {\n\t\t\t...resolvedOptions,\n\t\t\t...resolvedHooks,\n\n\t\t\tfullURL,\n\t\t\tinitURL: resolvedInitURL,\n\t\t\tinitURLNormalized: normalizedInitURL,\n\t\t} satisfies CallApiExtraOptionsForHooks;\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tconst timeoutSignal = options.timeout != null ? createTimeoutSignal(options.timeout) : null;\n\n\t\tconst combinedSignal = createCombinedSignal(\n\t\t\tresolvedRequestOptions.signal,\n\t\t\ttimeoutSignal,\n\t\t\tnewFetchController.signal\n\t\t);\n\n\t\tlet request = {\n\t\t\t...resolvedRequestOptions,\n\n\t\t\tsignal: combinedSignal,\n\t\t} satisfies CallApiRequestOptionsForHooks;\n\n\t\tconst {\n\t\t\tgetAbortErrorMessage,\n\t\t\thandleRequestCancelStrategy,\n\t\t\thandleRequestDeferStrategy,\n\t\t\tremoveDedupeKeyFromCache,\n\t\t\tresolvedDedupeStrategy,\n\t\t} = await createDedupeStrategy({\n\t\t\t$GlobalRequestInfoCache,\n\t\t\t$LocalRequestInfoCache,\n\t\t\tbaseConfig,\n\t\t\tconfig,\n\t\t\tnewFetchController,\n\t\t\toptions,\n\t\t\trequest,\n\t\t});\n\n\t\ttry {\n\t\t\tawait handleRequestCancelStrategy();\n\n\t\t\tawait executeHooksInTryBlock(options.onBeforeRequest?.({ baseConfig, config, options, request }));\n\n\t\t\tconst {\n\t\t\t\textraOptionsValidationResult,\n\t\t\t\trequestOptionsValidationResult,\n\t\t\t\tresolvedSchema,\n\t\t\t\tresolvedSchemaConfig,\n\t\t\t\tshouldApplySchemaOutput,\n\t\t\t} = await handleConfigValidation({\n\t\t\t\tbaseExtraOptions,\n\t\t\t\tcurrentRouteSchemaKey: resolvedCurrentRouteSchemaKey,\n\t\t\t\textraOptions,\n\t\t\t\toptions,\n\t\t\t\trequestOptions: request,\n\t\t\t});\n\n\t\t\t// == Apply Schema Output for Extra Options\n\t\t\tif (shouldApplySchemaOutput) {\n\t\t\t\toptions = { ...options, ...extraOptionsValidationResult };\n\t\t\t}\n\n\t\t\t// == Apply Schema Output for Request Options\n\t\t\tconst rawBody = shouldApplySchemaOutput ? requestOptionsValidationResult?.body : request.body;\n\n\t\t\tconst validBody = getBody({\n\t\t\t\tbody: rawBody,\n\t\t\t\tbodySerializer: options.bodySerializer,\n\t\t\t});\n\n\t\t\ttype HeaderFn = Extract<InferHeadersOption<CallApiSchema>[\"headers\"], AnyFunction>;\n\n\t\t\tconst resolvedHeaders =\n\t\t\t\tisFunction<HeaderFn>(fetchOptions.headers) ?\n\t\t\t\t\tfetchOptions.headers({ baseHeaders: baseFetchOptions.headers ?? {} })\n\t\t\t\t:\t(fetchOptions.headers ?? baseFetchOptions.headers);\n\n\t\t\tconst validHeaders = await getHeaders({\n\t\t\t\tauth: options.auth,\n\t\t\t\tbody: rawBody,\n\t\t\t\theaders: shouldApplySchemaOutput ? requestOptionsValidationResult?.headers : resolvedHeaders,\n\t\t\t});\n\n\t\t\tconst validMethod = getMethod({\n\t\t\t\tinitURL: resolvedInitURL,\n\t\t\t\tmethod: shouldApplySchemaOutput ? requestOptionsValidationResult?.method : request.method,\n\t\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t\t});\n\n\t\t\trequest = {\n\t\t\t\t...request,\n\t\t\t\t...(Boolean(validBody) && { body: validBody }),\n\t\t\t\t...(Boolean(validHeaders) && { headers: validHeaders }),\n\t\t\t\t...(Boolean(validMethod) && { method: validMethod }),\n\t\t\t};\n\n\t\t\tawait executeHooksInTryBlock(options.onRequest?.({ baseConfig, config, options, request }));\n\n\t\t\tconst response = await handleRequestDeferStrategy({ options, request });\n\n\t\t\t// == Also clone response when dedupeStrategy is set to \"defer\" to avoid error thrown from reading response.(whatever) more than once\n\t\t\tconst shouldCloneResponse = resolvedDedupeStrategy === \"defer\" || options.cloneResponse;\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await resolveResponseData(\n\t\t\t\t\tshouldCloneResponse ? response.clone() : response,\n\t\t\t\t\toptions.responseType,\n\t\t\t\t\toptions.responseParser\n\t\t\t\t);\n\n\t\t\t\tconst validErrorData = await handleSchemaValidation(resolvedSchema, \"errorData\", {\n\t\t\t\t\tinputValue: errorData,\n\t\t\t\t\tresponse,\n\t\t\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t\t\t});\n\n\t\t\t\t// == Push all error handling responsibilities to the catch block if not retrying\n\t\t\t\tthrow new HTTPError(\n\t\t\t\t\t{\n\t\t\t\t\t\tdefaultHTTPErrorMessage: options.defaultHTTPErrorMessage,\n\t\t\t\t\t\terrorData: validErrorData,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t},\n\t\t\t\t\t{ cause: validErrorData }\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst successData = await resolveResponseData(\n\t\t\t\tshouldCloneResponse ? response.clone() : response,\n\t\t\t\toptions.responseType,\n\t\t\t\toptions.responseParser\n\t\t\t);\n\n\t\t\tconst validSuccessData = await handleSchemaValidation(resolvedSchema, \"data\", {\n\t\t\t\tinputValue: successData,\n\t\t\t\tresponse,\n\t\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t\t});\n\n\t\t\tconst successContext = {\n\t\t\t\tbaseConfig,\n\t\t\t\tconfig,\n\t\t\t\tdata: validSuccessData,\n\t\t\t\toptions,\n\t\t\t\trequest,\n\t\t\t\tresponse,\n\t\t\t} satisfies SuccessContext<unknown>;\n\n\t\t\tawait executeHooksInTryBlock(\n\t\t\t\toptions.onSuccess?.(successContext),\n\n\t\t\t\toptions.onResponse?.({ ...successContext, error: null })\n\t\t\t);\n\n\t\t\tconst successResult = resolveSuccessResult(successContext.data, {\n\t\t\t\tresponse: successContext.response,\n\t\t\t\tresultMode: options.resultMode,\n\t\t\t});\n\n\t\t\treturn successResult as never;\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst errorInfo = {\n\t\t\t\tcloneResponse: options.cloneResponse,\n\t\t\t\tresultMode: options.resultMode,\n\t\t\t} satisfies ErrorInfo;\n\n\t\t\tconst { errorDetails, generalErrorResult } = resolveErrorResult(error, errorInfo);\n\n\t\t\tconst errorContext = {\n\t\t\t\tbaseConfig,\n\t\t\t\tconfig,\n\t\t\t\terror: errorDetails.error as never,\n\t\t\t\toptions,\n\t\t\t\trequest,\n\t\t\t\tresponse: errorDetails.response as never,\n\t\t\t} satisfies ErrorContext<unknown>;\n\n\t\t\tconst shouldThrowOnError = Boolean(\n\t\t\t\tisFunction(options.throwOnError) ? options.throwOnError(errorContext) : options.throwOnError\n\t\t\t);\n\n\t\t\tconst hookInfo = {\n\t\t\t\terrorInfo,\n\t\t\t\tshouldThrowOnError,\n\t\t\t} satisfies ExecuteHookInfo;\n\n\t\t\tconst handleRetryOrGetErrorResult = async () => {\n\t\t\t\tconst { currentAttemptCount, getDelay, shouldAttemptRetry } =\n\t\t\t\t\tcreateRetryStrategy(errorContext);\n\n\t\t\t\tconst shouldRetry = await shouldAttemptRetry();\n\n\t\t\t\tif (shouldRetry) {\n\t\t\t\t\tconst retryContext = {\n\t\t\t\t\t\t...errorContext,\n\t\t\t\t\t\tretryAttemptCount: currentAttemptCount,\n\t\t\t\t\t} satisfies RetryContext<unknown>;\n\n\t\t\t\t\tconst hookError = await executeHooksInCatchBlock(\n\t\t\t\t\t\t[options.onRetry?.(retryContext)],\n\t\t\t\t\t\thookInfo\n\t\t\t\t\t);\n\n\t\t\t\t\tif (hookError) {\n\t\t\t\t\t\treturn hookError;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst delay = getDelay();\n\n\t\t\t\t\tawait waitFor(delay);\n\n\t\t\t\t\tconst updatedOptions = {\n\t\t\t\t\t\t...config,\n\t\t\t\t\t\t\"~retryAttemptCount\": currentAttemptCount + 1,\n\t\t\t\t\t} satisfies typeof config;\n\n\t\t\t\t\treturn callApi(initURLOrURLObject as never, updatedOptions as never) as never;\n\t\t\t\t}\n\n\t\t\t\tif (shouldThrowOnError) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\n\t\t\t\treturn generalErrorResult;\n\t\t\t};\n\n\t\t\tif (isValidationErrorInstance(error)) {\n\t\t\t\tconst hookError = await executeHooksInCatchBlock(\n\t\t\t\t\t[options.onValidationError?.(errorContext), options.onError?.(errorContext)],\n\t\t\t\t\thookInfo\n\t\t\t\t);\n\n\t\t\t\treturn (hookError ?? (await handleRetryOrGetErrorResult())) as never;\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst hookError = await executeHooksInCatchBlock(\n\t\t\t\t\t[\n\t\t\t\t\t\toptions.onResponseError?.(errorContext),\n\t\t\t\t\t\toptions.onError?.(errorContext),\n\t\t\t\t\t\toptions.onResponse?.({ ...errorContext, data: null }),\n\t\t\t\t\t],\n\t\t\t\t\thookInfo\n\t\t\t\t);\n\n\t\t\t\treturn (hookError ?? (await handleRetryOrGetErrorResult())) as never;\n\t\t\t}\n\n\t\t\tlet message = (error as Error | undefined)?.message;\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tmessage = getAbortErrorMessage();\n\n\t\t\t\t!shouldThrowOnError && console.error(`${error.name}:`, message);\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tmessage = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\t!shouldThrowOnError && console.error(`${error.name}:`, message);\n\t\t\t}\n\n\t\t\tconst hookError = await executeHooksInCatchBlock(\n\t\t\t\t[options.onRequestError?.(errorContext), options.onError?.(errorContext)],\n\t\t\t\thookInfo\n\t\t\t);\n\n\t\t\treturn (hookError\n\t\t\t\t?? getCustomizedErrorResult(await handleRetryOrGetErrorResult(), { message })) as never;\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tremoveDedupeKeyFromCache();\n\t\t}\n\t};\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n","import type { CallApiPlugin } from \"./plugins\";\nimport type { ResponseTypeUnion, ResultModeUnion } from \"./result\";\nimport type {\n\tBaseCallApiConfig,\n\tCallApiExtraOptions,\n\tCallApiParameters,\n\tInferInitURL,\n\tThrowOnErrorUnion,\n} from \"./types\";\nimport type { DefaultDataType, DefaultPluginArray, DefaultThrowOnError } from \"./types/default-types\";\nimport type { AnyFunction, Writeable } from \"./types/type-helpers\";\nimport type {\n\tBaseCallApiSchemaAndConfig,\n\tBaseCallApiSchemaRoutes,\n\tCallApiSchema,\n\tCallApiSchemaConfig,\n} from \"./validation\";\n\nexport const defineSchema = <\n\tconst TBaseSchemaRoutes extends BaseCallApiSchemaRoutes,\n\tconst TSchemaConfig extends CallApiSchemaConfig,\n>(\n\troutes: TBaseSchemaRoutes,\n\tconfig?: TSchemaConfig\n) => {\n\treturn {\n\t\tconfig: defineSchemaConfig(config),\n\t\troutes: defineSchemaRoutes(routes),\n\t} satisfies BaseCallApiSchemaAndConfig;\n};\n\nexport const defineSchemaConfig = <const TConfig extends CallApiExtraOptions[\"schemaConfig\"]>(\n\tconfig: TConfig\n) => {\n\treturn config as NonNullable<Writeable<typeof config, \"deep\">>;\n};\n\nexport const defineSchemaRoutes = <const TBaseSchemaRoutes extends BaseCallApiSchemaRoutes>(\n\troutes: TBaseSchemaRoutes\n) => {\n\treturn routes as Writeable<typeof routes, \"deep\">;\n};\n\nexport const definePlugin = <\n\t// eslint-disable-next-line perfectionist/sort-union-types -- Let the first one be first\n\tconst TPlugin extends CallApiPlugin | AnyFunction<CallApiPlugin>,\n>(\n\tplugin: TPlugin\n) => {\n\treturn plugin as Writeable<TPlugin, \"deep\">;\n};\n\nexport const defineBaseConfig = <const TBaseConfig extends BaseCallApiConfig>(baseConfig: TBaseConfig) => {\n\treturn baseConfig as Writeable<typeof baseConfig, \"deep\">;\n};\n\nexport const defineParameters = <\n\tTData = DefaultDataType,\n\tTErrorData = DefaultDataType,\n\tTResultMode extends ResultModeUnion = ResultModeUnion,\n\tTThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError,\n\tTResponseType extends ResponseTypeUnion = ResponseTypeUnion,\n\tTBaseSchemaRoutes extends BaseCallApiSchemaRoutes = BaseCallApiSchemaRoutes,\n\tTSchema extends CallApiSchema = CallApiSchema,\n\tTBaseSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig,\n\tTSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig,\n\tTInitURL extends InferInitURL<BaseCallApiSchemaRoutes, TSchemaConfig> = InferInitURL<\n\t\tBaseCallApiSchemaRoutes,\n\t\tTSchemaConfig\n\t>,\n\tTCurrentRouteSchemaKey extends string = string,\n\tTBasePluginArray extends CallApiPlugin[] = DefaultPluginArray,\n\tTPluginArray extends CallApiPlugin[] = DefaultPluginArray,\n>(\n\t...parameters: CallApiParameters<\n\t\tTData,\n\t\tTErrorData,\n\t\tTResultMode,\n\t\tTThrowOnError,\n\t\tTResponseType,\n\t\tTBaseSchemaRoutes,\n\t\tTSchema,\n\t\tTBaseSchemaConfig,\n\t\tTSchemaConfig,\n\t\tTInitURL,\n\t\tTCurrentRouteSchemaKey,\n\t\tTBasePluginArray,\n\t\tTPluginArray\n\t>\n) => {\n\treturn parameters;\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { CallApiExtraOptions, CallApiResultErrorVariant, HTTPError, PossibleHTTPError, PossibleJavaScriptError, PossibleValidationError, ValidationError } from "../common-Bk1Hh1hR.js";
1
+ import { CallApiExtraOptions, CallApiResultErrorVariant, HTTPError, PossibleHTTPError, PossibleJavaScriptError, PossibleValidationError, ValidationError } from "../common-BqnzZD5r.js";
2
2
 
3
3
  //#region src/utils/common.d.ts
4
4
 
@@ -1,3 +1,3 @@
1
- import { isHTTPError, isHTTPErrorInstance, isJavascriptError, isValidationError, isValidationErrorInstance, toQueryString } from "../utils-BCsnh8UI.js";
1
+ import { isHTTPError, isHTTPErrorInstance, isJavascriptError, isValidationError, isValidationErrorInstance, toQueryString } from "../common-BFea9qeg.js";
2
2
 
3
3
  export { isHTTPError, isHTTPErrorInstance, isJavascriptError, isValidationError, isValidationErrorInstance, toQueryString };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zayne-labs/callapi",
3
3
  "type": "module",
4
- "version": "1.10.3",
4
+ "version": "1.10.5",
5
5
  "description": "A lightweight wrapper over fetch with quality of life improvements like built-in request cancellation, retries, interceptors and more",
6
6
  "author": "Ryan Zayne",
7
7
  "license": "MIT",
@@ -41,18 +41,17 @@
41
41
  "@total-typescript/ts-reset": "0.6.1",
42
42
  "@vitest/browser": "^3.2.4",
43
43
  "@vitest/coverage-v8": "3.2.4",
44
- "@zayne-labs/prettier-config": "^0.9.15",
45
- "@zayne-labs/toolkit-type-helpers": "^0.11.7",
46
- "@zayne-labs/tsconfig": "0.9.15",
44
+ "@zayne-labs/prettier-config": "^0.9.17",
45
+ "@zayne-labs/tsconfig": "0.9.17",
47
46
  "concurrently": "^9.2.1",
48
47
  "cross-env": "^10.0.0",
49
- "playwright": "^1.55.0",
48
+ "playwright": "^1.55.1",
50
49
  "publint": "^0.3.13",
51
50
  "size-limit": "11.2.0",
52
- "tsdown": "^0.15.2",
51
+ "tsdown": "^0.15.4",
53
52
  "typescript": "5.9.2",
54
53
  "vitest": "^3.2.4",
55
- "zod": "^4.1.9"
54
+ "zod": "^4.1.11"
56
55
  },
57
56
  "publishConfig": {
58
57
  "access": "public",
@@ -62,7 +61,7 @@
62
61
  "size-limit": [
63
62
  {
64
63
  "path": "./src/index.ts",
65
- "limit": "6 kb"
64
+ "limit": "6.5 kb"
66
65
  },
67
66
  {
68
67
  "path": "./src/utils/index.ts",