@zayne-labs/callapi 0.5.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +123 -120
- package/dist/esm/chunk-AKFUJ4JG.js +1 -0
- package/dist/esm/chunk-AKFUJ4JG.js.map +1 -0
- package/dist/esm/chunk-F6RUPSGH.js +1 -0
- package/dist/esm/chunk-F6RUPSGH.js.map +1 -0
- package/dist/esm/chunk-KQNDKJNJ.js +1 -0
- package/dist/esm/chunk-KQNDKJNJ.js.map +1 -0
- package/dist/esm/createFetchClient.d.ts +2 -5
- package/dist/esm/createFetchClient.js +1 -5
- package/dist/esm/createFetchClient.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/type-helpers-DpDJiTqb.d.ts +12 -0
- package/dist/esm/typeof.d.ts +1 -1
- package/dist/esm/typeof.js +1 -3
- package/dist/esm/typeof.js.map +1 -1
- package/dist/esm/{types-DIDORyP8.d.ts → types-CfjkQnRk.d.ts} +128 -112
- package/dist/esm/utils.d.ts +2 -2
- package/dist/esm/utils.js +1 -4
- package/dist/esm/utils.js.map +1 -1
- package/package.json +19 -15
- package/dist/esm/chunk-RRO7PFYR.js +0 -8
- package/dist/esm/chunk-RRO7PFYR.js.map +0 -1
- package/dist/esm/chunk-XE3JEDG3.js +0 -7
- package/dist/esm/chunk-XE3JEDG3.js.map +0 -1
- package/dist/esm/chunk-ZYWIPUWT.js +0 -5
- package/dist/esm/chunk-ZYWIPUWT.js.map +0 -1
- package/dist/esm/type-helpers-Dibitydy.d.ts +0 -9
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
"use strict";var e,r=Object.defineProperty,t=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,n={};((e,t)=>{for(var o in t)r(e,o,{get:t[o],enumerable:!0})})(n,{callApi:()=>E,createFetchClient:()=>w}),module.exports=(e=n,((e,n,a,i)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let l of o(n))s.call(e,l)||l===a||r(e,l,{get:()=>n[l],enumerable:!(i=t(n,l))||i.enumerable});return e})(r({},"__esModule",{value:!0}),e));var a=e=>!("object"!=typeof e||null===e||e instanceof FormData||Array.isArray(e)),i=e=>"string"==typeof e,l=(e,r)=>{if(!r)return e;const t=(e=>e?new URLSearchParams(e).toString():(console.error("toQueryString:","No query params provided!"),null))(r);return e.endsWith("?")?`${e}${t}`:e.includes("?")?`${e}&${t}`:`${e}?${t}`},u=e=>{return!e||a(e)?e:Object.fromEntries((r=e,Array.isArray(r)?e:e.entries()));var r},c=Object.keys({408:"Request Timeout",409:"Conflict",425:"Too Early",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"}).map(Number),p=["GET"],d=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],y=(e,r)=>{const t=Object.entries(e).filter((([e])=>!r.includes(e)));return Object.fromEntries(t)},f=(e,r)=>{const t=new Set(r),o=Object.entries(e).filter((([e])=>t.has(e)));return Object.fromEntries(o)},m=e=>[f(e,d),y(e,d)],h=(e,r,t)=>{const o=((e,r)=>({arrayBuffer:()=>e.arrayBuffer(),blob:()=>e.blob(),formData:()=>e.formData(),json:async()=>r?r(await e.text()):e.json(),text:()=>e.text()}))(e,t);if(!Object.hasOwn(o,r))throw new Error(`Invalid response type: ${r}`);return o[r]()},b=class extends Error{errorData;isHTTPError=!0;name="HTTPError";response;constructor(e,r){const{defaultErrorMessage:t,errorData:o,response:s}=e;super(o.message??t,r),this.errorData=o,this.response=s}},w=e=>{const r=new Map,[t,o]=m(e??{}),{body:s,headers:n,signal:d,...f}=t,E=async(e,t)=>{const[w,g]=m(t??{}),{body:R=s,headers:O,signal:D=d,...T}=w,q={baseURL:"",bodySerializer:JSON.stringify,cancelRedundantRequests:!0,defaultErrorMessage:"Failed to fetch data from server!",responseType:"json",retries:0,retryCodes:c,retryDelay:0,retryMethods:p,...o,...g},$={body:a(R)?q.bodySerializer(R):R,headers:n||O||q.auth||a(R)?{...a(R)&&{Accept:"application/json","Content-Type":"application/json"},...(j=R,"string"==typeof j&&j.includes("=")&&{"Content-Type":"application/x-www-form-urlencoded"}),...i(q.auth)&&{Authorization:`Bearer ${q.auth}`},...a(q.auth)&&{Authorization:"bearer"in q.auth?`Bearer ${q.auth.bearer}`:`Token ${q.auth.token}`},...u(n),...u(O)}:void 0,method:"GET",...f,...T};var j;const v=((e,r)=>`${e} | ${JSON.stringify(r??{})}`)(e,y({...$,...q},["onRequest","onResponse","onResponseError","onError","onRequestError"])),M=r.get(v);if(M&&q.cancelRedundantRequests){const r=new DOMException(`Automatic cancelation of the previous unfinished request to the same url, with the same fetch options: ${e}`,"AbortError");M.abort(r)}const P=new AbortController;r.set(v,P);const S=q.timeout?AbortSignal.timeout(q.timeout):null,A=AbortSignal.any([P.signal,...S?[S]:[],...D?[D]:[]]),x={signal:A,...$};try{await(q.onRequest?.({options:q,request:x}));const r=await fetch(`${q.baseURL}${l(e,q.query)}`,x);if(!r.ok&&!A.aborted&&q.retries>0&&q.retryCodes.includes(r.status)&&q.retryMethods.includes(x.method))return await(e=>{if(0===e)return;const{promise:r,resolve:t}=Promise.withResolvers();return setTimeout(t,e),r})(q.retryDelay),await E(e,{...t,retries:q.retries-1});if(!r.ok){const e=await h(q.cloneResponse?r.clone():r,q.responseType,q.responseParser);throw new b({defaultErrorMessage:q.defaultErrorMessage,errorData:e,response:r})}const o=await h(q.cloneResponse?r.clone():r,q.responseType,q.responseParser),s=q.responseValidator?q.responseValidator(o):o;return await(q.onResponse?.({data:s,options:q,request:x,response:q.cloneResponse?r.clone():r})),(e=>{const{options:r,response:t,successData:o}=e,s={data:o,error:null,response:t};return r.resultMode&&"all"!==r.resultMode?{onlyError:s.error,onlyResponse:s.response,onlySuccess:s.data}[r.resultMode]:s})({options:q,response:r,successData:s})}catch(e){const r=(e=>{const{error:r,options:t}=e;return(e={})=>{const{errorData:o,message:s,response:n}=e;if("function"==typeof t.throwOnError?t.throwOnError(r):t.throwOnError)throw r;return{data:null,error:{errorData:o??r,message:s??r?.message??t.defaultErrorMessage,name:r?.name??"UnknownError"},response:n??null}}})({error:e,options:q});if(e instanceof DOMException&&"TimeoutError"===e.name){const t=`Request timed out after ${q.timeout}ms`;return console.error(`${e.name}:`,t),r({message:t})}if(e instanceof DOMException&&"AbortError"===e.name){const t=`Request aborted due to ${e.message}`;return console.error(`${e.name}:`,t),r({message:t})}if((e=>e instanceof b||a(e)&&"HTTPError"===e.name&&!0===e.isHTTPError)(e)){const{errorData:t,response:o}=e;return await Promise.allSettled([q.onResponseError?.({errorData:t,options:q,request:x,response:q.cloneResponse?o.clone():o}),q.onError?.({error:null,errorData:t,options:q,request:x,response:o})]),r({errorData:t,message:t?.message,response:o})}return await Promise.allSettled([q.onRequestError?.({error:e,options:q,request:x}),q.onError?.({error:e,errorData:null,options:q,request:x,response:null})]),r()}finally{r.delete(v)}};return E.create=w,E},E=w();//# sourceMappingURL=index.cjs.map
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/typeof.ts","../../src/utils.ts","../../src/createFetchClient.ts"],"sourcesContent":["export { callApi, createFetchClient } from \"./createFetchClient\";\n\nexport type {\n\t$RequestOptions,\n\tExtraOptions,\n\tFetchConfig,\n\tResponseContext,\n\tResponseErrorContext,\n} from \"./types\";\n\nexport { HTTPError, isHTTPError, isHTTPErrorInstance, toQueryString } from \"./utils\";\n","import type { AnyFunction } from \"./type-helpers\";\n\nexport const isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn (\n\t\ttypeof value === \"object\" && value !== null && !(value instanceof FormData) && !Array.isArray(value)\n\t);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n\nexport const isString = (value: unknown) => typeof value === \"string\";\n\nexport const isQueryString = (value: unknown): value is string =>\n\ttypeof value === \"string\" && value.includes(\"=\");\n","import { isArray, isFunction, isObject } from \"./typeof\";\nimport type {\n\t$BaseRequestOptions,\n\t$RequestOptions,\n\tApiErrorVariant,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\ntype ToQueryStringFn = {\n\t(params: ExtraOptions[\"query\"]): string | null;\n\t(params: Required<ExtraOptions>[\"query\"]): string;\n};\n\nexport const toQueryString: ToQueryStringFn = (params) => {\n\tif (!params) {\n\t\tconsole.error(\"No query params provided\");\n\t\treturn null as never;\n\t}\n\n\treturn new URLSearchParams(params as Record<string, string>).toString();\n};\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = toQueryString(params);\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\tif (url.includes(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nconst omitKeys = <TObject extends Record<string, unknown>, const TOmitArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype data = {\n\tsuccessData: unknown;\n\toptions: ExtraOptions;\n\tresponse: Response;\n};\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 = <CallApiResult>(info: data): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = {\n\t\tdata: successData,\n\t\terror: null,\n\t\tresponse,\n\t};\n\n\tif (options.resultMode === undefined || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlySuccess: apiDetails.data,\n\t\tonlyError: apiDetails.error,\n\t\tonlyResponse: apiDetails.response,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const $resolveErrorResult = <CallApiResult>($info: { error?: unknown; options: ExtraOptions }) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\tresponse?: Response;\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\tname: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t\terrorData: errorData ?? error,\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\n\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\n\treturn isObject(error) && error.name === \"HTTPError\";\n};\n\ntype ErrorDetails<TErrorResponse> = {\n\terrorData: TErrorResponse;\n\tresponse: Response;\n\tdefaultErrorMessage: string;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\n\n\toverride name = \"HTTPError\" as const;\n\n\tisHTTPError = true;\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, response, errorData } = errorDetails;\n\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.errorData = errorData;\n\t\tthis.response = response;\n\t}\n}\n\n// prettier-ignore\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const waitUntil = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n","import { isObject, isQueryString, isString } from \"./typeof\";\nimport type {\n\t$RequestOptions,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultModeUnion,\n} from \"./types\";\nimport {\n\t$resolveErrorResult,\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetResponseData,\n\tisHTTPErrorInstance,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twaitUntil,\n} from \"./utils\";\n\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData = unknown,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\theaders: baseHeaders,\n\t\tbody: baseBody,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\tconst { signal = baseSignal, body = baseBody, headers, ...restOfFetchConfig } = fetchConfig;\n\n\t\t// == Default Options\n\t\tconst options = {\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tresponseType: \"json\",\n\t\t\tbaseURL: \"\",\n\t\t\tretries: 0,\n\t\t\tretryDelay: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tcancelRedundantRequests: true,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\tconst prevFetchController = abortControllerStore.get(url);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\n\t\t\t\t`Automatic cancelation of the previous unfinished request to this same url: ${url}`,\n\t\t\t\t\"AbortError\"\n\t\t\t);\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(url, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\tconst combinedSignal = AbortSignal.any([\n\t\t\tnewFetchController.signal,\n\t\t\t...(timeoutSignal ? [timeoutSignal] : []),\n\t\t\t...(signal ? [signal] : []),\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\n\t\t\tmethod: \"GET\",\n\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\n\t\t\t// - headers are provided\n\t\t\t// - The body is an object\n\t\t\t// - The auth option is provided\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || options.auth || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isQueryString(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ request: requestInit, options });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\toptions.cloneResponse ? 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\t// == Pushing all error handling responsibilities to the catch block\n\t\t\t\tthrow new HTTPError({\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\toptions.cloneResponse ? 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 = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tdata: validSuccessData,\n\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t\trequest: requestInit,\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ successData: validSuccessData, response, options });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = $resolveErrorResult<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tconst message = `Request aborted due to ${error.message}`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst { errorData, response } = error;\n\n\t\t\t\tawait options.onResponseError?.({\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\toptions,\n\t\t\t\t});\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\tawait options.onRequestError?.({ request: requestInit, error: error as Error, options });\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(url);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\n\tcallApi.cancel = (url: string, reason?: unknown) => {\n\t\treason ? abortControllerStore.get(url)?.abort(reason) : abortControllerStore.get(url)?.abort();\n\t};\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n"],"mappings":"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","names":["src_exports","__export","HTTPError","callApi","createFetchClient","isHTTPError","isHTTPErrorInstance","toQueryString","__toCommonJS","isArray","value","isObject","isFunction","isString","isQueryString","toQueryString","params","mergeUrlWithParams","url","paramsString","objectifyHeaders","headers","isObject","isArray","retryCodesLookup","defaultRetryCodes","defaultRetryMethods","fetchSpecificKeys","omitKeys","initialObject","keysToOmit","arrayFromFilteredObject","key","pickKeys","keysToPick","keysToPickSet","filteredArray","objectKey","splitConfig","config","handleResponseType","response","parser","getResponseData","responseType","RESPONSE_TYPE_LOOKUP","resolveSuccessResult","info","options","successData","apiDetails","$resolveErrorResult","$info","error","errorData","message","isFunction","isHTTPError","HTTPError","errorDetails","errorOptions","defaultErrorMessage","isHTTPErrorInstance","waitUntil","delay","promise","resolve","createFetchClient","baseConfig","abortControllerStore","baseFetchConfig","baseExtraOptions","splitConfig","baseHeaders","baseBody","baseSignal","restOfBaseFetchConfig","callApi","url","config","fetchConfig","extraOptions","signal","body","headers","restOfFetchConfig","options","defaultRetryCodes","defaultRetryMethods","prevFetchController","reason","newFetchController","timeoutSignal","combinedSignal","requestInit","isObject","isQueryString","isString","objectifyHeaders","response","mergeUrlWithParams","waitUntil","errorData","getResponseData","HTTPError","successData","validSuccessData","resolveSuccessResult","error","resolveErrorResult","$resolveErrorResult","message","isHTTPErrorInstance"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/typeof.ts","../../src/utils.ts","../../src/createFetchClient.ts"],"sourcesContent":["export { callApi, createFetchClient } from \"./createFetchClient\";\n\nexport type {\n\t$RequestOptions,\n\tExtraOptions,\n\tFetchConfig,\n\tResponseContext,\n\tResponseErrorContext,\n\tErrorContext,\n} from \"./types\";\n","import type { AnyFunction } from \"./type-helpers\";\n\nexport const isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn (\n\t\ttypeof value === \"object\" && value !== null && !(value instanceof FormData) && !Array.isArray(value)\n\t);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n\nexport const isString = (value: unknown) => typeof value === \"string\";\n\nexport const isQueryString = (value: unknown): value is string =>\n\ttypeof value === \"string\" && value.includes(\"=\");\n","import { isArray, isFunction, isObject } from \"./typeof\";\nimport type {\n\t$BaseRequestOptions,\n\t$RequestOptions,\n\tApiErrorVariant,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\n// prettier-ignore\nexport const getRequestKey = <TConfig extends Record<string, unknown>>(url: string, config?: TConfig) => `${url} | ${JSON.stringify(config ?? {})}`;\n\ntype ToQueryStringFn = {\n\t(params: ExtraOptions[\"query\"]): null | string;\n\t(params: Required<ExtraOptions>[\"query\"]): string;\n};\n\nexport const toQueryString: ToQueryStringFn = (params) => {\n\tif (!params) {\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\n\n\t\treturn null as never;\n\t}\n\n\treturn new URLSearchParams(params as Record<string, string>).toString();\n};\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = toQueryString(params);\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\tif (url.includes(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nexport const omitKeys = <\n\tTObject extends Record<string, unknown>,\n\tconst TOmitArray extends Array<keyof TObject>,\n>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype data = {\n\toptions: ExtraOptions;\n\tresponse: Response;\n\tsuccessData: unknown;\n};\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 = <CallApiResult>(info: data): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = {\n\t\tdata: successData,\n\t\terror: null,\n\t\tresponse,\n\t};\n\n\tif (!options.resultMode || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlyError: apiDetails.error,\n\t\tonlyResponse: apiDetails.response,\n\t\tonlySuccess: apiDetails.data,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const getResolveErrorResultFn = <CallApiResult>($info: {\n\terror?: unknown;\n\toptions: ExtraOptions;\n}) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t\tresponse?: Response;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\terrorData: errorData ?? error,\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t\tname: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\n\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\n\treturn isObject(error) && error.name === \"HTTPError\";\n};\n\ntype ErrorDetails<TErrorResponse> = {\n\tdefaultErrorMessage: string;\n\terrorData: TErrorResponse;\n\tresponse: Response;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\n\tisHTTPError = true;\n\n\toverride name = \"HTTPError\" as const;\n\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\n\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.errorData = errorData;\n\t\tthis.response = response;\n\t}\n}\n\n// prettier-ignore\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const waitUntil = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n","import { isObject, isQueryString, isString } from \"./typeof\";\nimport type {\n\t$RequestOptions,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultModeUnion,\n} from \"./types\";\nimport {\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetRequestKey,\n\tgetResolveErrorResultFn,\n\tgetResponseData,\n\tisHTTPErrorInstance,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tomitKeys,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twaitUntil,\n} from \"./utils\";\n\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData = unknown,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\tbody: baseBody,\n\t\theaders: baseHeaders,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\n\n\t\t// == Default Extra Options\n\t\tconst options = {\n\t\t\tbaseURL: \"\",\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tcancelRedundantRequests: true,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tresponseType: \"json\",\n\t\t\tretries: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryDelay: 0,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\t// == Default Fetch Config\n\t\tconst defaultFetchOptions = {\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// - The auth option is provided\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || options.auth || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isQueryString(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\n\t\t\t// - headers are provided\n\t\t\t// - The body is an object\n\t\t\tmethod: \"GET\",\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\tconst requestKey = getRequestKey(\n\t\t\turl,\n\t\t\tomitKeys({ ...defaultFetchOptions, ...options }, [\n\t\t\t\t\"onRequest\",\n\t\t\t\t\"onResponse\",\n\t\t\t\t\"onResponseError\",\n\t\t\t\t\"onError\",\n\t\t\t\t\"onRequestError\",\n\t\t\t])\n\t\t);\n\n\t\tconst prevFetchController = abortControllerStore.get(requestKey);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\n\t\t\t\t`Automatic cancelation of the previous unfinished request to the same url, with the same fetch options: ${url}`,\n\t\t\t\t\"AbortError\"\n\t\t\t);\n\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(requestKey, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\tconst combinedSignal = AbortSignal.any([\n\t\t\tnewFetchController.signal,\n\t\t\t...(timeoutSignal ? [timeoutSignal] : []),\n\t\t\t...(signal ? [signal] : []),\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\t\t\t...defaultFetchOptions,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ options, request: requestInit });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\toptions.cloneResponse ? 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\t// == Pushing all error handling responsibilities to the catch block\n\t\t\t\tthrow new HTTPError({\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\toptions.cloneResponse ? 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 = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tdata: validSuccessData,\n\t\t\t\toptions,\n\t\t\t\trequest: requestInit,\n\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ options, response, successData: validSuccessData });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = getResolveErrorResultFn<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tconst message = `Request aborted due to ${error.message}`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst { errorData, response } = error;\n\n\t\t\t\tvoid (await Promise.allSettled([\n\t\t\t\t\toptions.onResponseError?.({\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t\t\t}),\n\n\t\t\t\t\t// == Also call the onError interceptor\n\t\t\t\t\toptions.onError?.({\n\t\t\t\t\t\terror: null,\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}),\n\t\t\t\t]));\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid (await Promise.allSettled([\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request: requestInit }),\n\n\t\t\t\t// == Also call the onError interceptor\n\t\t\t\toptions.onError?.({\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\terrorData: null,\n\t\t\t\t\toptions,\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\tresponse: null,\n\t\t\t\t}),\n\t\t\t]));\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(requestKey);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n"],"mappings":"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","names":["callApi"]}
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -4,138 +4,72 @@ type AnyString = string & {
|
|
|
4
4
|
type AnyNumber = number & {
|
|
5
5
|
placeholder?: never;
|
|
6
6
|
};
|
|
7
|
+
type Prettify<TObject> = {
|
|
8
|
+
[Key in keyof TObject]: TObject[Key];
|
|
9
|
+
} & NonNullable<unknown>;
|
|
7
10
|
|
|
8
|
-
type ToQueryStringFn = {
|
|
9
|
-
(params: ExtraOptions["query"]): string | null;
|
|
10
|
-
(params: Required<ExtraOptions>["query"]): string;
|
|
11
|
-
};
|
|
12
|
-
declare const toQueryString: ToQueryStringFn;
|
|
13
11
|
declare const fetchSpecificKeys: ("body" | "method" | "headers" | "cache" | "credentials" | "integrity" | "keepalive" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
|
|
14
12
|
declare const handleResponseType: <TResponse>(response: Response, parser?: Required<ExtraOptions>["responseParser"]) => {
|
|
15
|
-
json: () => Promise<Record<string, unknown> | TResponse>;
|
|
16
13
|
arrayBuffer: () => Promise<TResponse>;
|
|
17
14
|
blob: () => Promise<TResponse>;
|
|
18
15
|
formData: () => Promise<TResponse>;
|
|
16
|
+
json: () => Promise<Record<string, unknown> | TResponse>;
|
|
19
17
|
text: () => Promise<TResponse>;
|
|
20
18
|
};
|
|
21
|
-
declare const isHTTPError: <TErrorData>(error: ApiErrorVariant<TErrorData>["error"] | null) => error is {
|
|
22
|
-
name: "HTTPError";
|
|
23
|
-
errorData: TErrorData;
|
|
24
|
-
message: string;
|
|
25
|
-
};
|
|
26
19
|
type ErrorDetails<TErrorResponse> = {
|
|
20
|
+
defaultErrorMessage: string;
|
|
27
21
|
errorData: TErrorResponse;
|
|
28
22
|
response: Response;
|
|
29
|
-
defaultErrorMessage: string;
|
|
30
23
|
};
|
|
31
24
|
type ErrorOptions = {
|
|
32
25
|
cause?: unknown;
|
|
33
26
|
};
|
|
34
27
|
declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {
|
|
35
|
-
response: ErrorDetails<TErrorResponse>["response"];
|
|
36
28
|
errorData: ErrorDetails<TErrorResponse>["errorData"];
|
|
37
|
-
name: "HTTPError";
|
|
38
29
|
isHTTPError: boolean;
|
|
30
|
+
name: "HTTPError";
|
|
31
|
+
response: ErrorDetails<TErrorResponse>["response"];
|
|
39
32
|
constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
|
|
40
33
|
}
|
|
41
|
-
declare const isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
42
34
|
|
|
43
35
|
interface $RequestOptions extends Pick<FetchConfig, (typeof fetchSpecificKeys)[number]> {
|
|
44
36
|
}
|
|
45
37
|
interface ExtraOptions<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = ResultModeUnion> {
|
|
46
|
-
/** Optional body of the request, can be a object or any other supported body type. */
|
|
47
|
-
body?: Record<string, unknown> | RequestInit["body"];
|
|
48
|
-
/**
|
|
49
|
-
* @description HTTP method for the request.
|
|
50
|
-
* @default "GET"
|
|
51
|
-
*/
|
|
52
|
-
method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | AnyString;
|
|
53
|
-
/**
|
|
54
|
-
* @description Query parameters to append to the URL.
|
|
55
|
-
*/
|
|
56
|
-
query?: Record<string, string | number | boolean>;
|
|
57
38
|
/**
|
|
58
39
|
* @description Authorization header value.
|
|
59
40
|
*/
|
|
60
|
-
auth?:
|
|
41
|
+
auth?: {
|
|
61
42
|
bearer: string;
|
|
62
43
|
token?: never;
|
|
63
44
|
} | {
|
|
64
|
-
token: string;
|
|
65
45
|
bearer?: never;
|
|
66
|
-
|
|
46
|
+
token: string;
|
|
47
|
+
} | string;
|
|
67
48
|
/**
|
|
68
|
-
* @description
|
|
49
|
+
* @description Base URL to be prepended to all request URLs
|
|
69
50
|
*/
|
|
70
|
-
|
|
51
|
+
baseURL?: string;
|
|
52
|
+
/** Optional body of the request, can be a object or any other supported body type. */
|
|
53
|
+
body?: Record<string, unknown> | RequestInit["body"];
|
|
71
54
|
/**
|
|
72
55
|
* @description Custom function to serialize the body object into a string.
|
|
73
56
|
*/
|
|
74
57
|
bodySerializer?: (bodyData: Record<string, unknown>) => string;
|
|
75
|
-
/**
|
|
76
|
-
* @description Custom function to parse the response string into a object.
|
|
77
|
-
*/
|
|
78
|
-
responseParser?: (responseString: string) => Record<string, unknown>;
|
|
79
|
-
/**
|
|
80
|
-
* @description Mode of the result, can influence how results are handled or returned.
|
|
81
|
-
* Can be set to "all" | "onlySuccess" | "onlyError" | "onlyResponse".
|
|
82
|
-
* @default "all"
|
|
83
|
-
*/
|
|
84
|
-
resultMode?: TResultMode;
|
|
85
58
|
/**
|
|
86
59
|
* @description If true, cancels previous unfinished requests to the same URL.
|
|
87
60
|
* @default true
|
|
88
61
|
*/
|
|
89
62
|
cancelRedundantRequests?: boolean;
|
|
90
|
-
/**
|
|
91
|
-
* @description Base URL to be prepended to all request URLs
|
|
92
|
-
*/
|
|
93
|
-
baseURL?: string;
|
|
94
|
-
/**
|
|
95
|
-
* @description Request timeout in milliseconds
|
|
96
|
-
*/
|
|
97
|
-
timeout?: number;
|
|
98
|
-
/**
|
|
99
|
-
* @description Default error message to use if none is provided from a response.
|
|
100
|
-
* @default "Failed to fetch data from server!"
|
|
101
|
-
*/
|
|
102
|
-
defaultErrorMessage?: string;
|
|
103
63
|
/**
|
|
104
64
|
* @description Whether to clone the response, so response.json and the like can used in the interceptors.
|
|
105
65
|
* @default false
|
|
106
66
|
*/
|
|
107
67
|
cloneResponse?: boolean;
|
|
108
68
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* @default false
|
|
112
|
-
*/
|
|
113
|
-
throwOnError?: boolean | ((error?: Error | HTTPError<TErrorData>) => boolean);
|
|
114
|
-
/**
|
|
115
|
-
* @description Expected response type, affects how response is parsed
|
|
116
|
-
* @default "json"
|
|
117
|
-
*/
|
|
118
|
-
responseType?: keyof ReturnType<typeof handleResponseType>;
|
|
119
|
-
/**
|
|
120
|
-
* @description Number of retry attempts for failed requests
|
|
121
|
-
* @default 0
|
|
122
|
-
*/
|
|
123
|
-
retries?: number;
|
|
124
|
-
/**
|
|
125
|
-
* @description Delay between retries in milliseconds
|
|
126
|
-
* @default 500
|
|
127
|
-
*/
|
|
128
|
-
retryDelay?: number;
|
|
129
|
-
/**
|
|
130
|
-
* @description HTTP status codes that trigger a retry
|
|
131
|
-
* @default [409, 425, 429, 500, 502, 503, 504]
|
|
132
|
-
*/
|
|
133
|
-
retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
|
|
134
|
-
/**
|
|
135
|
-
* HTTP methods that are allowed to retry
|
|
136
|
-
* @default ["GET", "POST"]
|
|
69
|
+
* @description Default error message to use if none is provided from a response.
|
|
70
|
+
* @default "Failed to fetch data from server!"
|
|
137
71
|
*/
|
|
138
|
-
|
|
72
|
+
defaultErrorMessage?: string;
|
|
139
73
|
/**
|
|
140
74
|
* @description an optional field you can fill with additional information,
|
|
141
75
|
* to associate with the request, typically used for logging or tracing.
|
|
@@ -159,71 +93,143 @@ interface ExtraOptions<TData = unknown, TErrorData = unknown, TResultMode extend
|
|
|
159
93
|
* ```
|
|
160
94
|
*/
|
|
161
95
|
meta?: Record<string, unknown>;
|
|
96
|
+
/**
|
|
97
|
+
* @description HTTP method for the request.
|
|
98
|
+
* @default "GET"
|
|
99
|
+
*/
|
|
100
|
+
method?: "DELETE" | "GET" | "PATCH" | "POST" | "PUT" | AnyString;
|
|
101
|
+
/**
|
|
102
|
+
* @description Interceptor to be called when an error occurs during the fetch request OR when an error response is received from the api
|
|
103
|
+
* It is basically a combination of `onRequestError` and `onResponseError` interceptors
|
|
104
|
+
*/
|
|
105
|
+
onError?: (anyErrorContext: ErrorContext<TErrorData>) => Promise<void> | void;
|
|
162
106
|
/** @description Interceptor to be called just before the request is made, allowing for modifications or additional operations. */
|
|
163
107
|
onRequest?: (requestContext: {
|
|
164
|
-
request: $RequestOptions;
|
|
165
108
|
options: ExtraOptions;
|
|
166
|
-
|
|
109
|
+
request: $RequestOptions;
|
|
110
|
+
}) => Promise<void> | void;
|
|
167
111
|
/** @description Interceptor to be called when an error occurs during the fetch request. */
|
|
168
112
|
onRequestError?: (requestErrorContext: {
|
|
169
113
|
error: Error;
|
|
170
|
-
request: $RequestOptions;
|
|
171
114
|
options: ExtraOptions;
|
|
172
|
-
|
|
115
|
+
request: $RequestOptions;
|
|
116
|
+
}) => Promise<void> | void;
|
|
173
117
|
/** @description Interceptor to be called when a successful response is received from the api. */
|
|
174
|
-
onResponse?: (responseContext: ResponseContext<TData>) => void |
|
|
118
|
+
onResponse?: (responseContext: ResponseContext<TData>) => Promise<void> | void;
|
|
175
119
|
/** @description Interceptor to be called when an error response is received from the api. */
|
|
176
|
-
onResponseError?: (responseErrorContext: ResponseErrorContext<TErrorData>) => void |
|
|
120
|
+
onResponseError?: (responseErrorContext: ResponseErrorContext<TErrorData>) => Promise<void> | void;
|
|
121
|
+
/**
|
|
122
|
+
* @description Query parameters to append to the URL.
|
|
123
|
+
*/
|
|
124
|
+
query?: Record<string, boolean | number | string>;
|
|
125
|
+
/**
|
|
126
|
+
* @description Custom function to parse the response string into a object.
|
|
127
|
+
*/
|
|
128
|
+
responseParser?: (responseString: string) => Record<string, unknown>;
|
|
129
|
+
/**
|
|
130
|
+
* @description Expected response type, affects how response is parsed
|
|
131
|
+
* @default "json"
|
|
132
|
+
*/
|
|
133
|
+
responseType?: keyof ReturnType<typeof handleResponseType>;
|
|
134
|
+
/**
|
|
135
|
+
* @description Custom function to validate the response data.
|
|
136
|
+
*/
|
|
137
|
+
responseValidator?: (data: unknown) => TData;
|
|
138
|
+
/**
|
|
139
|
+
* @description Mode of the result, can influence how results are handled or returned.
|
|
140
|
+
* Can be set to "all" | "onlySuccess" | "onlyError" | "onlyResponse".
|
|
141
|
+
* @default "all"
|
|
142
|
+
*/
|
|
143
|
+
resultMode?: TResultMode;
|
|
144
|
+
/**
|
|
145
|
+
* @description Number of retry attempts for failed requests
|
|
146
|
+
* @default 0
|
|
147
|
+
*/
|
|
148
|
+
retries?: number;
|
|
149
|
+
/**
|
|
150
|
+
* @description HTTP status codes that trigger a retry
|
|
151
|
+
* @default [409, 425, 429, 500, 502, 503, 504]
|
|
152
|
+
*/
|
|
153
|
+
retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
|
|
154
|
+
/**
|
|
155
|
+
* @description Delay between retries in milliseconds
|
|
156
|
+
* @default 500
|
|
157
|
+
*/
|
|
158
|
+
retryDelay?: number;
|
|
159
|
+
/**
|
|
160
|
+
* HTTP methods that are allowed to retry
|
|
161
|
+
* @default ["GET", "POST"]
|
|
162
|
+
*/
|
|
163
|
+
retryMethods?: Array<"GET" | "POST" | AnyString>;
|
|
164
|
+
/**
|
|
165
|
+
* If true or the function returns true, throws errors instead of returning them
|
|
166
|
+
* The function is passed the error object and can be used to conditionally throw the error
|
|
167
|
+
* @default false
|
|
168
|
+
*/
|
|
169
|
+
throwOnError?: ((error?: Error | HTTPError<TErrorData>) => boolean) | boolean;
|
|
170
|
+
/**
|
|
171
|
+
* @description Request timeout in milliseconds
|
|
172
|
+
*/
|
|
173
|
+
timeout?: number;
|
|
177
174
|
}
|
|
178
|
-
type ResponseContext<TData> = {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
175
|
+
type ResponseContext<TData> = Prettify<{
|
|
176
|
+
data: TData;
|
|
177
|
+
options: ExtraOptions;
|
|
178
|
+
request: $RequestOptions;
|
|
179
|
+
response: Response;
|
|
180
|
+
}>;
|
|
181
|
+
type ResponseErrorContext<TErrorData> = Prettify<{
|
|
182
|
+
errorData: TErrorData;
|
|
183
|
+
options: ExtraOptions;
|
|
184
|
+
request: $RequestOptions;
|
|
185
|
+
response: Response;
|
|
186
|
+
}>;
|
|
187
|
+
type ErrorContext<TErrorData> = Prettify<{
|
|
188
|
+
error: Error;
|
|
189
|
+
errorData?: null;
|
|
190
|
+
options: ExtraOptions;
|
|
191
|
+
request: $RequestOptions;
|
|
192
|
+
response: null;
|
|
193
|
+
} | {
|
|
194
|
+
error: null;
|
|
195
|
+
errorData?: TErrorData;
|
|
196
|
+
options: ExtraOptions;
|
|
197
|
+
request: $RequestOptions;
|
|
198
|
+
response: Response;
|
|
199
|
+
}>;
|
|
200
|
+
interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = "all"> extends Omit<RequestInit, "body" | "method">, ExtraOptions<TData, TErrorData, TResultMode> {
|
|
195
201
|
}
|
|
196
|
-
type BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion =
|
|
202
|
+
type BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = "all"> = FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode>;
|
|
197
203
|
type ApiSuccessVariant<TData> = {
|
|
198
204
|
data: TData;
|
|
199
205
|
error: null;
|
|
200
206
|
response: Response;
|
|
201
207
|
};
|
|
202
208
|
type PossibleErrorNames = {
|
|
203
|
-
_: "AbortError" | "
|
|
209
|
+
_: "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | "UnknownError";
|
|
204
210
|
}["_"];
|
|
205
211
|
type ApiErrorVariant<TErrorData> = {
|
|
206
212
|
data: null;
|
|
207
213
|
error: {
|
|
208
|
-
|
|
209
|
-
errorData: TErrorData;
|
|
214
|
+
errorData: Error;
|
|
210
215
|
message: string;
|
|
216
|
+
name: PossibleErrorNames;
|
|
211
217
|
};
|
|
212
|
-
response:
|
|
218
|
+
response: null;
|
|
213
219
|
} | {
|
|
214
220
|
data: null;
|
|
215
221
|
error: {
|
|
216
|
-
|
|
217
|
-
errorData: Error;
|
|
222
|
+
errorData: TErrorData;
|
|
218
223
|
message: string;
|
|
224
|
+
name: "HTTPError";
|
|
219
225
|
};
|
|
220
|
-
response:
|
|
226
|
+
response: Response;
|
|
221
227
|
};
|
|
222
228
|
type ResultModeMap<TData = unknown, TErrorData = unknown> = {
|
|
223
|
-
all:
|
|
224
|
-
onlySuccess: ApiSuccessVariant<TData>["data"];
|
|
229
|
+
all: ApiErrorVariant<TErrorData> | ApiSuccessVariant<TData>;
|
|
225
230
|
onlyError: ApiErrorVariant<TErrorData>["error"];
|
|
226
231
|
onlyResponse: Response;
|
|
232
|
+
onlySuccess: ApiSuccessVariant<TData>["data"];
|
|
227
233
|
};
|
|
228
234
|
type ResultModeUnion = {
|
|
229
235
|
_: {
|
|
@@ -235,16 +241,13 @@ type GetCallApiResult<TData, TErrorData, TResultMode> = TResultMode extends NonN
|
|
|
235
241
|
declare const createFetchClient: <TBaseData, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
236
242
|
<TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeUnion = TBaseResultMode>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode>): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
237
243
|
create: any;
|
|
238
|
-
cancel(url: string, reason?: unknown): void;
|
|
239
244
|
};
|
|
240
245
|
declare const callApi: {
|
|
241
246
|
<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = undefined>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode> | undefined): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
242
247
|
create: <TBaseData, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
243
248
|
<TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeUnion = TBaseResultMode>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode>): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
244
249
|
create: any;
|
|
245
|
-
cancel(url: string, reason?: unknown): void;
|
|
246
250
|
};
|
|
247
|
-
cancel(url: string, reason?: unknown): void;
|
|
248
251
|
};
|
|
249
252
|
|
|
250
|
-
export { type $RequestOptions, type ExtraOptions, type FetchConfig,
|
|
253
|
+
export { type $RequestOptions, type ErrorContext, type ExtraOptions, type FetchConfig, type ResponseContext, type ResponseErrorContext, callApi, createFetchClient };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var r=r=>Array.isArray(r),t=r=>!("object"!=typeof r||null===r||r instanceof FormData||Array.isArray(r)),o=r=>"function"==typeof r,a=r=>"string"==typeof r,e=r=>"string"==typeof r&&r.includes("=");export{r as isArray,o as isFunction,t as isObject,e as isQueryString,a as isString};//# sourceMappingURL=chunk-AKFUJ4JG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/typeof.ts"],"names":[],"mappings":";AAEO,IAAM,OAAU,GAAA,CAAS,KAAsC,KAAA,KAAA,CAAM,QAAQ,KAAK,EAAA;AAE5E,IAAA,QAAA,GAAW,CAA0C,KAAqC,KAAA;AACtG,EACC,OAAA,OAAO,KAAU,KAAA,QAAA,IAAY,KAAU,KAAA,IAAA,IAAQ,EAAE,KAAA,YAAiB,QAAa,CAAA,IAAA,CAAC,KAAM,CAAA,OAAA,CAAQ,KAAK,CAAA,CAAA;AAErG,EAAA;AAEO,IAAM,UAAa,GAAA,CAAgC,KACzD,KAAA,OAAO,KAAU,KAAA,WAAA;AAEX,IAAM,QAAW,GAAA,CAAC,KAAmB,KAAA,OAAO,KAAU,KAAA,SAAA;AAEhD,IAAA,aAAA,GAAgB,CAAC,KAC7B,KAAA,OAAO,UAAU,QAAY,IAAA,KAAA,CAAM,SAAS,GAAG","file":"chunk-AKFUJ4JG.js","sourcesContent":["import type { AnyFunction } from \"./type-helpers\";\n\nexport const isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn (\n\t\ttypeof value === \"object\" && value !== null && !(value instanceof FormData) && !Array.isArray(value)\n\t);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n\nexport const isString = (value: unknown) => typeof value === \"string\";\n\nexport const isQueryString = (value: unknown): value is string =>\n\ttypeof value === \"string\" && value.includes(\"=\");\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isObject as r,isArray as e,isFunction as o}from"./chunk-AKFUJ4JG.js";var t=(r,e)=>`${r} | ${JSON.stringify(e??{})}`,s=r=>r?new URLSearchParams(r).toString():(console.error("toQueryString:","No query params provided!"),null),n=(r,e)=>{if(!e)return r;const o=s(e);return r.endsWith("?")?`${r}${o}`:r.includes("?")?`${r}&${o}`:`${r}?${o}`},a=o=>!o||r(o)?o:Object.fromEntries(e(o)?o:o.entries()),i=Object.keys({408:"Request Timeout",409:"Conflict",425:"Too Early",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"}).map(Number),l=["GET"],c=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],u=(r,e)=>{const o=Object.entries(r).filter((([r])=>!e.includes(r)));return Object.fromEntries(o)},m=(r,e)=>{const o=new Set(e),t=Object.entries(r).filter((([r])=>o.has(r)));return Object.fromEntries(t)},d=r=>[m(r,c),u(r,c)],f=(r,e)=>({arrayBuffer:()=>r.arrayBuffer(),blob:()=>r.blob(),formData:()=>r.formData(),json:async()=>e?e(await r.text()):r.json(),text:()=>r.text()}),p=(r,e,o)=>{const t=f(r,o);if(!Object.hasOwn(t,e))throw new Error(`Invalid response type: ${e}`);return t[e]()},E=r=>{const{options:e,response:o,successData:t}=r,s={data:t,error:null,response:o};return e.resultMode&&"all"!==e.resultMode?{onlyError:s.error,onlyResponse:s.response,onlySuccess:s.data}[e.resultMode]:s},y=r=>{const{error:e,options:t}=r;return(r={})=>{const{errorData:s,message:n,response:a}=r;if(o(t.throwOnError)?t.throwOnError(e):t.throwOnError)throw e;return{data:null,error:{errorData:s??e,message:n??e?.message??t.defaultErrorMessage,name:e?.name??"UnknownError"},response:a??null}}},h=e=>r(e)&&"HTTPError"===e.name,w=class extends Error{errorData;isHTTPError=!0;name="HTTPError";response;constructor(r,e){const{defaultErrorMessage:o,errorData:t,response:s}=r;super(t.message??o,e),this.errorData=t,this.response=s}},T=e=>e instanceof w||r(e)&&"HTTPError"===e.name&&!0===e.isHTTPError,b=r=>{if(0===r)return;const{promise:e,resolve:o}=Promise.withResolvers();return setTimeout(o,r),e};export{w as HTTPError,i as defaultRetryCodes,l as defaultRetryMethods,c as fetchSpecificKeys,t as getRequestKey,y as getResolveErrorResultFn,p as getResponseData,f as handleResponseType,h as isHTTPError,T as isHTTPErrorInstance,n as mergeUrlWithParams,a as objectifyHeaders,u as omitKeys,E as resolveSuccessResult,d as splitConfig,s as toQueryString,b as waitUntil};//# sourceMappingURL=chunk-F6RUPSGH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils.ts"],"names":[],"mappings":"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","file":"chunk-F6RUPSGH.js","sourcesContent":["import { isArray, isFunction, isObject } from \"./typeof\";\nimport type {\n\t$BaseRequestOptions,\n\t$RequestOptions,\n\tApiErrorVariant,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\n// prettier-ignore\nexport const getRequestKey = <TConfig extends Record<string, unknown>>(url: string, config?: TConfig) => `${url} | ${JSON.stringify(config ?? {})}`;\n\ntype ToQueryStringFn = {\n\t(params: ExtraOptions[\"query\"]): null | string;\n\t(params: Required<ExtraOptions>[\"query\"]): string;\n};\n\nexport const toQueryString: ToQueryStringFn = (params) => {\n\tif (!params) {\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\n\n\t\treturn null as never;\n\t}\n\n\treturn new URLSearchParams(params as Record<string, string>).toString();\n};\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = toQueryString(params);\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\tif (url.includes(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nexport const omitKeys = <\n\tTObject extends Record<string, unknown>,\n\tconst TOmitArray extends Array<keyof TObject>,\n>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype data = {\n\toptions: ExtraOptions;\n\tresponse: Response;\n\tsuccessData: unknown;\n};\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 = <CallApiResult>(info: data): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = {\n\t\tdata: successData,\n\t\terror: null,\n\t\tresponse,\n\t};\n\n\tif (!options.resultMode || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlyError: apiDetails.error,\n\t\tonlyResponse: apiDetails.response,\n\t\tonlySuccess: apiDetails.data,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const getResolveErrorResultFn = <CallApiResult>($info: {\n\terror?: unknown;\n\toptions: ExtraOptions;\n}) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t\tresponse?: Response;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\terrorData: errorData ?? error,\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t\tname: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\n\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\n\treturn isObject(error) && error.name === \"HTTPError\";\n};\n\ntype ErrorDetails<TErrorResponse> = {\n\tdefaultErrorMessage: string;\n\terrorData: TErrorResponse;\n\tresponse: Response;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\n\tisHTTPError = true;\n\n\toverride name = \"HTTPError\" as const;\n\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\n\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.errorData = errorData;\n\t\tthis.response = response;\n\t}\n}\n\n// prettier-ignore\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const waitUntil = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{splitConfig as e,defaultRetryCodes as r,defaultRetryMethods as o,objectifyHeaders as t,getRequestKey as s,omitKeys as n,mergeUrlWithParams as a,waitUntil as i,getResponseData as u,HTTPError as l,resolveSuccessResult as c,getResolveErrorResultFn as p,isHTTPErrorInstance as d}from"./chunk-F6RUPSGH.js";import{isObject as m,isQueryString as h,isString as y}from"./chunk-AKFUJ4JG.js";var f=R=>{const w=new Map,[b,E]=e(R??{}),{body:g,headers:q,signal:D,...A}=b,$=async(f,R)=>{const[b,M]=e(R??{}),{body:S=g,headers:T,signal:k=D,...j}=b,x={baseURL:"",bodySerializer:JSON.stringify,cancelRedundantRequests:!0,defaultErrorMessage:"Failed to fetch data from server!",responseType:"json",retries:0,retryCodes:r,retryDelay:0,retryMethods:o,...E,...M},C={body:m(S)?x.bodySerializer(S):S,headers:q||T||x.auth||m(S)?{...m(S)&&{Accept:"application/json","Content-Type":"application/json"},...h(S)&&{"Content-Type":"application/x-www-form-urlencoded"},...y(x.auth)&&{Authorization:`Bearer ${x.auth}`},...m(x.auth)&&{Authorization:"bearer"in x.auth?`Bearer ${x.auth.bearer}`:`Token ${x.auth.token}`},...t(q),...t(T)}:void 0,method:"GET",...A,...j},P=s(f,n({...C,...x},["onRequest","onResponse","onResponseError","onError","onRequestError"])),v=w.get(P);if(v&&x.cancelRedundantRequests){const e=new DOMException(`Automatic cancelation of the previous unfinished request to the same url, with the same fetch options: ${f}`,"AbortError");v.abort(e)}const z=new AbortController;w.set(P,z);const O=x.timeout?AbortSignal.timeout(x.timeout):null,U=AbortSignal.any([z.signal,...O?[O]:[],...k?[k]:[]]),F={signal:U,...C};try{await(x.onRequest?.({options:x,request:F}));const e=await fetch(`${x.baseURL}${a(f,x.query)}`,F);if(!e.ok&&!U.aborted&&x.retries>0&&x.retryCodes.includes(e.status)&&x.retryMethods.includes(F.method))return await i(x.retryDelay),await $(f,{...R,retries:x.retries-1});if(!e.ok){const r=await u(x.cloneResponse?e.clone():e,x.responseType,x.responseParser);throw new l({defaultErrorMessage:x.defaultErrorMessage,errorData:r,response:e})}const r=await u(x.cloneResponse?e.clone():e,x.responseType,x.responseParser),o=x.responseValidator?x.responseValidator(r):r;return await(x.onResponse?.({data:o,options:x,request:F,response:x.cloneResponse?e.clone():e})),c({options:x,response:e,successData:o})}catch(e){const r=p({error:e,options:x});if(e instanceof DOMException&&"TimeoutError"===e.name){const o=`Request timed out after ${x.timeout}ms`;return console.error(`${e.name}:`,o),r({message:o})}if(e instanceof DOMException&&"AbortError"===e.name){const o=`Request aborted due to ${e.message}`;return console.error(`${e.name}:`,o),r({message:o})}if(d(e)){const{errorData:o,response:t}=e;return await Promise.allSettled([x.onResponseError?.({errorData:o,options:x,request:F,response:x.cloneResponse?t.clone():t}),x.onError?.({error:null,errorData:o,options:x,request:F,response:t})]),r({errorData:o,message:o?.message,response:t})}return await Promise.allSettled([x.onRequestError?.({error:e,options:x,request:F}),x.onError?.({error:e,errorData:null,options:x,request:F,response:null})]),r()}finally{w.delete(P)}};return $.create=f,$},R=f();export{R as callApi,f as createFetchClient};//# sourceMappingURL=chunk-KQNDKJNJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/createFetchClient.ts"],"names":["callApi"],"mappings":"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","file":"chunk-KQNDKJNJ.js","sourcesContent":["import { isObject, isQueryString, isString } from \"./typeof\";\nimport type {\n\t$RequestOptions,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultModeUnion,\n} from \"./types\";\nimport {\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetRequestKey,\n\tgetResolveErrorResultFn,\n\tgetResponseData,\n\tisHTTPErrorInstance,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tomitKeys,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twaitUntil,\n} from \"./utils\";\n\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData = unknown,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\tbody: baseBody,\n\t\theaders: baseHeaders,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\n\n\t\t// == Default Extra Options\n\t\tconst options = {\n\t\t\tbaseURL: \"\",\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tcancelRedundantRequests: true,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tresponseType: \"json\",\n\t\t\tretries: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryDelay: 0,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\t// == Default Fetch Config\n\t\tconst defaultFetchOptions = {\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// - The auth option is provided\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || options.auth || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isQueryString(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\n\t\t\t// - headers are provided\n\t\t\t// - The body is an object\n\t\t\tmethod: \"GET\",\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\tconst requestKey = getRequestKey(\n\t\t\turl,\n\t\t\tomitKeys({ ...defaultFetchOptions, ...options }, [\n\t\t\t\t\"onRequest\",\n\t\t\t\t\"onResponse\",\n\t\t\t\t\"onResponseError\",\n\t\t\t\t\"onError\",\n\t\t\t\t\"onRequestError\",\n\t\t\t])\n\t\t);\n\n\t\tconst prevFetchController = abortControllerStore.get(requestKey);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\n\t\t\t\t`Automatic cancelation of the previous unfinished request to the same url, with the same fetch options: ${url}`,\n\t\t\t\t\"AbortError\"\n\t\t\t);\n\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(requestKey, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\tconst combinedSignal = AbortSignal.any([\n\t\t\tnewFetchController.signal,\n\t\t\t...(timeoutSignal ? [timeoutSignal] : []),\n\t\t\t...(signal ? [signal] : []),\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\t\t\t...defaultFetchOptions,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ options, request: requestInit });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\toptions.cloneResponse ? 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\t// == Pushing all error handling responsibilities to the catch block\n\t\t\t\tthrow new HTTPError({\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\toptions.cloneResponse ? 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 = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tdata: validSuccessData,\n\t\t\t\toptions,\n\t\t\t\trequest: requestInit,\n\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ options, response, successData: validSuccessData });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = getResolveErrorResultFn<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tconst message = `Request aborted due to ${error.message}`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst { errorData, response } = error;\n\n\t\t\t\tvoid (await Promise.allSettled([\n\t\t\t\t\toptions.onResponseError?.({\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t\t\t}),\n\n\t\t\t\t\t// == Also call the onError interceptor\n\t\t\t\t\toptions.onError?.({\n\t\t\t\t\t\terror: null,\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}),\n\t\t\t\t]));\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid (await Promise.allSettled([\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request: requestInit }),\n\n\t\t\t\t// == Also call the onError interceptor\n\t\t\t\toptions.onError?.({\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\terrorData: null,\n\t\t\t\t\toptions,\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\tresponse: null,\n\t\t\t\t}),\n\t\t\t]));\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(requestKey);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n"]}
|