@zayne-labs/callapi 1.0.0-rc.21 → 1.0.0-rc.22
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 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/utils/index.cjs.map +1 -1
- package/dist/esm/{chunk-LJI67ND4.js → chunk-O3QDH76S.js} +1 -1
- package/dist/esm/chunk-O3QDH76S.js.map +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/package.json +2 -2
- package/dist/esm/chunk-LJI67ND4.js.map +0 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,r=Object.defineProperty,o=Object.getOwnPropertyDescriptor,t=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,n={};((e,o)=>{for(var t in o)r(e,t,{get:o[t],enumerable:!0})})(n,{callApi:()=>
|
|
1
|
+
"use strict";var e,r=Object.defineProperty,o=Object.getOwnPropertyDescriptor,t=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,n={};((e,o)=>{for(var t in o)r(e,t,{get:o[t],enumerable:!0})})(n,{callApi:()=>T,createFetchClient:()=>O}),module.exports=(e=n,((e,n,a,l)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let i of t(n))s.call(e,i)||i===a||r(e,i,{get:()=>n[i],enumerable:!(l=o(n,i))||l.enumerable});return e})(r({},"__esModule",{value:!0}),e));var a=e=>Array.isArray(e),l=e=>!("object"!=typeof e||null===e||e instanceof FormData||a(e)),i=e=>"string"==typeof e,u="&",c=(e,r)=>{if(!r)return e;const o=(t=r)?new URLSearchParams(t).toString():(console.error("toQueryString:","No query params provided!"),null);var t;return 0===o?.length?e:e.endsWith("?")?`${e}${o}`:e.includes("?")?`${e}${u}${o}`:`${e}?${o}`},p=(e,r,o)=>{const t=((e,r)=>{if(!r)return e;let o=e;if(a(r)){const e=o.split("/").filter((e=>e.startsWith(":")));for(const[t,s]of e.entries()){const e=r[t];o=o.replace(s,e)}return o}for(const[e,t]of Object.entries(r))o=o.replace(`:${e}`,String(t));return o})(e,r);return c(t,o)},d=e=>!e||l(e)?e:Object.fromEntries(a(e)?e:e.entries()),m=e=>{const{auth:r,baseHeaders:o,body:t,headers:s}=e;var n;if(o||s||t||r)return{...l(t)&&{Accept:"application/json","Content-Type":"application/json"},...(n=t,i(n)&&n.includes("=")&&{"Content-Type":"application/x-www-form-urlencoded"}),...(i(r)||null===r)&&{Authorization:`Bearer ${r}`},...l(r)&&{Authorization:"bearer"in r?`Bearer ${r.bearer}`:`Token ${r.token}`},...d(o),...d(s)}},f=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),y=["GET"],g=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],E=(e,r)=>{const o=Object.entries(e).filter((([e])=>!r.includes(e)));return Object.fromEntries(o)},h=(e,r)=>{const o=new Set(r),t=Object.entries(e).filter((([e])=>o.has(e)));return Object.fromEntries(t)},b=(e,r,o,t)=>{if(a(e)&&o){return async o=>{const s=[...e,...r?[r]:[]],n=[...new Set(s)];if("sequential"===t)for(const e of n)await e(o);"parallel"===t&&await Promise.all(n.map((e=>e(o))))}}return r??e},w=(e,r,o)=>{const t=((e,r)=>({arrayBuffer:()=>e.arrayBuffer(),blob:()=>e.blob(),formData:()=>e.formData(),json:async()=>r?r(await e.text()):e.json(),text:()=>e.text()}))(e,o);if(!Object.hasOwn(t,r))throw new Error(`Invalid response type: ${r}`);return t[r]()},R=e=>{const{defaultErrorMessage:r,error:o,message:t,resultMode:s}=e;let n;if(q(o)){const{errorData:e,message:t=r,name:s,response:a}=o;n={data:null,error:{errorData:e,message:t,name:s},response:a}}if(o){const{message:e,name:r}=o;n={data:null,error:{errorData:o,message:t??e,name:r},response:null}}return{apiDetails:n,generalErrorResult:{all:n,onlyError:n.error,onlyResponse:n.response,onlySuccess:n.data}[s??"all"]??n,resolveCustomErrorInfo:({message:r})=>R({...e,message:r}).generalErrorResult}},M=class extends Error{errorData;isHTTPError=!0;name="HTTPError";response;constructor(e,r){const{defaultErrorMessage:o,errorData:t,response:s}=e;super(t.message??o,r),this.errorData=t,this.response=s,Error.captureStackTrace(this,this.constructor)}},q=e=>e instanceof M||l(e)&&"HTTPError"===e.name&&!0===e.isHTTPError,S=e=>{if(0===e)return;const{promise:r,resolve:o}=(()=>{let e,r;return{promise:new Promise(((o,t)=>{r=o,e=t})),reject:e,resolve:r}})();return setTimeout(o,e),r},D=(...e)=>Promise.all(e),O=(e={})=>{const[r,o]=(e=>[h(e,g),E(e,[...g,"requestKey"])])(e),{body:t,headers:s,signal:n,...a}=r,{onError:i,onRequest:c,onRequestError:d,onResponse:T,onResponseError:$,onSuccess:j,...v}=o,I=new Map,P=async(e,r={})=>{const[o,O]=(e=>[h(e,g),E(e,g)])(r),{body:x=t,headers:C,signal:A=n,...k}=o,{onError:H,onRequest:B,onRequestError:N,onResponse:z,onResponseError:G,onSuccess:U,...F}=O,L={baseURL:"",bodySerializer:JSON.stringify,dedupeStrategy:"cancel",defaultErrorMessage:"Failed to fetch data from server!",mergedInterceptorsExecutionMode:"parallel",mergeInterceptors:!0,responseType:"json",resultMode:"all",retries:0,retryCodes:f,retryDelay:0,retryMethods:y,...v,...F},J={...{onError:b(i,H,L.mergeInterceptors,L.mergedInterceptorsExecutionMode),onRequest:b(c,B,L.mergeInterceptors,L.mergedInterceptorsExecutionMode),onRequestError:b(d,N,L.mergeInterceptors,L.mergedInterceptorsExecutionMode),onResponse:b(T,z,L.mergeInterceptors,L.mergedInterceptorsExecutionMode),onResponseError:b($,G,L.mergeInterceptors,L.mergedInterceptorsExecutionMode),onSuccess:b(j,U,L.mergeInterceptors,L.mergedInterceptorsExecutionMode)},...L},K=`${J.baseURL}${p(e,J.params,J.query)}`,V={method:"GET",body:l(x)?J.bodySerializer(x):x,headers:m({auth:J.auth,baseHeaders:s,body:x,headers:C}),...a,...k},W="cancel"===J.dedupeStrategy||"defer"===J.dedupeStrategy,_=J.requestKey??(W?((e,r)=>`${e} ${u} ${JSON.stringify(r)}`)(K,{...V,...J}):null);null!=_&&await S(.1);const Q=_?I:null,X=Q?.get(_);if(X&&"cancel"===J.dedupeStrategy){const r=new DOMException(`Request aborted as another request to the endpoint: ${e}, with the same request options was initiated.`,"AbortError");X.controller.abort(r)}const Y=new AbortController,Z=null!=J.timeout?(ee=J.timeout,AbortSignal.timeout(ee)):null;var ee;const re=((...e)=>AbortSignal.any(e.filter(Boolean)))(Y.signal,Z,A),oe={signal:re,...V},te={url:K,...oe};try{await D(J.onRequest?.({options:J,request:te})),oe.headers=m({auth:J.auth,baseHeaders:s,body:te.body,headers:te.headers}),te.headers=oe.headers;const o=X&&"defer"===J.dedupeStrategy?X.responsePromise:fetch(K,oe);Q?.set(_,{controller:Y,responsePromise:o});const t=await o;if(!t.ok&&!re.aborted&&J.retries>0&&J.retryCodes.includes(t.status)&&J.retryMethods.includes(oe.method))return await S(J.retryDelay),await P(e,{...r,retries:J.retries-1});const n="defer"===J.dedupeStrategy||"onlyResponse"===J.resultMode||J.shouldCloneResponse;if(!t.ok){const e=await w(n?t.clone():t,J.responseType,J.responseParser);throw new M({defaultErrorMessage:J.defaultErrorMessage,errorData:e,response:t})}const a=await w(n?t.clone():t,J.responseType,J.responseParser),l=J.responseValidator?J.responseValidator(a):a;return await D(J.onSuccess?.({data:l,options:J,request:te,response:J.shouldCloneResponse?t.clone():t}),J.onResponse?.({data:l,errorData:null,options:J,request:te,response:J.shouldCloneResponse?t.clone():t})),(e=>{const{response:r,resultMode:o,successData:t}=e,s={data:t,error:null,response:r};return o?{all:s,onlyError:s.error,onlyResponse:s.response,onlySuccess:s.data}[o]:s})({response:t,resultMode:J.resultMode,successData:l})}catch(e){const{apiDetails:r,generalErrorResult:o,resolveCustomErrorInfo:t}=R({defaultErrorMessage:J.defaultErrorMessage,error:e,resultMode:J.resultMode}),s="function"==typeof J.throwOnError?J.throwOnError({error:r.error,options:J,request:te}):J.throwOnError,n=()=>{if(s)throw r.error};if(e instanceof DOMException&&"TimeoutError"===e.name){const r=`Request timed out after ${J.timeout}ms`;return console.error(`${e.name}:`,r),n(),t({message:r})}if(e instanceof DOMException&&"AbortError"===e.name){const{message:r,name:t}=e;return console.error(`${t}:`,r),n(),o}if(q(e)){const{errorData:r,response:t}=e;return await D(J.onResponseError?.({errorData:r,options:J,request:te,response:J.shouldCloneResponse?t.clone():t}),J.onResponse?.({data:null,errorData:r,options:J,request:te,response:J.shouldCloneResponse?t.clone():t}),J.onError?.({error:e,options:J,request:te,response:J.shouldCloneResponse?t.clone():t})),n(),o}return await D(J.onRequestError?.({error:e,options:J,request:te}),J.onError?.({error:o.error,options:J,request:te,response:null})),n(),o}finally{Q?.delete(_)}};return P.create=O,P},T=O();//# sourceMappingURL=index.cjs.map
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/utils/typeof.ts","../../src/utils/common.ts","../../src/utils/polyfills.ts","../../src/createFetchClient.ts"],"sourcesContent":["export { callApi, createFetchClient } from \"./createFetchClient\";\r\n\r\nexport type {\r\n\tRequestOptions,\r\n\tCallApiExtraOptions,\r\n\tCallApiConfig,\r\n\tSuccessResponseContext,\r\n\tResponseErrorContext,\r\n\tErrorContext,\r\n} from \"./types\";\r\n","import type { AnyFunction } from \"./type-helpers\";\r\n\r\nexport const isArray = <TArrayItem>(value: unknown): value is TArrayItem[] => Array.isArray(value);\r\n\r\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\r\n\treturn typeof value === \"object\" && value !== null && !(value instanceof FormData) && !isArray(value);\r\n};\r\n\r\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\r\n\ttypeof value === \"function\";\r\n\r\nexport const isQueryString = (value: unknown): value is string => isString(value) && value.includes(\"=\");\r\n\r\nexport const isString = (value: unknown) => typeof value === \"string\";\r\n","import type {\r\n\tApiErrorVariant,\r\n\tBaseCallApiConfig,\r\n\tBaseCallApiExtraOptions,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tPossibleErrorNames,\r\n\tResultModeMap,\r\n} from \"../types\";\r\nimport type { AnyFunction, Awaitable } from \"./type-helpers\";\r\nimport { isArray, isObject, isQueryString, isString } from \"./typeof\";\r\n\r\n// prettier-ignore\r\nexport const generateRequestKey = (url: string, config: Record<string, unknown>) => `${url} ${ampersand} ${JSON.stringify(config)}`;\r\n\r\ntype ToQueryStringFn = {\r\n\t(params: CallApiConfig[\"query\"]): string | null;\r\n\t(params: Required<CallApiConfig>[\"query\"]): string;\r\n};\r\n\r\nexport const toQueryString: ToQueryStringFn = (params) => {\r\n\tif (!params) {\r\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\r\n\r\n\t\treturn null as never;\r\n\t}\r\n\r\n\treturn new URLSearchParams(params as Record<string, string>).toString();\r\n};\r\n\r\nconst slash = \"/\";\r\nconst column = \":\";\r\nconst mergeUrlWithParams = (url: string, params: CallApiExtraOptions[\"params\"]) => {\r\n\tif (!params) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tlet newUrl = url;\r\n\r\n\tif (isArray(params)) {\r\n\t\tconst matchedParamArray = newUrl\r\n\t\t\t.split(slash)\r\n\t\t\t.filter((matchedParam) => matchedParam.startsWith(column));\r\n\r\n\t\tfor (const [index, matchedParam] of matchedParamArray.entries()) {\r\n\t\t\tconst param = params[index] as string;\r\n\t\t\tnewUrl = newUrl.replace(matchedParam, param);\r\n\t\t}\r\n\r\n\t\treturn newUrl;\r\n\t}\r\n\r\n\tfor (const [key, value] of Object.entries(params)) {\r\n\t\tnewUrl = newUrl.replace(`:${key}`, String(value));\r\n\t}\r\n\r\n\treturn newUrl;\r\n};\r\n\r\nconst questionMark = \"?\";\r\nconst ampersand = \"&\";\r\n\r\nconst mergeUrlWithQuery = (url: string, query: CallApiConfig[\"query\"]): string => {\r\n\tif (!query) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tconst queryString = toQueryString(query);\r\n\r\n\tif (queryString?.length === 0) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tif (url.endsWith(questionMark)) {\r\n\t\treturn `${url}${queryString}`;\r\n\t}\r\n\r\n\tif (url.includes(questionMark)) {\r\n\t\treturn `${url}${ampersand}${queryString}`;\r\n\t}\r\n\r\n\treturn `${url}${questionMark}${queryString}`;\r\n};\r\n\r\nexport const mergeUrlWithParamsAndQuery = (\r\n\turl: string,\r\n\tparams: CallApiExtraOptions[\"params\"],\r\n\tquery: CallApiExtraOptions[\"query\"]\r\n) => {\r\n\tconst urlWithMergedParams = mergeUrlWithParams(url, params);\r\n\r\n\treturn mergeUrlWithQuery(urlWithMergedParams, query);\r\n};\r\n\r\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\r\n\tif (!headers || isObject(headers)) {\r\n\t\treturn headers;\r\n\t}\r\n\r\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\r\n};\r\n\r\nexport const resolveHeaders = (options: {\r\n\tauth: CallApiConfig[\"auth\"];\r\n\tbaseHeaders: CallApiConfig[\"headers\"];\r\n\tbody: CallApiConfig[\"body\"];\r\n\theaders: CallApiConfig[\"headers\"];\r\n}) => {\r\n\tconst { auth, baseHeaders, body, headers } = options;\r\n\r\n\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing\r\n\tconst shouldResolveHeaders = baseHeaders || headers || body || auth;\r\n\r\n\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\r\n\t// - headers are provided\r\n\t// - The body is an object\r\n\t// - The auth option is provided\r\n\tif (!shouldResolveHeaders) return;\r\n\r\n\treturn {\r\n\t\t...(isObject(body) && {\r\n\t\t\tAccept: \"application/json\",\r\n\t\t\t\"Content-Type\": \"application/json\",\r\n\t\t}),\r\n\t\t...(isQueryString(body) && {\r\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\r\n\t\t}),\r\n\t\t...((isString(auth) || auth === null) && {\r\n\t\t\tAuthorization: `Bearer ${auth}`,\r\n\t\t}),\r\n\t\t...(isObject(auth) && {\r\n\t\t\tAuthorization: \"bearer\" in auth ? `Bearer ${auth.bearer}` : `Token ${auth.token}`,\r\n\t\t}),\r\n\t\t...objectifyHeaders(baseHeaders),\r\n\t\t...objectifyHeaders(headers),\r\n\t};\r\n};\r\n\r\nconst retryCodesLookup = {\r\n\t408: \"Request Timeout\",\r\n\t409: \"Conflict\",\r\n\t425: \"Too Early\",\r\n\t429: \"Too Many Requests\",\r\n\t500: \"Internal Server Error\",\r\n\t502: \"Bad Gateway\",\r\n\t503: \"Service Unavailable\",\r\n\t504: \"Gateway Timeout\",\r\n};\r\n\r\nexport const defaultRetryCodes: Required<BaseCallApiConfig>[\"retryCodes\"] =\r\n\tObject.keys(retryCodesLookup).map(Number);\r\n\r\nexport const defaultRetryMethods: Required<BaseCallApiConfig>[\"retryMethods\"] = [\"GET\"];\r\n\r\nexport const fetchSpecificKeys = [\r\n\t\"body\",\r\n\t\"integrity\",\r\n\t\"method\",\r\n\t\"headers\",\r\n\t\"signal\",\r\n\t\"cache\",\r\n\t\"redirect\",\r\n\t\"window\",\r\n\t\"credentials\",\r\n\t\"keepalive\",\r\n\t\"referrer\",\r\n\t\"priority\",\r\n\t\"mode\",\r\n\t\"referrerPolicy\",\r\n] satisfies Array<keyof RequestInit>;\r\n\r\nexport const omitKeys = <\r\n\tTObject extends Record<string, unknown>,\r\n\tconst TOmitArray extends Array<keyof TObject>,\r\n>(\r\n\tinitialObject: TObject,\r\n\tkeysToOmit: TOmitArray\r\n) => {\r\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\r\n\t\t([key]) => !keysToOmit.includes(key)\r\n\t);\r\n\r\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\r\n\r\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\r\n};\r\n\r\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\r\n\tinitialObject: TObject,\r\n\tkeysToPick: TPickArray\r\n) => {\r\n\tconst keysToPickSet = new Set(keysToPick);\r\n\r\n\tconst arrayFromInitObject = Object.entries(initialObject);\r\n\r\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\r\n\r\n\tconst updatedObject = Object.fromEntries(filteredArray);\r\n\r\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\r\n};\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitBaseConfig = (baseConfig: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(baseConfig, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(baseConfig, [...fetchSpecificKeys, \"requestKey\"] satisfies Array<\r\n\t\t\tkeyof CallApiConfig\r\n\t\t>) as BaseCallApiExtraOptions,\r\n\t] as const;\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitConfig = (config: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(config, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(config, fetchSpecificKeys) as CallApiExtraOptions,\r\n\t] as const;\r\n\r\nexport const handleInterceptorsMerge = <\r\n\tTBaseInterceptor extends AnyFunction<Awaitable<void>> | Array<AnyFunction<Awaitable<void>>>,\r\n\tTInterceptor extends AnyFunction<Awaitable<void>>,\r\n>(\r\n\tbaseInterceptor: TBaseInterceptor | undefined,\r\n\tinterceptor: TInterceptor | undefined,\r\n\tmergeInterceptors: CallApiExtraOptions[\"mergeInterceptors\"],\r\n\tmergedInterceptorsExecutionMode: CallApiExtraOptions[\"mergedInterceptorsExecutionMode\"]\r\n) => {\r\n\tif (isArray(baseInterceptor) && mergeInterceptors) {\r\n\t\tconst mergedInterceptor = async (ctx: Record<string, unknown>) => {\r\n\t\t\tconst interceptorArray = [...baseInterceptor, ...(interceptor ? [interceptor] : [])] as Array<\r\n\t\t\t\tAnyFunction<Awaitable<void>>\r\n\t\t\t>;\r\n\r\n\t\t\tconst uniqueInterceptorArray = [...new Set(interceptorArray)];\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"sequential\") {\r\n\t\t\t\tfor (const uniqueInterceptor of uniqueInterceptorArray) {\r\n\t\t\t\t\t// eslint-disable-next-line no-await-in-loop\r\n\t\t\t\t\tawait uniqueInterceptor(ctx);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"parallel\") {\r\n\t\t\t\tawait Promise.all(uniqueInterceptorArray.map((uniqueInterceptor) => uniqueInterceptor(ctx)));\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\treturn mergedInterceptor;\r\n\t}\r\n\r\n\treturn interceptor ?? (baseInterceptor as typeof interceptor);\r\n};\r\n\r\nexport const handleResponseType = <TResponse>(\r\n\tresponse: Response,\r\n\tparser?: Required<CallApiExtraOptions>[\"responseParser\"]\r\n) => ({\r\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\r\n\tblob: () => response.blob() as Promise<TResponse>,\r\n\tformData: () => response.formData() as Promise<TResponse>,\r\n\tjson: async () => {\r\n\t\tif (parser) {\r\n\t\t\treturn parser(await response.text());\r\n\t\t}\r\n\r\n\t\treturn response.json() as Promise<TResponse>;\r\n\t},\r\n\ttext: () => response.text() as Promise<TResponse>,\r\n});\r\n\r\nexport const getResponseData = <TResponse>(\r\n\tresponse: Response,\r\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\r\n\tparser: CallApiExtraOptions[\"responseParser\"]\r\n) => {\r\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\r\n\r\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\r\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\r\n\t}\r\n\r\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\r\n};\r\n\r\ntype SuccessInfo = {\r\n\tresponse: Response;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n\tsuccessData: unknown;\r\n};\r\n\r\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\r\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\r\nexport const resolveSuccessResult = <CallApiResult>(info: SuccessInfo): CallApiResult => {\r\n\tconst { response, resultMode, successData } = info;\r\n\r\n\tconst apiDetails = {\r\n\t\tdata: successData,\r\n\t\terror: null,\r\n\t\tresponse,\r\n\t};\r\n\r\n\tif (!resultMode) {\r\n\t\treturn apiDetails as CallApiResult;\r\n\t}\r\n\r\n\treturn {\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode] as CallApiResult;\r\n};\r\n\r\ntype ErrorInfo = {\r\n\tdefaultErrorMessage: Required<CallApiExtraOptions>[\"defaultErrorMessage\"];\r\n\terror?: unknown;\r\n\tmessage?: string;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n};\r\n\r\nexport const resolveErrorResult = <CallApiResult>(info: ErrorInfo) => {\r\n\tconst { defaultErrorMessage, error, message: customErrorMessage, resultMode } = info;\r\n\r\n\tlet apiDetails!: ResultModeMap[\"all\"];\r\n\r\n\tif (isHTTPErrorInstance(error)) {\r\n\t\tconst { errorData, message = defaultErrorMessage, name, response } = error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: { errorData, message, name },\r\n\t\t\tresponse,\r\n\t\t};\r\n\t}\r\n\r\n\tif (error) {\r\n\t\tconst { message, name } = error as Error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: {\r\n\t\t\t\terrorData: error as Error,\r\n\t\t\t\tmessage: customErrorMessage ?? message,\r\n\t\t\t\tname: name as PossibleErrorNames,\r\n\t\t\t},\r\n\t\t\tresponse: null,\r\n\t\t};\r\n\t}\r\n\r\n\tconst generalErrorResult = ({\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode ?? \"all\"] ?? apiDetails) as CallApiResult;\r\n\r\n\t// prettier-ignore\r\n\tconst resolveCustomErrorInfo = ({ message }: Pick<ErrorInfo, \"message\">) => {\r\n\t\tconst errorResult = resolveErrorResult<CallApiResult>({ ...info, message });\r\n\r\n\t\treturn errorResult.generalErrorResult;\r\n\t};\r\n\r\n\treturn { generalErrorResult, resolveCustomErrorInfo };\r\n};\r\n\r\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\r\n\treturn isObject(error) && error.name === \"HTTPError\";\r\n};\r\n\r\ntype ErrorDetails<TErrorResponse> = {\r\n\tdefaultErrorMessage: string;\r\n\terrorData: TErrorResponse;\r\n\tresponse: Response;\r\n};\r\n\r\ntype ErrorOptions = {\r\n\tcause?: unknown;\r\n};\r\n\r\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\r\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\r\n\tisHTTPError = true;\r\n\r\n\toverride name = \"HTTPError\" as const;\r\n\r\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\r\n\r\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\r\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\r\n\r\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\r\n\r\n\t\tthis.errorData = errorData;\r\n\t\tthis.response = response;\r\n\r\n\t\tError.captureStackTrace(this, this.constructor);\r\n\t}\r\n}\r\n\r\nexport const isHTTPErrorInstance = <TErrorResponse>(\r\n\terror: unknown\r\n): error is HTTPError<TErrorResponse> => {\r\n\treturn (\r\n\t\t// prettier-ignore\r\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\r\n\t);\r\n};\r\n\r\nconst PromiseWithResolvers = () => {\r\n\tlet reject!: (reason?: unknown) => void;\r\n\tlet resolve!: (value: unknown) => void;\r\n\r\n\tconst promise = new Promise((res, rej) => {\r\n\t\tresolve = res;\r\n\t\treject = rej;\r\n\t});\r\n\r\n\treturn { promise, reject, resolve };\r\n};\r\n\r\nexport const waitUntil = (delay: number) => {\r\n\tif (delay === 0) return;\r\n\r\n\tconst { promise, resolve } = PromiseWithResolvers();\r\n\r\n\tsetTimeout(resolve, delay);\r\n\r\n\treturn promise;\r\n};\r\n\r\nexport const executeInterceptors = <TInterceptor extends Awaitable<void>>(\r\n\t...interceptors: TInterceptor[]\r\n) => Promise.all(interceptors);\r\n","// prettier-ignore\nexport const createCombinedSignal = (...signals: Array<AbortSignal | null | undefined>) => AbortSignal.any(signals.filter(Boolean));\n\nexport const createTimeoutSignal = (milliseconds: number) => AbortSignal.timeout(milliseconds);\n","import type {\r\n\tBaseCallApiConfig,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tGetCallApiResult,\r\n\tInterceptorUnion,\r\n\tRequestOptions,\r\n\tResultModeUnion,\r\n} from \"./types\";\r\nimport {\r\n\tHTTPError,\r\n\tdefaultRetryCodes,\r\n\tdefaultRetryMethods,\r\n\texecuteInterceptors,\r\n\tgenerateRequestKey,\r\n\tgetResponseData,\r\n\thandleInterceptorsMerge,\r\n\tisHTTPErrorInstance,\r\n\tmergeUrlWithParamsAndQuery,\r\n\tresolveErrorResult,\r\n\tresolveHeaders,\r\n\tresolveSuccessResult,\r\n\tsplitBaseConfig,\r\n\tsplitConfig,\r\n\twaitUntil,\r\n} from \"./utils/common\";\r\nimport { createCombinedSignal, createTimeoutSignal } from \"./utils/polyfills\";\r\nimport { isFunction, isObject } from \"./utils/typeof\";\r\n\r\nexport const createFetchClient = <\r\n\tTBaseData,\r\n\tTBaseErrorData = unknown,\r\n\tTBaseResultMode extends ResultModeUnion = ResultModeUnion,\r\n>(\r\n\tbaseConfig: BaseCallApiConfig<TBaseData, TBaseErrorData, TBaseResultMode> = {}\r\n) => {\r\n\tconst [baseFetchConfig, baseExtraOptions] = splitBaseConfig(baseConfig);\r\n\r\n\tconst {\r\n\t\tbody: baseBody,\r\n\t\theaders: baseHeaders,\r\n\t\tsignal: baseSignal,\r\n\t\t...restOfBaseFetchConfig\r\n\t} = baseFetchConfig;\r\n\r\n\tconst {\r\n\t\tonError: onBaseError,\r\n\t\tonRequest: onBaseRequest,\r\n\t\tonRequestError: onBaseRequestError,\r\n\t\tonResponse: onBaseResponse,\r\n\t\tonResponseError: onBaseResponseError,\r\n\t\tonSuccess: onBaseSuccess,\r\n\t\t...restOfBaseExtraOptions\r\n\t} = baseExtraOptions;\r\n\r\n\tconst requestInfoCache = new Map<\r\n\t\tstring | null,\r\n\t\t{ controller: AbortController; responsePromise: Promise<Response> }\r\n\t>();\r\n\r\n\tconst callApi = async <\r\n\t\tTData = TBaseData,\r\n\t\tTErrorData = TBaseErrorData,\r\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\r\n\t>(\r\n\t\turl: string,\r\n\t\tconfig: CallApiConfig<TData, TErrorData, TResultMode> = {}\r\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\r\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\r\n\r\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config);\r\n\r\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\r\n\r\n\t\t// prettier-ignore\r\n\t\tconst {\r\n\t\t\tonError,\r\n\t\t\tonRequest,\r\n\t\t\tonRequestError,\r\n\t\t\tonResponse,\r\n\t\t\tonResponseError,\r\n\t\t\tonSuccess,\r\n\t\t\t...restOfExtraOptions\r\n\t\t} = extraOptions;\r\n\r\n\t\t// == Default Extra Options\r\n\t\tconst defaultOptions = {\r\n\t\t\tbaseURL: \"\",\r\n\t\t\tbodySerializer: JSON.stringify,\r\n\t\t\tdedupeStrategy: \"cancel\",\r\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\r\n\t\t\tmergedInterceptorsExecutionMode: \"parallel\",\r\n\t\t\tmergeInterceptors: true,\r\n\t\t\tresponseType: \"json\",\r\n\t\t\tresultMode: \"all\",\r\n\t\t\tretries: 0,\r\n\t\t\tretryCodes: defaultRetryCodes,\r\n\t\t\tretryDelay: 0,\r\n\t\t\tretryMethods: defaultRetryMethods,\r\n\r\n\t\t\t...restOfBaseExtraOptions,\r\n\t\t\t...restOfExtraOptions,\r\n\t\t} satisfies Omit<CallApiExtraOptions, InterceptorUnion>;\r\n\r\n\t\tconst interceptors = {\r\n\t\t\tonError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseError,\r\n\t\t\t\tonError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonRequest: handleInterceptorsMerge(\r\n\t\t\t\tonBaseRequest,\r\n\t\t\t\tonRequest,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonRequestError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseRequestError,\r\n\t\t\t\tonRequestError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonResponse: handleInterceptorsMerge(\r\n\t\t\t\tonBaseResponse,\r\n\t\t\t\tonResponse,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonResponseError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseResponseError,\r\n\t\t\t\tonResponseError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonSuccess: handleInterceptorsMerge(\r\n\t\t\t\tonBaseSuccess,\r\n\t\t\t\tonSuccess,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t} satisfies Pick<CallApiExtraOptions, InterceptorUnion>;\r\n\r\n\t\tconst options = {\r\n\t\t\t...interceptors,\r\n\t\t\t...defaultOptions,\r\n\t\t};\r\n\r\n\t\tconst fullUrl = `${options.baseURL}${mergeUrlWithParamsAndQuery(url, options.params, options.query)}`;\r\n\r\n\t\t// == Default Request Init\r\n\t\tconst defaultRequestOptions = {\r\n\t\t\tmethod: \"GET\",\r\n\t\t\t// eslint-disable-next-line perfectionist/sort-objects\r\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\r\n\r\n\t\t\theaders: resolveHeaders({ auth: options.auth, baseHeaders, body, headers }),\r\n\r\n\t\t\t...restOfBaseFetchConfig,\r\n\t\t\t...restOfFetchConfig,\r\n\t\t} satisfies RequestInit;\r\n\r\n\t\t// prettier-ignore\r\n\t\tconst shouldHaveRequestKey = options.dedupeStrategy === \"cancel\" || options.dedupeStrategy === \"defer\";\r\n\r\n\t\tconst requestKey =\r\n\t\t\toptions.requestKey ??\r\n\t\t\t(shouldHaveRequestKey\r\n\t\t\t\t? generateRequestKey(fullUrl, { ...defaultRequestOptions, ...options })\r\n\t\t\t\t: null);\r\n\r\n\t\t// == This is required to leave the smallest window of time for the cache to be updated with the last request info, if all requests with the same key start at the same time\r\n\t\tif (requestKey != null) {\r\n\t\t\tawait waitUntil(0.1);\r\n\t\t}\r\n\r\n\t\t// == This ensures cache operations only occur when key is available\r\n\t\tconst requestInfoCacheOrNull = requestKey ? requestInfoCache : null;\r\n\r\n\t\tconst prevRequestInfo = requestInfoCacheOrNull?.get(requestKey);\r\n\r\n\t\tif (prevRequestInfo && options.dedupeStrategy === \"cancel\") {\r\n\t\t\tconst reason = new DOMException(\r\n\t\t\t\t`Request aborted as another request to the endpoint: ${url}, with the same request options was initiated.`,\r\n\t\t\t\t\"AbortError\"\r\n\t\t\t);\r\n\r\n\t\t\tprevRequestInfo.controller.abort(reason);\r\n\t\t}\r\n\r\n\t\tconst newFetchController = new AbortController();\r\n\r\n\t\tconst timeoutSignal = options.timeout != null ? createTimeoutSignal(options.timeout) : null;\r\n\r\n\t\tconst combinedSignal = createCombinedSignal(newFetchController.signal, timeoutSignal, signal);\r\n\r\n\t\tconst requestInit = {\r\n\t\t\tsignal: combinedSignal,\r\n\t\t\t...defaultRequestOptions,\r\n\t\t} satisfies RequestInit;\r\n\r\n\t\tconst request = {\r\n\t\t\turl: fullUrl,\r\n\t\t\t...requestInit,\r\n\t\t} satisfies RequestOptions;\r\n\r\n\t\ttry {\r\n\t\t\tawait executeInterceptors(options.onRequest?.({ options, request }));\r\n\r\n\t\t\t// == Incase options.auth was updated in the request interceptor\r\n\t\t\trequestInit.headers = resolveHeaders({\r\n\t\t\t\tauth: options.auth,\r\n\t\t\t\tbaseHeaders,\r\n\t\t\t\tbody: request.body,\r\n\t\t\t\theaders: request.headers,\r\n\t\t\t});\r\n\r\n\t\t\trequest.headers = requestInit.headers;\r\n\r\n\t\t\tconst shouldUsePromiseFromCache = prevRequestInfo && options.dedupeStrategy === \"defer\";\r\n\r\n\t\t\tconst responsePromise = shouldUsePromiseFromCache\r\n\t\t\t\t? prevRequestInfo.responsePromise\r\n\t\t\t\t: fetch(fullUrl, requestInit);\r\n\r\n\t\t\trequestInfoCacheOrNull?.set(requestKey, { controller: newFetchController, responsePromise });\r\n\r\n\t\t\tconst response = await responsePromise;\r\n\r\n\t\t\tconst shouldRetry =\r\n\t\t\t\t!response.ok &&\r\n\t\t\t\t!combinedSignal.aborted &&\r\n\t\t\t\toptions.retries > 0 &&\r\n\t\t\t\toptions.retryCodes.includes(response.status) &&\r\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\r\n\r\n\t\t\tif (shouldRetry) {\r\n\t\t\t\tawait waitUntil(options.retryDelay);\r\n\r\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\r\n\t\t\t}\r\n\r\n\t\t\t// == Also clone response when dedupeStrategy is set to \"defer\", to avoid error thrown from reading response.(whatever) more than once\r\n\t\t\t// == Also clone response when resultMode is set to \"onlyResponse\", to avoid error thrown from reading response.(whatever) more than once\r\n\t\t\tconst shouldCloneResponse =\r\n\t\t\t\toptions.dedupeStrategy === \"defer\" ||\r\n\t\t\t\toptions.resultMode === \"onlyResponse\" ||\r\n\t\t\t\toptions.shouldCloneResponse;\r\n\r\n\t\t\tif (!response.ok) {\r\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\r\n\t\t\t\t\tshouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\toptions.responseType,\r\n\t\t\t\t\toptions.responseParser\r\n\t\t\t\t);\r\n\r\n\t\t\t\t// == Pushing all error handling responsibilities to the catch block\r\n\t\t\t\tthrow new HTTPError({\r\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\r\n\t\t\t\t\terrorData,\r\n\t\t\t\t\tresponse,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tconst successData = await getResponseData<TData>(\r\n\t\t\t\tshouldCloneResponse ? response.clone() : response,\r\n\t\t\t\toptions.responseType,\r\n\t\t\t\toptions.responseParser\r\n\t\t\t);\r\n\r\n\t\t\tconst validSuccessData = options.responseValidator\r\n\t\t\t\t? options.responseValidator(successData)\r\n\t\t\t\t: successData;\r\n\r\n\t\t\tawait executeInterceptors(\r\n\t\t\t\toptions.onSuccess?.({\r\n\t\t\t\t\tdata: validSuccessData,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t}),\r\n\r\n\t\t\t\toptions.onResponse?.({\r\n\t\t\t\t\tdata: validSuccessData,\r\n\t\t\t\t\terrorData: null,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\treturn resolveSuccessResult<CallApiResult>({\r\n\t\t\t\tresponse,\r\n\t\t\t\tresultMode: options.resultMode,\r\n\t\t\t\tsuccessData: validSuccessData,\r\n\t\t\t});\r\n\r\n\t\t\t// == Exhaustive Error handling\r\n\t\t} catch (error) {\r\n\t\t\tconst { generalErrorResult, resolveCustomErrorInfo } = resolveErrorResult<CallApiResult>({\r\n\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\r\n\t\t\t\terror,\r\n\t\t\t\tresultMode: options.resultMode,\r\n\t\t\t});\r\n\r\n\t\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\r\n\t\t\t\t? options.throwOnError({\r\n\t\t\t\t\t\terror: (generalErrorResult as { error: never }).error,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t})\r\n\t\t\t\t: options.throwOnError;\r\n\r\n\t\t\tif (shouldThrowOnError) {\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\r\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\r\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\r\n\r\n\t\t\t\tconsole.error(`${error.name}:`, message);\r\n\r\n\t\t\t\treturn resolveCustomErrorInfo({ message });\r\n\t\t\t}\r\n\r\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\r\n\t\t\t\tconst { message, name } = error;\r\n\r\n\t\t\t\tconsole.error(`${name}:`, message);\r\n\r\n\t\t\t\treturn generalErrorResult;\r\n\t\t\t}\r\n\r\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\r\n\t\t\t\tconst { errorData, response } = error;\r\n\r\n\t\t\t\tawait executeInterceptors(\r\n\t\t\t\t\toptions.onResponseError?.({\r\n\t\t\t\t\t\terrorData,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t}),\r\n\r\n\t\t\t\t\toptions.onResponse?.({\r\n\t\t\t\t\t\tdata: null,\r\n\t\t\t\t\t\terrorData,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t}),\r\n\r\n\t\t\t\t\t// == Also call the onError interceptor\r\n\t\t\t\t\toptions.onError?.({\r\n\t\t\t\t\t\terror,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t})\r\n\t\t\t\t);\r\n\r\n\t\t\t\treturn generalErrorResult;\r\n\t\t\t}\r\n\r\n\t\t\tawait executeInterceptors(\r\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\r\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request }),\r\n\r\n\t\t\t\t// == Also call the onError interceptor\r\n\t\t\t\toptions.onError?.({\r\n\t\t\t\t\terror: (generalErrorResult as { error: never }).error,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: null,\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\treturn generalErrorResult;\r\n\r\n\t\t\t// == Removing the now unneeded AbortController from store\r\n\t\t} finally {\r\n\t\t\trequestInfoCacheOrNull?.delete(requestKey);\r\n\t\t}\r\n\t};\r\n\r\n\tcallApi.create = createFetchClient;\r\n\r\n\treturn callApi;\r\n};\r\n\r\nexport const callApi = createFetchClient();\r\n"],"mappings":"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","names":["callApi"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/utils/typeof.ts","../../src/utils/common.ts","../../src/utils/polyfills.ts","../../src/createFetchClient.ts"],"sourcesContent":["export { callApi, createFetchClient } from \"./createFetchClient\";\r\n\r\nexport type {\r\n\tRequestOptions,\r\n\tCallApiExtraOptions,\r\n\tCallApiConfig,\r\n\tSuccessResponseContext,\r\n\tResponseErrorContext,\r\n\tErrorContext,\r\n} from \"./types\";\r\n","import type { AnyFunction } from \"./type-helpers\";\r\n\r\nexport const isArray = <TArrayItem>(value: unknown): value is TArrayItem[] => Array.isArray(value);\r\n\r\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\r\n\treturn typeof value === \"object\" && value !== null && !(value instanceof FormData) && !isArray(value);\r\n};\r\n\r\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\r\n\ttypeof value === \"function\";\r\n\r\nexport const isQueryString = (value: unknown): value is string => isString(value) && value.includes(\"=\");\r\n\r\nexport const isString = (value: unknown) => typeof value === \"string\";\r\n","import type {\r\n\tApiErrorVariant,\r\n\tBaseCallApiConfig,\r\n\tBaseCallApiExtraOptions,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tPossibleErrorNames,\r\n} from \"../types\";\r\nimport type { AnyFunction, Awaitable } from \"./type-helpers\";\r\nimport { isArray, isObject, isQueryString, isString } from \"./typeof\";\r\n\r\n// prettier-ignore\r\nexport const generateRequestKey = (url: string, config: Record<string, unknown>) => `${url} ${ampersand} ${JSON.stringify(config)}`;\r\n\r\ntype ToQueryStringFn = {\r\n\t(params: CallApiConfig[\"query\"]): string | null;\r\n\t(params: Required<CallApiConfig>[\"query\"]): string;\r\n};\r\n\r\nexport const toQueryString: ToQueryStringFn = (params) => {\r\n\tif (!params) {\r\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\r\n\r\n\t\treturn null as never;\r\n\t}\r\n\r\n\treturn new URLSearchParams(params as Record<string, string>).toString();\r\n};\r\n\r\nconst slash = \"/\";\r\nconst column = \":\";\r\nconst mergeUrlWithParams = (url: string, params: CallApiExtraOptions[\"params\"]) => {\r\n\tif (!params) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tlet newUrl = url;\r\n\r\n\tif (isArray(params)) {\r\n\t\tconst matchedParamArray = newUrl\r\n\t\t\t.split(slash)\r\n\t\t\t.filter((matchedParam) => matchedParam.startsWith(column));\r\n\r\n\t\tfor (const [index, matchedParam] of matchedParamArray.entries()) {\r\n\t\t\tconst param = params[index] as string;\r\n\t\t\tnewUrl = newUrl.replace(matchedParam, param);\r\n\t\t}\r\n\r\n\t\treturn newUrl;\r\n\t}\r\n\r\n\tfor (const [key, value] of Object.entries(params)) {\r\n\t\tnewUrl = newUrl.replace(`:${key}`, String(value));\r\n\t}\r\n\r\n\treturn newUrl;\r\n};\r\n\r\nconst questionMark = \"?\";\r\nconst ampersand = \"&\";\r\n\r\nconst mergeUrlWithQuery = (url: string, query: CallApiConfig[\"query\"]): string => {\r\n\tif (!query) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tconst queryString = toQueryString(query);\r\n\r\n\tif (queryString?.length === 0) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tif (url.endsWith(questionMark)) {\r\n\t\treturn `${url}${queryString}`;\r\n\t}\r\n\r\n\tif (url.includes(questionMark)) {\r\n\t\treturn `${url}${ampersand}${queryString}`;\r\n\t}\r\n\r\n\treturn `${url}${questionMark}${queryString}`;\r\n};\r\n\r\nexport const mergeUrlWithParamsAndQuery = (\r\n\turl: string,\r\n\tparams: CallApiExtraOptions[\"params\"],\r\n\tquery: CallApiExtraOptions[\"query\"]\r\n) => {\r\n\tconst urlWithMergedParams = mergeUrlWithParams(url, params);\r\n\r\n\treturn mergeUrlWithQuery(urlWithMergedParams, query);\r\n};\r\n\r\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\r\n\tif (!headers || isObject(headers)) {\r\n\t\treturn headers;\r\n\t}\r\n\r\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\r\n};\r\n\r\nexport const resolveHeaders = (options: {\r\n\tauth: CallApiConfig[\"auth\"];\r\n\tbaseHeaders: CallApiConfig[\"headers\"];\r\n\tbody: CallApiConfig[\"body\"];\r\n\theaders: CallApiConfig[\"headers\"];\r\n}) => {\r\n\tconst { auth, baseHeaders, body, headers } = options;\r\n\r\n\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing\r\n\tconst shouldResolveHeaders = baseHeaders || headers || body || auth;\r\n\r\n\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\r\n\t// - headers are provided\r\n\t// - The body is an object\r\n\t// - The auth option is provided\r\n\tif (!shouldResolveHeaders) return;\r\n\r\n\treturn {\r\n\t\t...(isObject(body) && {\r\n\t\t\tAccept: \"application/json\",\r\n\t\t\t\"Content-Type\": \"application/json\",\r\n\t\t}),\r\n\t\t...(isQueryString(body) && {\r\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\r\n\t\t}),\r\n\t\t...((isString(auth) || auth === null) && {\r\n\t\t\tAuthorization: `Bearer ${auth}`,\r\n\t\t}),\r\n\t\t...(isObject(auth) && {\r\n\t\t\tAuthorization: \"bearer\" in auth ? `Bearer ${auth.bearer}` : `Token ${auth.token}`,\r\n\t\t}),\r\n\t\t...objectifyHeaders(baseHeaders),\r\n\t\t...objectifyHeaders(headers),\r\n\t};\r\n};\r\n\r\nconst retryCodesLookup = {\r\n\t408: \"Request Timeout\",\r\n\t409: \"Conflict\",\r\n\t425: \"Too Early\",\r\n\t429: \"Too Many Requests\",\r\n\t500: \"Internal Server Error\",\r\n\t502: \"Bad Gateway\",\r\n\t503: \"Service Unavailable\",\r\n\t504: \"Gateway Timeout\",\r\n};\r\n\r\nexport const defaultRetryCodes: Required<BaseCallApiConfig>[\"retryCodes\"] =\r\n\tObject.keys(retryCodesLookup).map(Number);\r\n\r\nexport const defaultRetryMethods: Required<BaseCallApiConfig>[\"retryMethods\"] = [\"GET\"];\r\n\r\nexport const fetchSpecificKeys = [\r\n\t\"body\",\r\n\t\"integrity\",\r\n\t\"method\",\r\n\t\"headers\",\r\n\t\"signal\",\r\n\t\"cache\",\r\n\t\"redirect\",\r\n\t\"window\",\r\n\t\"credentials\",\r\n\t\"keepalive\",\r\n\t\"referrer\",\r\n\t\"priority\",\r\n\t\"mode\",\r\n\t\"referrerPolicy\",\r\n] satisfies Array<keyof RequestInit>;\r\n\r\nexport const omitKeys = <\r\n\tTObject extends Record<string, unknown>,\r\n\tconst TOmitArray extends Array<keyof TObject>,\r\n>(\r\n\tinitialObject: TObject,\r\n\tkeysToOmit: TOmitArray\r\n) => {\r\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\r\n\t\t([key]) => !keysToOmit.includes(key)\r\n\t);\r\n\r\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\r\n\r\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\r\n};\r\n\r\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\r\n\tinitialObject: TObject,\r\n\tkeysToPick: TPickArray\r\n) => {\r\n\tconst keysToPickSet = new Set(keysToPick);\r\n\r\n\tconst arrayFromInitObject = Object.entries(initialObject);\r\n\r\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\r\n\r\n\tconst updatedObject = Object.fromEntries(filteredArray);\r\n\r\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\r\n};\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitBaseConfig = (baseConfig: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(baseConfig, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(baseConfig, [...fetchSpecificKeys, \"requestKey\"] satisfies Array<\r\n\t\t\tkeyof CallApiConfig\r\n\t\t>) as BaseCallApiExtraOptions,\r\n\t] as const;\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitConfig = (config: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(config, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(config, fetchSpecificKeys) as CallApiExtraOptions,\r\n\t] as const;\r\n\r\nexport const handleInterceptorsMerge = <\r\n\tTBaseInterceptor extends AnyFunction<Awaitable<void>> | Array<AnyFunction<Awaitable<void>>>,\r\n\tTInterceptor extends AnyFunction<Awaitable<void>>,\r\n>(\r\n\tbaseInterceptor: TBaseInterceptor | undefined,\r\n\tinterceptor: TInterceptor | undefined,\r\n\tmergeInterceptors: CallApiExtraOptions[\"mergeInterceptors\"],\r\n\tmergedInterceptorsExecutionMode: CallApiExtraOptions[\"mergedInterceptorsExecutionMode\"]\r\n) => {\r\n\tif (isArray(baseInterceptor) && mergeInterceptors) {\r\n\t\tconst mergedInterceptor = async (ctx: Record<string, unknown>) => {\r\n\t\t\tconst interceptorArray = [...baseInterceptor, ...(interceptor ? [interceptor] : [])] as Array<\r\n\t\t\t\tAnyFunction<Awaitable<void>>\r\n\t\t\t>;\r\n\r\n\t\t\tconst uniqueInterceptorArray = [...new Set(interceptorArray)];\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"sequential\") {\r\n\t\t\t\tfor (const uniqueInterceptor of uniqueInterceptorArray) {\r\n\t\t\t\t\t// eslint-disable-next-line no-await-in-loop\r\n\t\t\t\t\tawait uniqueInterceptor(ctx);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"parallel\") {\r\n\t\t\t\tawait Promise.all(uniqueInterceptorArray.map((uniqueInterceptor) => uniqueInterceptor(ctx)));\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\treturn mergedInterceptor;\r\n\t}\r\n\r\n\treturn interceptor ?? (baseInterceptor as typeof interceptor);\r\n};\r\n\r\nexport const handleResponseType = <TResponse>(\r\n\tresponse: Response,\r\n\tparser?: Required<CallApiExtraOptions>[\"responseParser\"]\r\n) => ({\r\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\r\n\tblob: () => response.blob() as Promise<TResponse>,\r\n\tformData: () => response.formData() as Promise<TResponse>,\r\n\tjson: async () => {\r\n\t\tif (parser) {\r\n\t\t\treturn parser(await response.text());\r\n\t\t}\r\n\r\n\t\treturn response.json() as Promise<TResponse>;\r\n\t},\r\n\ttext: () => response.text() as Promise<TResponse>,\r\n});\r\n\r\nexport const getResponseData = <TResponse>(\r\n\tresponse: Response,\r\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\r\n\tparser: CallApiExtraOptions[\"responseParser\"]\r\n) => {\r\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\r\n\r\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\r\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\r\n\t}\r\n\r\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\r\n};\r\n\r\ntype SuccessInfo = {\r\n\tresponse: Response;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n\tsuccessData: unknown;\r\n};\r\n\r\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\r\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\r\nexport const resolveSuccessResult = <CallApiResult>(info: SuccessInfo): CallApiResult => {\r\n\tconst { response, resultMode, successData } = info;\r\n\r\n\tconst apiDetails = {\r\n\t\tdata: successData,\r\n\t\terror: null,\r\n\t\tresponse,\r\n\t};\r\n\r\n\tif (!resultMode) {\r\n\t\treturn apiDetails as CallApiResult;\r\n\t}\r\n\r\n\treturn {\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode] as CallApiResult;\r\n};\r\n\r\ntype ErrorInfo = {\r\n\tdefaultErrorMessage: Required<CallApiExtraOptions>[\"defaultErrorMessage\"];\r\n\terror?: unknown;\r\n\tmessage?: string;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n};\r\n\r\nexport const resolveErrorResult = <TCallApiResult>(info: ErrorInfo) => {\r\n\tconst { defaultErrorMessage, error, message: customErrorMessage, resultMode } = info;\r\n\r\n\tlet apiDetails!: ApiErrorVariant<unknown>;\r\n\r\n\tif (isHTTPErrorInstance(error)) {\r\n\t\tconst { errorData, message = defaultErrorMessage, name, response } = error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: { errorData, message, name },\r\n\t\t\tresponse,\r\n\t\t};\r\n\t}\r\n\r\n\tif (error) {\r\n\t\tconst { message, name } = error as Error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: {\r\n\t\t\t\terrorData: error as Error,\r\n\t\t\t\tmessage: customErrorMessage ?? message,\r\n\t\t\t\tname: name as PossibleErrorNames,\r\n\t\t\t},\r\n\t\t\tresponse: null,\r\n\t\t};\r\n\t}\r\n\r\n\tconst generalErrorResult = ({\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode ?? \"all\"] ?? apiDetails) as TCallApiResult;\r\n\r\n\t// prettier-ignore\r\n\tconst resolveCustomErrorInfo = ({ message }: Pick<ErrorInfo, \"message\">) => {\r\n\t\tconst errorResult = resolveErrorResult<TCallApiResult>({ ...info, message });\r\n\r\n\t\treturn errorResult.generalErrorResult;\r\n\t};\r\n\r\n\treturn { apiDetails, generalErrorResult, resolveCustomErrorInfo };\r\n};\r\n\r\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\r\n\treturn isObject(error) && error.name === \"HTTPError\";\r\n};\r\n\r\ntype ErrorDetails<TErrorResponse> = {\r\n\tdefaultErrorMessage: string;\r\n\terrorData: TErrorResponse;\r\n\tresponse: Response;\r\n};\r\n\r\ntype ErrorOptions = {\r\n\tcause?: unknown;\r\n};\r\n\r\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\r\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\r\n\tisHTTPError = true;\r\n\r\n\toverride name = \"HTTPError\" as const;\r\n\r\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\r\n\r\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\r\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\r\n\r\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\r\n\r\n\t\tthis.errorData = errorData;\r\n\t\tthis.response = response;\r\n\r\n\t\tError.captureStackTrace(this, this.constructor);\r\n\t}\r\n}\r\n\r\nexport const isHTTPErrorInstance = <TErrorResponse>(\r\n\terror: unknown\r\n): error is HTTPError<TErrorResponse> => {\r\n\treturn (\r\n\t\t// prettier-ignore\r\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\r\n\t);\r\n};\r\n\r\nconst PromiseWithResolvers = () => {\r\n\tlet reject!: (reason?: unknown) => void;\r\n\tlet resolve!: (value: unknown) => void;\r\n\r\n\tconst promise = new Promise((res, rej) => {\r\n\t\tresolve = res;\r\n\t\treject = rej;\r\n\t});\r\n\r\n\treturn { promise, reject, resolve };\r\n};\r\n\r\nexport const waitUntil = (delay: number) => {\r\n\tif (delay === 0) return;\r\n\r\n\tconst { promise, resolve } = PromiseWithResolvers();\r\n\r\n\tsetTimeout(resolve, delay);\r\n\r\n\treturn promise;\r\n};\r\n\r\nexport const executeInterceptors = <TInterceptor extends Awaitable<void>>(\r\n\t...interceptors: TInterceptor[]\r\n) => Promise.all(interceptors);\r\n","// prettier-ignore\nexport const createCombinedSignal = (...signals: Array<AbortSignal | null | undefined>) => AbortSignal.any(signals.filter(Boolean));\n\nexport const createTimeoutSignal = (milliseconds: number) => AbortSignal.timeout(milliseconds);\n","import type {\r\n\tBaseCallApiConfig,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tGetCallApiResult,\r\n\tInterceptorUnion,\r\n\tRequestOptions,\r\n\tResultModeUnion,\r\n} from \"./types\";\r\nimport {\r\n\tHTTPError,\r\n\tdefaultRetryCodes,\r\n\tdefaultRetryMethods,\r\n\texecuteInterceptors,\r\n\tgenerateRequestKey,\r\n\tgetResponseData,\r\n\thandleInterceptorsMerge,\r\n\tisHTTPErrorInstance,\r\n\tmergeUrlWithParamsAndQuery,\r\n\tresolveErrorResult,\r\n\tresolveHeaders,\r\n\tresolveSuccessResult,\r\n\tsplitBaseConfig,\r\n\tsplitConfig,\r\n\twaitUntil,\r\n} from \"./utils/common\";\r\nimport { createCombinedSignal, createTimeoutSignal } from \"./utils/polyfills\";\r\nimport { isFunction, isObject } from \"./utils/typeof\";\r\n\r\nexport const createFetchClient = <\r\n\tTBaseData,\r\n\tTBaseErrorData = unknown,\r\n\tTBaseResultMode extends ResultModeUnion = ResultModeUnion,\r\n>(\r\n\tbaseConfig: BaseCallApiConfig<TBaseData, TBaseErrorData, TBaseResultMode> = {}\r\n) => {\r\n\tconst [baseFetchConfig, baseExtraOptions] = splitBaseConfig(baseConfig);\r\n\r\n\tconst {\r\n\t\tbody: baseBody,\r\n\t\theaders: baseHeaders,\r\n\t\tsignal: baseSignal,\r\n\t\t...restOfBaseFetchConfig\r\n\t} = baseFetchConfig;\r\n\r\n\tconst {\r\n\t\tonError: onBaseError,\r\n\t\tonRequest: onBaseRequest,\r\n\t\tonRequestError: onBaseRequestError,\r\n\t\tonResponse: onBaseResponse,\r\n\t\tonResponseError: onBaseResponseError,\r\n\t\tonSuccess: onBaseSuccess,\r\n\t\t...restOfBaseExtraOptions\r\n\t} = baseExtraOptions;\r\n\r\n\tconst requestInfoCache = new Map<\r\n\t\tstring | null,\r\n\t\t{ controller: AbortController; responsePromise: Promise<Response> }\r\n\t>();\r\n\r\n\tconst callApi = async <\r\n\t\tTData = TBaseData,\r\n\t\tTErrorData = TBaseErrorData,\r\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\r\n\t>(\r\n\t\turl: string,\r\n\t\tconfig: CallApiConfig<TData, TErrorData, TResultMode> = {}\r\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\r\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\r\n\r\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config);\r\n\r\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\r\n\r\n\t\t// prettier-ignore\r\n\t\tconst {\r\n\t\t\tonError,\r\n\t\t\tonRequest,\r\n\t\t\tonRequestError,\r\n\t\t\tonResponse,\r\n\t\t\tonResponseError,\r\n\t\t\tonSuccess,\r\n\t\t\t...restOfExtraOptions\r\n\t\t} = extraOptions;\r\n\r\n\t\t// == Default Extra Options\r\n\t\tconst defaultOptions = {\r\n\t\t\tbaseURL: \"\",\r\n\t\t\tbodySerializer: JSON.stringify,\r\n\t\t\tdedupeStrategy: \"cancel\",\r\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\r\n\t\t\tmergedInterceptorsExecutionMode: \"parallel\",\r\n\t\t\tmergeInterceptors: true,\r\n\t\t\tresponseType: \"json\",\r\n\t\t\tresultMode: \"all\",\r\n\t\t\tretries: 0,\r\n\t\t\tretryCodes: defaultRetryCodes,\r\n\t\t\tretryDelay: 0,\r\n\t\t\tretryMethods: defaultRetryMethods,\r\n\r\n\t\t\t...restOfBaseExtraOptions,\r\n\t\t\t...restOfExtraOptions,\r\n\t\t} satisfies Omit<CallApiExtraOptions, InterceptorUnion>;\r\n\r\n\t\tconst interceptors = {\r\n\t\t\tonError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseError,\r\n\t\t\t\tonError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonRequest: handleInterceptorsMerge(\r\n\t\t\t\tonBaseRequest,\r\n\t\t\t\tonRequest,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonRequestError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseRequestError,\r\n\t\t\t\tonRequestError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonResponse: handleInterceptorsMerge(\r\n\t\t\t\tonBaseResponse,\r\n\t\t\t\tonResponse,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonResponseError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseResponseError,\r\n\t\t\t\tonResponseError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonSuccess: handleInterceptorsMerge(\r\n\t\t\t\tonBaseSuccess,\r\n\t\t\t\tonSuccess,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t} satisfies Pick<CallApiExtraOptions, InterceptorUnion>;\r\n\r\n\t\tconst options = {\r\n\t\t\t...interceptors,\r\n\t\t\t...defaultOptions,\r\n\t\t};\r\n\r\n\t\tconst fullUrl = `${options.baseURL}${mergeUrlWithParamsAndQuery(url, options.params, options.query)}`;\r\n\r\n\t\t// == Default Request Init\r\n\t\tconst defaultRequestOptions = {\r\n\t\t\tmethod: \"GET\",\r\n\t\t\t// eslint-disable-next-line perfectionist/sort-objects\r\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\r\n\r\n\t\t\theaders: resolveHeaders({ auth: options.auth, baseHeaders, body, headers }),\r\n\r\n\t\t\t...restOfBaseFetchConfig,\r\n\t\t\t...restOfFetchConfig,\r\n\t\t} satisfies RequestInit;\r\n\r\n\t\t// prettier-ignore\r\n\t\tconst shouldHaveRequestKey = options.dedupeStrategy === \"cancel\" || options.dedupeStrategy === \"defer\";\r\n\r\n\t\tconst requestKey =\r\n\t\t\toptions.requestKey ??\r\n\t\t\t(shouldHaveRequestKey\r\n\t\t\t\t? generateRequestKey(fullUrl, { ...defaultRequestOptions, ...options })\r\n\t\t\t\t: null);\r\n\r\n\t\t// == This is required to leave the smallest window of time for the cache to be updated with the last request info, if all requests with the same key start at the same time\r\n\t\tif (requestKey != null) {\r\n\t\t\tawait waitUntil(0.1);\r\n\t\t}\r\n\r\n\t\t// == This ensures cache operations only occur when key is available\r\n\t\tconst requestInfoCacheOrNull = requestKey ? requestInfoCache : null;\r\n\r\n\t\tconst prevRequestInfo = requestInfoCacheOrNull?.get(requestKey);\r\n\r\n\t\tif (prevRequestInfo && options.dedupeStrategy === \"cancel\") {\r\n\t\t\tconst reason = new DOMException(\r\n\t\t\t\t`Request aborted as another request to the endpoint: ${url}, with the same request options was initiated.`,\r\n\t\t\t\t\"AbortError\"\r\n\t\t\t);\r\n\r\n\t\t\tprevRequestInfo.controller.abort(reason);\r\n\t\t}\r\n\r\n\t\tconst newFetchController = new AbortController();\r\n\r\n\t\tconst timeoutSignal = options.timeout != null ? createTimeoutSignal(options.timeout) : null;\r\n\r\n\t\tconst combinedSignal = createCombinedSignal(newFetchController.signal, timeoutSignal, signal);\r\n\r\n\t\tconst requestInit = {\r\n\t\t\tsignal: combinedSignal,\r\n\t\t\t...defaultRequestOptions,\r\n\t\t} satisfies RequestInit;\r\n\r\n\t\tconst request = {\r\n\t\t\turl: fullUrl,\r\n\t\t\t...requestInit,\r\n\t\t} satisfies RequestOptions;\r\n\r\n\t\ttry {\r\n\t\t\tawait executeInterceptors(options.onRequest?.({ options, request }));\r\n\r\n\t\t\t// == Incase options.auth was updated in the request interceptor\r\n\t\t\trequestInit.headers = resolveHeaders({\r\n\t\t\t\tauth: options.auth,\r\n\t\t\t\tbaseHeaders,\r\n\t\t\t\tbody: request.body,\r\n\t\t\t\theaders: request.headers,\r\n\t\t\t});\r\n\r\n\t\t\trequest.headers = requestInit.headers;\r\n\r\n\t\t\tconst shouldUsePromiseFromCache = prevRequestInfo && options.dedupeStrategy === \"defer\";\r\n\r\n\t\t\tconst responsePromise = shouldUsePromiseFromCache\r\n\t\t\t\t? prevRequestInfo.responsePromise\r\n\t\t\t\t: fetch(fullUrl, requestInit);\r\n\r\n\t\t\trequestInfoCacheOrNull?.set(requestKey, { controller: newFetchController, responsePromise });\r\n\r\n\t\t\tconst response = await responsePromise;\r\n\r\n\t\t\tconst shouldRetry =\r\n\t\t\t\t!response.ok &&\r\n\t\t\t\t!combinedSignal.aborted &&\r\n\t\t\t\toptions.retries > 0 &&\r\n\t\t\t\toptions.retryCodes.includes(response.status) &&\r\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\r\n\r\n\t\t\tif (shouldRetry) {\r\n\t\t\t\tawait waitUntil(options.retryDelay);\r\n\r\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\r\n\t\t\t}\r\n\r\n\t\t\t// == Also clone response when dedupeStrategy is set to \"defer\", to avoid error thrown from reading response.(whatever) more than once\r\n\t\t\t// == Also clone response when resultMode is set to \"onlyResponse\", to avoid error thrown from reading response.(whatever) more than once\r\n\t\t\tconst shouldCloneResponse =\r\n\t\t\t\toptions.dedupeStrategy === \"defer\" ||\r\n\t\t\t\toptions.resultMode === \"onlyResponse\" ||\r\n\t\t\t\toptions.shouldCloneResponse;\r\n\r\n\t\t\tif (!response.ok) {\r\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\r\n\t\t\t\t\tshouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\toptions.responseType,\r\n\t\t\t\t\toptions.responseParser\r\n\t\t\t\t);\r\n\r\n\t\t\t\t// == Pushing all error handling responsibilities to the catch block\r\n\t\t\t\tthrow new HTTPError({\r\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\r\n\t\t\t\t\terrorData,\r\n\t\t\t\t\tresponse,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tconst successData = await getResponseData<TData>(\r\n\t\t\t\tshouldCloneResponse ? response.clone() : response,\r\n\t\t\t\toptions.responseType,\r\n\t\t\t\toptions.responseParser\r\n\t\t\t);\r\n\r\n\t\t\tconst validSuccessData = options.responseValidator\r\n\t\t\t\t? options.responseValidator(successData)\r\n\t\t\t\t: successData;\r\n\r\n\t\t\tawait executeInterceptors(\r\n\t\t\t\toptions.onSuccess?.({\r\n\t\t\t\t\tdata: validSuccessData,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t}),\r\n\r\n\t\t\t\toptions.onResponse?.({\r\n\t\t\t\t\tdata: validSuccessData,\r\n\t\t\t\t\terrorData: null,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\treturn resolveSuccessResult<CallApiResult>({\r\n\t\t\t\tresponse,\r\n\t\t\t\tresultMode: options.resultMode,\r\n\t\t\t\tsuccessData: validSuccessData,\r\n\t\t\t});\r\n\r\n\t\t\t// == Exhaustive Error handling\r\n\t\t} catch (error) {\r\n\t\t\tconst { apiDetails, generalErrorResult, resolveCustomErrorInfo } =\r\n\t\t\t\tresolveErrorResult<CallApiResult>({\r\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\r\n\t\t\t\t\terror,\r\n\t\t\t\t\tresultMode: options.resultMode,\r\n\t\t\t\t});\r\n\r\n\t\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\r\n\t\t\t\t? options.throwOnError({\r\n\t\t\t\t\t\terror: apiDetails.error,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t})\r\n\t\t\t\t: options.throwOnError;\r\n\r\n\t\t\t// eslint-disable-next-line unicorn/consistent-function-scoping\r\n\t\t\tconst handleThrowOnError = () => {\r\n\t\t\t\tif (!shouldThrowOnError) return;\r\n\r\n\t\t\t\tthrow apiDetails.error as Error;\r\n\t\t\t};\r\n\r\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\r\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\r\n\r\n\t\t\t\tconsole.error(`${error.name}:`, message);\r\n\r\n\t\t\t\thandleThrowOnError();\r\n\r\n\t\t\t\treturn resolveCustomErrorInfo({ message });\r\n\t\t\t}\r\n\r\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\r\n\t\t\t\tconst { message, name } = error;\r\n\r\n\t\t\t\tconsole.error(`${name}:`, message);\r\n\r\n\t\t\t\thandleThrowOnError();\r\n\r\n\t\t\t\treturn generalErrorResult;\r\n\t\t\t}\r\n\r\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\r\n\t\t\t\tconst { errorData, response } = error;\r\n\r\n\t\t\t\tawait executeInterceptors(\r\n\t\t\t\t\toptions.onResponseError?.({\r\n\t\t\t\t\t\terrorData,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t}),\r\n\r\n\t\t\t\t\toptions.onResponse?.({\r\n\t\t\t\t\t\tdata: null,\r\n\t\t\t\t\t\terrorData,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t}),\r\n\r\n\t\t\t\t\t// == Also call the onError interceptor\r\n\t\t\t\t\toptions.onError?.({\r\n\t\t\t\t\t\terror,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t})\r\n\t\t\t\t);\r\n\r\n\t\t\t\thandleThrowOnError();\r\n\r\n\t\t\t\treturn generalErrorResult;\r\n\t\t\t}\r\n\r\n\t\t\tawait executeInterceptors(\r\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\r\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request }),\r\n\r\n\t\t\t\t// == Also call the onError interceptor\r\n\t\t\t\toptions.onError?.({\r\n\t\t\t\t\terror: (generalErrorResult as { error: never }).error,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: null,\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\thandleThrowOnError();\r\n\r\n\t\t\treturn generalErrorResult;\r\n\r\n\t\t\t// == Removing the now unneeded AbortController from store\r\n\t\t} finally {\r\n\t\t\trequestInfoCacheOrNull?.delete(requestKey);\r\n\t\t}\r\n\t};\r\n\r\n\tcallApi.create = createFetchClient;\r\n\r\n\treturn callApi;\r\n};\r\n\r\nexport const callApi = createFetchClient();\r\n"],"mappings":"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","names":["callApi"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/index.ts","../../../src/utils/typeof.ts","../../../src/utils/common.ts"],"sourcesContent":["export { HTTPError, isHTTPError, isHTTPErrorInstance, toQueryString } from \"./common\";\r\n","import type { AnyFunction } from \"./type-helpers\";\r\n\r\nexport const isArray = <TArrayItem>(value: unknown): value is TArrayItem[] => Array.isArray(value);\r\n\r\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\r\n\treturn typeof value === \"object\" && value !== null && !(value instanceof FormData) && !isArray(value);\r\n};\r\n\r\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\r\n\ttypeof value === \"function\";\r\n\r\nexport const isQueryString = (value: unknown): value is string => isString(value) && value.includes(\"=\");\r\n\r\nexport const isString = (value: unknown) => typeof value === \"string\";\r\n","import type {\r\n\tApiErrorVariant,\r\n\tBaseCallApiConfig,\r\n\tBaseCallApiExtraOptions,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tPossibleErrorNames,\r\n\tResultModeMap,\r\n} from \"../types\";\r\nimport type { AnyFunction, Awaitable } from \"./type-helpers\";\r\nimport { isArray, isObject, isQueryString, isString } from \"./typeof\";\r\n\r\n// prettier-ignore\r\nexport const generateRequestKey = (url: string, config: Record<string, unknown>) => `${url} ${ampersand} ${JSON.stringify(config)}`;\r\n\r\ntype ToQueryStringFn = {\r\n\t(params: CallApiConfig[\"query\"]): string | null;\r\n\t(params: Required<CallApiConfig>[\"query\"]): string;\r\n};\r\n\r\nexport const toQueryString: ToQueryStringFn = (params) => {\r\n\tif (!params) {\r\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\r\n\r\n\t\treturn null as never;\r\n\t}\r\n\r\n\treturn new URLSearchParams(params as Record<string, string>).toString();\r\n};\r\n\r\nconst slash = \"/\";\r\nconst column = \":\";\r\nconst mergeUrlWithParams = (url: string, params: CallApiExtraOptions[\"params\"]) => {\r\n\tif (!params) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tlet newUrl = url;\r\n\r\n\tif (isArray(params)) {\r\n\t\tconst matchedParamArray = newUrl\r\n\t\t\t.split(slash)\r\n\t\t\t.filter((matchedParam) => matchedParam.startsWith(column));\r\n\r\n\t\tfor (const [index, matchedParam] of matchedParamArray.entries()) {\r\n\t\t\tconst param = params[index] as string;\r\n\t\t\tnewUrl = newUrl.replace(matchedParam, param);\r\n\t\t}\r\n\r\n\t\treturn newUrl;\r\n\t}\r\n\r\n\tfor (const [key, value] of Object.entries(params)) {\r\n\t\tnewUrl = newUrl.replace(`:${key}`, String(value));\r\n\t}\r\n\r\n\treturn newUrl;\r\n};\r\n\r\nconst questionMark = \"?\";\r\nconst ampersand = \"&\";\r\n\r\nconst mergeUrlWithQuery = (url: string, query: CallApiConfig[\"query\"]): string => {\r\n\tif (!query) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tconst queryString = toQueryString(query);\r\n\r\n\tif (queryString?.length === 0) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tif (url.endsWith(questionMark)) {\r\n\t\treturn `${url}${queryString}`;\r\n\t}\r\n\r\n\tif (url.includes(questionMark)) {\r\n\t\treturn `${url}${ampersand}${queryString}`;\r\n\t}\r\n\r\n\treturn `${url}${questionMark}${queryString}`;\r\n};\r\n\r\nexport const mergeUrlWithParamsAndQuery = (\r\n\turl: string,\r\n\tparams: CallApiExtraOptions[\"params\"],\r\n\tquery: CallApiExtraOptions[\"query\"]\r\n) => {\r\n\tconst urlWithMergedParams = mergeUrlWithParams(url, params);\r\n\r\n\treturn mergeUrlWithQuery(urlWithMergedParams, query);\r\n};\r\n\r\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\r\n\tif (!headers || isObject(headers)) {\r\n\t\treturn headers;\r\n\t}\r\n\r\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\r\n};\r\n\r\nexport const resolveHeaders = (options: {\r\n\tauth: CallApiConfig[\"auth\"];\r\n\tbaseHeaders: CallApiConfig[\"headers\"];\r\n\tbody: CallApiConfig[\"body\"];\r\n\theaders: CallApiConfig[\"headers\"];\r\n}) => {\r\n\tconst { auth, baseHeaders, body, headers } = options;\r\n\r\n\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing\r\n\tconst shouldResolveHeaders = baseHeaders || headers || body || auth;\r\n\r\n\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\r\n\t// - headers are provided\r\n\t// - The body is an object\r\n\t// - The auth option is provided\r\n\tif (!shouldResolveHeaders) return;\r\n\r\n\treturn {\r\n\t\t...(isObject(body) && {\r\n\t\t\tAccept: \"application/json\",\r\n\t\t\t\"Content-Type\": \"application/json\",\r\n\t\t}),\r\n\t\t...(isQueryString(body) && {\r\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\r\n\t\t}),\r\n\t\t...((isString(auth) || auth === null) && {\r\n\t\t\tAuthorization: `Bearer ${auth}`,\r\n\t\t}),\r\n\t\t...(isObject(auth) && {\r\n\t\t\tAuthorization: \"bearer\" in auth ? `Bearer ${auth.bearer}` : `Token ${auth.token}`,\r\n\t\t}),\r\n\t\t...objectifyHeaders(baseHeaders),\r\n\t\t...objectifyHeaders(headers),\r\n\t};\r\n};\r\n\r\nconst retryCodesLookup = {\r\n\t408: \"Request Timeout\",\r\n\t409: \"Conflict\",\r\n\t425: \"Too Early\",\r\n\t429: \"Too Many Requests\",\r\n\t500: \"Internal Server Error\",\r\n\t502: \"Bad Gateway\",\r\n\t503: \"Service Unavailable\",\r\n\t504: \"Gateway Timeout\",\r\n};\r\n\r\nexport const defaultRetryCodes: Required<BaseCallApiConfig>[\"retryCodes\"] =\r\n\tObject.keys(retryCodesLookup).map(Number);\r\n\r\nexport const defaultRetryMethods: Required<BaseCallApiConfig>[\"retryMethods\"] = [\"GET\"];\r\n\r\nexport const fetchSpecificKeys = [\r\n\t\"body\",\r\n\t\"integrity\",\r\n\t\"method\",\r\n\t\"headers\",\r\n\t\"signal\",\r\n\t\"cache\",\r\n\t\"redirect\",\r\n\t\"window\",\r\n\t\"credentials\",\r\n\t\"keepalive\",\r\n\t\"referrer\",\r\n\t\"priority\",\r\n\t\"mode\",\r\n\t\"referrerPolicy\",\r\n] satisfies Array<keyof RequestInit>;\r\n\r\nexport const omitKeys = <\r\n\tTObject extends Record<string, unknown>,\r\n\tconst TOmitArray extends Array<keyof TObject>,\r\n>(\r\n\tinitialObject: TObject,\r\n\tkeysToOmit: TOmitArray\r\n) => {\r\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\r\n\t\t([key]) => !keysToOmit.includes(key)\r\n\t);\r\n\r\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\r\n\r\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\r\n};\r\n\r\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\r\n\tinitialObject: TObject,\r\n\tkeysToPick: TPickArray\r\n) => {\r\n\tconst keysToPickSet = new Set(keysToPick);\r\n\r\n\tconst arrayFromInitObject = Object.entries(initialObject);\r\n\r\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\r\n\r\n\tconst updatedObject = Object.fromEntries(filteredArray);\r\n\r\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\r\n};\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitBaseConfig = (baseConfig: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(baseConfig, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(baseConfig, [...fetchSpecificKeys, \"requestKey\"] satisfies Array<\r\n\t\t\tkeyof CallApiConfig\r\n\t\t>) as BaseCallApiExtraOptions,\r\n\t] as const;\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitConfig = (config: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(config, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(config, fetchSpecificKeys) as CallApiExtraOptions,\r\n\t] as const;\r\n\r\nexport const handleInterceptorsMerge = <\r\n\tTBaseInterceptor extends AnyFunction<Awaitable<void>> | Array<AnyFunction<Awaitable<void>>>,\r\n\tTInterceptor extends AnyFunction<Awaitable<void>>,\r\n>(\r\n\tbaseInterceptor: TBaseInterceptor | undefined,\r\n\tinterceptor: TInterceptor | undefined,\r\n\tmergeInterceptors: CallApiExtraOptions[\"mergeInterceptors\"],\r\n\tmergedInterceptorsExecutionMode: CallApiExtraOptions[\"mergedInterceptorsExecutionMode\"]\r\n) => {\r\n\tif (isArray(baseInterceptor) && mergeInterceptors) {\r\n\t\tconst mergedInterceptor = async (ctx: Record<string, unknown>) => {\r\n\t\t\tconst interceptorArray = [...baseInterceptor, ...(interceptor ? [interceptor] : [])] as Array<\r\n\t\t\t\tAnyFunction<Awaitable<void>>\r\n\t\t\t>;\r\n\r\n\t\t\tconst uniqueInterceptorArray = [...new Set(interceptorArray)];\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"sequential\") {\r\n\t\t\t\tfor (const uniqueInterceptor of uniqueInterceptorArray) {\r\n\t\t\t\t\t// eslint-disable-next-line no-await-in-loop\r\n\t\t\t\t\tawait uniqueInterceptor(ctx);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"parallel\") {\r\n\t\t\t\tawait Promise.all(uniqueInterceptorArray.map((uniqueInterceptor) => uniqueInterceptor(ctx)));\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\treturn mergedInterceptor;\r\n\t}\r\n\r\n\treturn interceptor ?? (baseInterceptor as typeof interceptor);\r\n};\r\n\r\nexport const handleResponseType = <TResponse>(\r\n\tresponse: Response,\r\n\tparser?: Required<CallApiExtraOptions>[\"responseParser\"]\r\n) => ({\r\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\r\n\tblob: () => response.blob() as Promise<TResponse>,\r\n\tformData: () => response.formData() as Promise<TResponse>,\r\n\tjson: async () => {\r\n\t\tif (parser) {\r\n\t\t\treturn parser(await response.text());\r\n\t\t}\r\n\r\n\t\treturn response.json() as Promise<TResponse>;\r\n\t},\r\n\ttext: () => response.text() as Promise<TResponse>,\r\n});\r\n\r\nexport const getResponseData = <TResponse>(\r\n\tresponse: Response,\r\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\r\n\tparser: CallApiExtraOptions[\"responseParser\"]\r\n) => {\r\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\r\n\r\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\r\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\r\n\t}\r\n\r\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\r\n};\r\n\r\ntype SuccessInfo = {\r\n\tresponse: Response;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n\tsuccessData: unknown;\r\n};\r\n\r\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\r\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\r\nexport const resolveSuccessResult = <CallApiResult>(info: SuccessInfo): CallApiResult => {\r\n\tconst { response, resultMode, successData } = info;\r\n\r\n\tconst apiDetails = {\r\n\t\tdata: successData,\r\n\t\terror: null,\r\n\t\tresponse,\r\n\t};\r\n\r\n\tif (!resultMode) {\r\n\t\treturn apiDetails as CallApiResult;\r\n\t}\r\n\r\n\treturn {\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode] as CallApiResult;\r\n};\r\n\r\ntype ErrorInfo = {\r\n\tdefaultErrorMessage: Required<CallApiExtraOptions>[\"defaultErrorMessage\"];\r\n\terror?: unknown;\r\n\tmessage?: string;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n};\r\n\r\nexport const resolveErrorResult = <CallApiResult>(info: ErrorInfo) => {\r\n\tconst { defaultErrorMessage, error, message: customErrorMessage, resultMode } = info;\r\n\r\n\tlet apiDetails!: ResultModeMap[\"all\"];\r\n\r\n\tif (isHTTPErrorInstance(error)) {\r\n\t\tconst { errorData, message = defaultErrorMessage, name, response } = error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: { errorData, message, name },\r\n\t\t\tresponse,\r\n\t\t};\r\n\t}\r\n\r\n\tif (error) {\r\n\t\tconst { message, name } = error as Error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: {\r\n\t\t\t\terrorData: error as Error,\r\n\t\t\t\tmessage: customErrorMessage ?? message,\r\n\t\t\t\tname: name as PossibleErrorNames,\r\n\t\t\t},\r\n\t\t\tresponse: null,\r\n\t\t};\r\n\t}\r\n\r\n\tconst generalErrorResult = ({\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode ?? \"all\"] ?? apiDetails) as CallApiResult;\r\n\r\n\t// prettier-ignore\r\n\tconst resolveCustomErrorInfo = ({ message }: Pick<ErrorInfo, \"message\">) => {\r\n\t\tconst errorResult = resolveErrorResult<CallApiResult>({ ...info, message });\r\n\r\n\t\treturn errorResult.generalErrorResult;\r\n\t};\r\n\r\n\treturn { generalErrorResult, resolveCustomErrorInfo };\r\n};\r\n\r\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\r\n\treturn isObject(error) && error.name === \"HTTPError\";\r\n};\r\n\r\ntype ErrorDetails<TErrorResponse> = {\r\n\tdefaultErrorMessage: string;\r\n\terrorData: TErrorResponse;\r\n\tresponse: Response;\r\n};\r\n\r\ntype ErrorOptions = {\r\n\tcause?: unknown;\r\n};\r\n\r\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\r\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\r\n\tisHTTPError = true;\r\n\r\n\toverride name = \"HTTPError\" as const;\r\n\r\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\r\n\r\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\r\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\r\n\r\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\r\n\r\n\t\tthis.errorData = errorData;\r\n\t\tthis.response = response;\r\n\r\n\t\tError.captureStackTrace(this, this.constructor);\r\n\t}\r\n}\r\n\r\nexport const isHTTPErrorInstance = <TErrorResponse>(\r\n\terror: unknown\r\n): error is HTTPError<TErrorResponse> => {\r\n\treturn (\r\n\t\t// prettier-ignore\r\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\r\n\t);\r\n};\r\n\r\nconst PromiseWithResolvers = () => {\r\n\tlet reject!: (reason?: unknown) => void;\r\n\tlet resolve!: (value: unknown) => void;\r\n\r\n\tconst promise = new Promise((res, rej) => {\r\n\t\tresolve = res;\r\n\t\treject = rej;\r\n\t});\r\n\r\n\treturn { promise, reject, resolve };\r\n};\r\n\r\nexport const waitUntil = (delay: number) => {\r\n\tif (delay === 0) return;\r\n\r\n\tconst { promise, resolve } = PromiseWithResolvers();\r\n\r\n\tsetTimeout(resolve, delay);\r\n\r\n\treturn promise;\r\n};\r\n\r\nexport const executeInterceptors = <TInterceptor extends Awaitable<void>>(\r\n\t...interceptors: TInterceptor[]\r\n) => Promise.all(interceptors);\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,UAAU,CAAa,UAA0C,MAAM,QAAQ,KAAK;AAE1F,IAAM,WAAW,CAA0C,UAAqC;AACtG,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,iBAAiB,aAAa,CAAC,QAAQ,KAAK;AACrG;;;ACcO,IAAM,gBAAiC,CAAC,WAAW;AACzD,MAAI,CAAC,QAAQ;AACZ,YAAQ,MAAM,kBAAkB,2BAA2B;AAE3D,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,gBAAgB,MAAgC,EAAE,SAAS;AACvE;AA8GA,IAAM,mBAAmB;AAAA,EACxB,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACN;AAEO,IAAM,oBACZ,OAAO,KAAK,gBAAgB,EAAE,IAAI,MAAM;AAwNlC,IAAM,cAAc,CAAa,UAAuD;AAC9F,SAAO,SAAS,KAAK,KAAK,MAAM,SAAS;AAC1C;AAYO,IAAM,YAAN,cAAkE,MAAM;AAAA,EAC9E;AAAA,EACA,cAAc;AAAA,EAEL,OAAO;AAAA,EAEhB;AAAA,EAEA,YAAY,cAA4C,cAA6B;AACpF,UAAM,EAAE,qBAAqB,WAAW,SAAS,IAAI;AAErD,UAAO,UAAmC,WAAW,qBAAqB,YAAY;AAEtF,SAAK,YAAY;AACjB,SAAK,WAAW;AAEhB,UAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,EAC/C;AACD;AAEO,IAAM,sBAAsB,CAClC,UACwC;AACxC;AAAA;AAAA,IAEC,iBAAiB,aAAc,SAAS,KAAK,KAAK,MAAM,SAAS,eAAe,MAAM,gBAAgB;AAAA;AAExG;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/index.ts","../../../src/utils/typeof.ts","../../../src/utils/common.ts"],"sourcesContent":["export { HTTPError, isHTTPError, isHTTPErrorInstance, toQueryString } from \"./common\";\r\n","import type { AnyFunction } from \"./type-helpers\";\r\n\r\nexport const isArray = <TArrayItem>(value: unknown): value is TArrayItem[] => Array.isArray(value);\r\n\r\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\r\n\treturn typeof value === \"object\" && value !== null && !(value instanceof FormData) && !isArray(value);\r\n};\r\n\r\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\r\n\ttypeof value === \"function\";\r\n\r\nexport const isQueryString = (value: unknown): value is string => isString(value) && value.includes(\"=\");\r\n\r\nexport const isString = (value: unknown) => typeof value === \"string\";\r\n","import type {\r\n\tApiErrorVariant,\r\n\tBaseCallApiConfig,\r\n\tBaseCallApiExtraOptions,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tPossibleErrorNames,\r\n} from \"../types\";\r\nimport type { AnyFunction, Awaitable } from \"./type-helpers\";\r\nimport { isArray, isObject, isQueryString, isString } from \"./typeof\";\r\n\r\n// prettier-ignore\r\nexport const generateRequestKey = (url: string, config: Record<string, unknown>) => `${url} ${ampersand} ${JSON.stringify(config)}`;\r\n\r\ntype ToQueryStringFn = {\r\n\t(params: CallApiConfig[\"query\"]): string | null;\r\n\t(params: Required<CallApiConfig>[\"query\"]): string;\r\n};\r\n\r\nexport const toQueryString: ToQueryStringFn = (params) => {\r\n\tif (!params) {\r\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\r\n\r\n\t\treturn null as never;\r\n\t}\r\n\r\n\treturn new URLSearchParams(params as Record<string, string>).toString();\r\n};\r\n\r\nconst slash = \"/\";\r\nconst column = \":\";\r\nconst mergeUrlWithParams = (url: string, params: CallApiExtraOptions[\"params\"]) => {\r\n\tif (!params) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tlet newUrl = url;\r\n\r\n\tif (isArray(params)) {\r\n\t\tconst matchedParamArray = newUrl\r\n\t\t\t.split(slash)\r\n\t\t\t.filter((matchedParam) => matchedParam.startsWith(column));\r\n\r\n\t\tfor (const [index, matchedParam] of matchedParamArray.entries()) {\r\n\t\t\tconst param = params[index] as string;\r\n\t\t\tnewUrl = newUrl.replace(matchedParam, param);\r\n\t\t}\r\n\r\n\t\treturn newUrl;\r\n\t}\r\n\r\n\tfor (const [key, value] of Object.entries(params)) {\r\n\t\tnewUrl = newUrl.replace(`:${key}`, String(value));\r\n\t}\r\n\r\n\treturn newUrl;\r\n};\r\n\r\nconst questionMark = \"?\";\r\nconst ampersand = \"&\";\r\n\r\nconst mergeUrlWithQuery = (url: string, query: CallApiConfig[\"query\"]): string => {\r\n\tif (!query) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tconst queryString = toQueryString(query);\r\n\r\n\tif (queryString?.length === 0) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tif (url.endsWith(questionMark)) {\r\n\t\treturn `${url}${queryString}`;\r\n\t}\r\n\r\n\tif (url.includes(questionMark)) {\r\n\t\treturn `${url}${ampersand}${queryString}`;\r\n\t}\r\n\r\n\treturn `${url}${questionMark}${queryString}`;\r\n};\r\n\r\nexport const mergeUrlWithParamsAndQuery = (\r\n\turl: string,\r\n\tparams: CallApiExtraOptions[\"params\"],\r\n\tquery: CallApiExtraOptions[\"query\"]\r\n) => {\r\n\tconst urlWithMergedParams = mergeUrlWithParams(url, params);\r\n\r\n\treturn mergeUrlWithQuery(urlWithMergedParams, query);\r\n};\r\n\r\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\r\n\tif (!headers || isObject(headers)) {\r\n\t\treturn headers;\r\n\t}\r\n\r\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\r\n};\r\n\r\nexport const resolveHeaders = (options: {\r\n\tauth: CallApiConfig[\"auth\"];\r\n\tbaseHeaders: CallApiConfig[\"headers\"];\r\n\tbody: CallApiConfig[\"body\"];\r\n\theaders: CallApiConfig[\"headers\"];\r\n}) => {\r\n\tconst { auth, baseHeaders, body, headers } = options;\r\n\r\n\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing\r\n\tconst shouldResolveHeaders = baseHeaders || headers || body || auth;\r\n\r\n\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\r\n\t// - headers are provided\r\n\t// - The body is an object\r\n\t// - The auth option is provided\r\n\tif (!shouldResolveHeaders) return;\r\n\r\n\treturn {\r\n\t\t...(isObject(body) && {\r\n\t\t\tAccept: \"application/json\",\r\n\t\t\t\"Content-Type\": \"application/json\",\r\n\t\t}),\r\n\t\t...(isQueryString(body) && {\r\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\r\n\t\t}),\r\n\t\t...((isString(auth) || auth === null) && {\r\n\t\t\tAuthorization: `Bearer ${auth}`,\r\n\t\t}),\r\n\t\t...(isObject(auth) && {\r\n\t\t\tAuthorization: \"bearer\" in auth ? `Bearer ${auth.bearer}` : `Token ${auth.token}`,\r\n\t\t}),\r\n\t\t...objectifyHeaders(baseHeaders),\r\n\t\t...objectifyHeaders(headers),\r\n\t};\r\n};\r\n\r\nconst retryCodesLookup = {\r\n\t408: \"Request Timeout\",\r\n\t409: \"Conflict\",\r\n\t425: \"Too Early\",\r\n\t429: \"Too Many Requests\",\r\n\t500: \"Internal Server Error\",\r\n\t502: \"Bad Gateway\",\r\n\t503: \"Service Unavailable\",\r\n\t504: \"Gateway Timeout\",\r\n};\r\n\r\nexport const defaultRetryCodes: Required<BaseCallApiConfig>[\"retryCodes\"] =\r\n\tObject.keys(retryCodesLookup).map(Number);\r\n\r\nexport const defaultRetryMethods: Required<BaseCallApiConfig>[\"retryMethods\"] = [\"GET\"];\r\n\r\nexport const fetchSpecificKeys = [\r\n\t\"body\",\r\n\t\"integrity\",\r\n\t\"method\",\r\n\t\"headers\",\r\n\t\"signal\",\r\n\t\"cache\",\r\n\t\"redirect\",\r\n\t\"window\",\r\n\t\"credentials\",\r\n\t\"keepalive\",\r\n\t\"referrer\",\r\n\t\"priority\",\r\n\t\"mode\",\r\n\t\"referrerPolicy\",\r\n] satisfies Array<keyof RequestInit>;\r\n\r\nexport const omitKeys = <\r\n\tTObject extends Record<string, unknown>,\r\n\tconst TOmitArray extends Array<keyof TObject>,\r\n>(\r\n\tinitialObject: TObject,\r\n\tkeysToOmit: TOmitArray\r\n) => {\r\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\r\n\t\t([key]) => !keysToOmit.includes(key)\r\n\t);\r\n\r\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\r\n\r\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\r\n};\r\n\r\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\r\n\tinitialObject: TObject,\r\n\tkeysToPick: TPickArray\r\n) => {\r\n\tconst keysToPickSet = new Set(keysToPick);\r\n\r\n\tconst arrayFromInitObject = Object.entries(initialObject);\r\n\r\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\r\n\r\n\tconst updatedObject = Object.fromEntries(filteredArray);\r\n\r\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\r\n};\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitBaseConfig = (baseConfig: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(baseConfig, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(baseConfig, [...fetchSpecificKeys, \"requestKey\"] satisfies Array<\r\n\t\t\tkeyof CallApiConfig\r\n\t\t>) as BaseCallApiExtraOptions,\r\n\t] as const;\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitConfig = (config: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(config, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(config, fetchSpecificKeys) as CallApiExtraOptions,\r\n\t] as const;\r\n\r\nexport const handleInterceptorsMerge = <\r\n\tTBaseInterceptor extends AnyFunction<Awaitable<void>> | Array<AnyFunction<Awaitable<void>>>,\r\n\tTInterceptor extends AnyFunction<Awaitable<void>>,\r\n>(\r\n\tbaseInterceptor: TBaseInterceptor | undefined,\r\n\tinterceptor: TInterceptor | undefined,\r\n\tmergeInterceptors: CallApiExtraOptions[\"mergeInterceptors\"],\r\n\tmergedInterceptorsExecutionMode: CallApiExtraOptions[\"mergedInterceptorsExecutionMode\"]\r\n) => {\r\n\tif (isArray(baseInterceptor) && mergeInterceptors) {\r\n\t\tconst mergedInterceptor = async (ctx: Record<string, unknown>) => {\r\n\t\t\tconst interceptorArray = [...baseInterceptor, ...(interceptor ? [interceptor] : [])] as Array<\r\n\t\t\t\tAnyFunction<Awaitable<void>>\r\n\t\t\t>;\r\n\r\n\t\t\tconst uniqueInterceptorArray = [...new Set(interceptorArray)];\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"sequential\") {\r\n\t\t\t\tfor (const uniqueInterceptor of uniqueInterceptorArray) {\r\n\t\t\t\t\t// eslint-disable-next-line no-await-in-loop\r\n\t\t\t\t\tawait uniqueInterceptor(ctx);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"parallel\") {\r\n\t\t\t\tawait Promise.all(uniqueInterceptorArray.map((uniqueInterceptor) => uniqueInterceptor(ctx)));\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\treturn mergedInterceptor;\r\n\t}\r\n\r\n\treturn interceptor ?? (baseInterceptor as typeof interceptor);\r\n};\r\n\r\nexport const handleResponseType = <TResponse>(\r\n\tresponse: Response,\r\n\tparser?: Required<CallApiExtraOptions>[\"responseParser\"]\r\n) => ({\r\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\r\n\tblob: () => response.blob() as Promise<TResponse>,\r\n\tformData: () => response.formData() as Promise<TResponse>,\r\n\tjson: async () => {\r\n\t\tif (parser) {\r\n\t\t\treturn parser(await response.text());\r\n\t\t}\r\n\r\n\t\treturn response.json() as Promise<TResponse>;\r\n\t},\r\n\ttext: () => response.text() as Promise<TResponse>,\r\n});\r\n\r\nexport const getResponseData = <TResponse>(\r\n\tresponse: Response,\r\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\r\n\tparser: CallApiExtraOptions[\"responseParser\"]\r\n) => {\r\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\r\n\r\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\r\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\r\n\t}\r\n\r\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\r\n};\r\n\r\ntype SuccessInfo = {\r\n\tresponse: Response;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n\tsuccessData: unknown;\r\n};\r\n\r\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\r\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\r\nexport const resolveSuccessResult = <CallApiResult>(info: SuccessInfo): CallApiResult => {\r\n\tconst { response, resultMode, successData } = info;\r\n\r\n\tconst apiDetails = {\r\n\t\tdata: successData,\r\n\t\terror: null,\r\n\t\tresponse,\r\n\t};\r\n\r\n\tif (!resultMode) {\r\n\t\treturn apiDetails as CallApiResult;\r\n\t}\r\n\r\n\treturn {\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode] as CallApiResult;\r\n};\r\n\r\ntype ErrorInfo = {\r\n\tdefaultErrorMessage: Required<CallApiExtraOptions>[\"defaultErrorMessage\"];\r\n\terror?: unknown;\r\n\tmessage?: string;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n};\r\n\r\nexport const resolveErrorResult = <TCallApiResult>(info: ErrorInfo) => {\r\n\tconst { defaultErrorMessage, error, message: customErrorMessage, resultMode } = info;\r\n\r\n\tlet apiDetails!: ApiErrorVariant<unknown>;\r\n\r\n\tif (isHTTPErrorInstance(error)) {\r\n\t\tconst { errorData, message = defaultErrorMessage, name, response } = error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: { errorData, message, name },\r\n\t\t\tresponse,\r\n\t\t};\r\n\t}\r\n\r\n\tif (error) {\r\n\t\tconst { message, name } = error as Error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: {\r\n\t\t\t\terrorData: error as Error,\r\n\t\t\t\tmessage: customErrorMessage ?? message,\r\n\t\t\t\tname: name as PossibleErrorNames,\r\n\t\t\t},\r\n\t\t\tresponse: null,\r\n\t\t};\r\n\t}\r\n\r\n\tconst generalErrorResult = ({\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode ?? \"all\"] ?? apiDetails) as TCallApiResult;\r\n\r\n\t// prettier-ignore\r\n\tconst resolveCustomErrorInfo = ({ message }: Pick<ErrorInfo, \"message\">) => {\r\n\t\tconst errorResult = resolveErrorResult<TCallApiResult>({ ...info, message });\r\n\r\n\t\treturn errorResult.generalErrorResult;\r\n\t};\r\n\r\n\treturn { apiDetails, generalErrorResult, resolveCustomErrorInfo };\r\n};\r\n\r\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\r\n\treturn isObject(error) && error.name === \"HTTPError\";\r\n};\r\n\r\ntype ErrorDetails<TErrorResponse> = {\r\n\tdefaultErrorMessage: string;\r\n\terrorData: TErrorResponse;\r\n\tresponse: Response;\r\n};\r\n\r\ntype ErrorOptions = {\r\n\tcause?: unknown;\r\n};\r\n\r\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\r\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\r\n\tisHTTPError = true;\r\n\r\n\toverride name = \"HTTPError\" as const;\r\n\r\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\r\n\r\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\r\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\r\n\r\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\r\n\r\n\t\tthis.errorData = errorData;\r\n\t\tthis.response = response;\r\n\r\n\t\tError.captureStackTrace(this, this.constructor);\r\n\t}\r\n}\r\n\r\nexport const isHTTPErrorInstance = <TErrorResponse>(\r\n\terror: unknown\r\n): error is HTTPError<TErrorResponse> => {\r\n\treturn (\r\n\t\t// prettier-ignore\r\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\r\n\t);\r\n};\r\n\r\nconst PromiseWithResolvers = () => {\r\n\tlet reject!: (reason?: unknown) => void;\r\n\tlet resolve!: (value: unknown) => void;\r\n\r\n\tconst promise = new Promise((res, rej) => {\r\n\t\tresolve = res;\r\n\t\treject = rej;\r\n\t});\r\n\r\n\treturn { promise, reject, resolve };\r\n};\r\n\r\nexport const waitUntil = (delay: number) => {\r\n\tif (delay === 0) return;\r\n\r\n\tconst { promise, resolve } = PromiseWithResolvers();\r\n\r\n\tsetTimeout(resolve, delay);\r\n\r\n\treturn promise;\r\n};\r\n\r\nexport const executeInterceptors = <TInterceptor extends Awaitable<void>>(\r\n\t...interceptors: TInterceptor[]\r\n) => Promise.all(interceptors);\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,UAAU,CAAa,UAA0C,MAAM,QAAQ,KAAK;AAE1F,IAAM,WAAW,CAA0C,UAAqC;AACtG,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,iBAAiB,aAAa,CAAC,QAAQ,KAAK;AACrG;;;ACaO,IAAM,gBAAiC,CAAC,WAAW;AACzD,MAAI,CAAC,QAAQ;AACZ,YAAQ,MAAM,kBAAkB,2BAA2B;AAE3D,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,gBAAgB,MAAgC,EAAE,SAAS;AACvE;AA8GA,IAAM,mBAAmB;AAAA,EACxB,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACN;AAEO,IAAM,oBACZ,OAAO,KAAK,gBAAgB,EAAE,IAAI,MAAM;AAwNlC,IAAM,cAAc,CAAa,UAAuD;AAC9F,SAAO,SAAS,KAAK,KAAK,MAAM,SAAS;AAC1C;AAYO,IAAM,YAAN,cAAkE,MAAM;AAAA,EAC9E;AAAA,EACA,cAAc;AAAA,EAEL,OAAO;AAAA,EAEhB;AAAA,EAEA,YAAY,cAA4C,cAA6B;AACpF,UAAM,EAAE,qBAAqB,WAAW,SAAS,IAAI;AAErD,UAAO,UAAmC,WAAW,qBAAqB,YAAY;AAEtF,SAAK,YAAY;AACjB,SAAK,WAAW;AAEhB,UAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,EAC/C;AACD;AAEO,IAAM,sBAAsB,CAClC,UACwC;AACxC;AAAA;AAAA,IAEC,iBAAiB,aAAc,SAAS,KAAK,KAAK,MAAM,SAAS,eAAe,MAAM,gBAAgB;AAAA;AAExG;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=e=>Array.isArray(e),r=r=>!("object"!=typeof r||null===r||r instanceof FormData||e(r)),t=e=>"function"==typeof e,o=e=>"string"==typeof e,s=(e,r)=>`${e} ${a} ${JSON.stringify(r)}`,n=e=>e?new URLSearchParams(e).toString():(console.error("toQueryString:","No query params provided!"),null),a="&",i=(r,t,o)=>{const s=((r,t)=>{if(!t)return r;let o=r;if(e(t)){const e=o.split("/").filter((e=>e.startsWith(":")));for(const[r,s]of e.entries()){const e=t[r];o=o.replace(s,e)}return o}for(const[e,r]of Object.entries(t))o=o.replace(`:${e}`,String(r));return o})(r,t);return((e,r)=>{if(!r)return e;const t=n(r);return 0===t?.length?e:e.endsWith("?")?`${e}${t}`:e.includes("?")?`${e}${a}${t}`:`${e}?${t}`})(s,o)},l=t=>!t||r(t)?t:Object.fromEntries(e(t)?t:t.entries()),c=e=>{const{auth:t,baseHeaders:s,body:n,headers:a}=e;var i;if(s||a||n||t)return{...r(n)&&{Accept:"application/json","Content-Type":"application/json"},...(i=n,o(i)&&i.includes("=")&&{"Content-Type":"application/x-www-form-urlencoded"}),...(o(t)||null===t)&&{Authorization:`Bearer ${t}`},...r(t)&&{Authorization:"bearer"in t?`Bearer ${t.bearer}`:`Token ${t.token}`},...l(s),...l(a)}},u=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),f=["GET"],p=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],m=(e,r)=>{const t=Object.entries(e).filter((([e])=>!r.includes(e)));return Object.fromEntries(t)},y=(e,r)=>{const t=new Set(r),o=Object.entries(e).filter((([e])=>t.has(e)));return Object.fromEntries(o)},d=e=>[y(e,p),m(e,[...p,"requestKey"])],E=e=>[y(e,p),m(e,p)],b=(r,t,o,s)=>{if(e(r)&&o){return async e=>{const o=[...r,...t?[t]:[]],n=[...new Set(o)];if("sequential"===s)for(const r of n)await r(e);"parallel"===s&&await Promise.all(n.map((r=>r(e))))}}return t??r},g=(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]()},T=e=>{const{response:r,resultMode:t,successData:o}=e,s={data:o,error:null,response:r};return t?{all:s,onlyError:s.error,onlyResponse:s.response,onlySuccess:s.data}[t]:s},h=e=>{const{defaultErrorMessage:r,error:t,message:o,resultMode:s}=e;let n;if(j(t)){const{errorData:e,message:o=r,name:s,response:a}=t;n={data:null,error:{errorData:e,message:o,name:s},response:a}}if(t){const{message:e,name:r}=t;n={data:null,error:{errorData:t,message:o??e,name:r},response:null}}return{generalErrorResult:{all:n,onlyError:n.error,onlyResponse:n.response,onlySuccess:n.data}[s??"all"]??n,resolveCustomErrorInfo:({message:r})=>h({...e,message:r}).generalErrorResult}},w=e=>r(e)&&"HTTPError"===e.name,$=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,Error.captureStackTrace(this,this.constructor)}},j=e=>e instanceof $||r(e)&&"HTTPError"===e.name&&!0===e.isHTTPError,S=e=>{if(0===e)return;const{promise:r,resolve:t}=(()=>{let e,r;return{promise:new Promise(((t,o)=>{r=t,e=o})),reject:e,resolve:r}})();return setTimeout(t,e),r},v=(...e)=>Promise.all(e);export{$ as HTTPError,u as defaultRetryCodes,f as defaultRetryMethods,v as executeInterceptors,s as generateRequestKey,g as getResponseData,b as handleInterceptorsMerge,t as isFunction,w as isHTTPError,j as isHTTPErrorInstance,r as isObject,i as mergeUrlWithParamsAndQuery,h as resolveErrorResult,c as resolveHeaders,T as resolveSuccessResult,d as splitBaseConfig,E as splitConfig,n as toQueryString,S as waitUntil};//# sourceMappingURL=chunk-
|
|
1
|
+
var e=e=>Array.isArray(e),r=r=>!("object"!=typeof r||null===r||r instanceof FormData||e(r)),t=e=>"function"==typeof e,o=e=>"string"==typeof e,s=(e,r)=>`${e} ${a} ${JSON.stringify(r)}`,n=e=>e?new URLSearchParams(e).toString():(console.error("toQueryString:","No query params provided!"),null),a="&",i=(r,t,o)=>{const s=((r,t)=>{if(!t)return r;let o=r;if(e(t)){const e=o.split("/").filter((e=>e.startsWith(":")));for(const[r,s]of e.entries()){const e=t[r];o=o.replace(s,e)}return o}for(const[e,r]of Object.entries(t))o=o.replace(`:${e}`,String(r));return o})(r,t);return((e,r)=>{if(!r)return e;const t=n(r);return 0===t?.length?e:e.endsWith("?")?`${e}${t}`:e.includes("?")?`${e}${a}${t}`:`${e}?${t}`})(s,o)},l=t=>!t||r(t)?t:Object.fromEntries(e(t)?t:t.entries()),c=e=>{const{auth:t,baseHeaders:s,body:n,headers:a}=e;var i;if(s||a||n||t)return{...r(n)&&{Accept:"application/json","Content-Type":"application/json"},...(i=n,o(i)&&i.includes("=")&&{"Content-Type":"application/x-www-form-urlencoded"}),...(o(t)||null===t)&&{Authorization:`Bearer ${t}`},...r(t)&&{Authorization:"bearer"in t?`Bearer ${t.bearer}`:`Token ${t.token}`},...l(s),...l(a)}},u=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),f=["GET"],p=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],m=(e,r)=>{const t=Object.entries(e).filter((([e])=>!r.includes(e)));return Object.fromEntries(t)},y=(e,r)=>{const t=new Set(r),o=Object.entries(e).filter((([e])=>t.has(e)));return Object.fromEntries(o)},d=e=>[y(e,p),m(e,[...p,"requestKey"])],E=e=>[y(e,p),m(e,p)],b=(r,t,o,s)=>{if(e(r)&&o){return async e=>{const o=[...r,...t?[t]:[]],n=[...new Set(o)];if("sequential"===s)for(const r of n)await r(e);"parallel"===s&&await Promise.all(n.map((r=>r(e))))}}return t??r},g=(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]()},T=e=>{const{response:r,resultMode:t,successData:o}=e,s={data:o,error:null,response:r};return t?{all:s,onlyError:s.error,onlyResponse:s.response,onlySuccess:s.data}[t]:s},h=e=>{const{defaultErrorMessage:r,error:t,message:o,resultMode:s}=e;let n;if(j(t)){const{errorData:e,message:o=r,name:s,response:a}=t;n={data:null,error:{errorData:e,message:o,name:s},response:a}}if(t){const{message:e,name:r}=t;n={data:null,error:{errorData:t,message:o??e,name:r},response:null}}return{apiDetails:n,generalErrorResult:{all:n,onlyError:n.error,onlyResponse:n.response,onlySuccess:n.data}[s??"all"]??n,resolveCustomErrorInfo:({message:r})=>h({...e,message:r}).generalErrorResult}},w=e=>r(e)&&"HTTPError"===e.name,$=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,Error.captureStackTrace(this,this.constructor)}},j=e=>e instanceof $||r(e)&&"HTTPError"===e.name&&!0===e.isHTTPError,S=e=>{if(0===e)return;const{promise:r,resolve:t}=(()=>{let e,r;return{promise:new Promise(((t,o)=>{r=t,e=o})),reject:e,resolve:r}})();return setTimeout(t,e),r},v=(...e)=>Promise.all(e);export{$ as HTTPError,u as defaultRetryCodes,f as defaultRetryMethods,v as executeInterceptors,s as generateRequestKey,g as getResponseData,b as handleInterceptorsMerge,t as isFunction,w as isHTTPError,j as isHTTPErrorInstance,r as isObject,i as mergeUrlWithParamsAndQuery,h as resolveErrorResult,c as resolveHeaders,T as resolveSuccessResult,d as splitBaseConfig,E as splitConfig,n as toQueryString,S as waitUntil};//# sourceMappingURL=chunk-O3QDH76S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/typeof.ts","../../src/utils/common.ts"],"names":[],"mappings":"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","file":"chunk-O3QDH76S.js","sourcesContent":["import type { AnyFunction } from \"./type-helpers\";\r\n\r\nexport const isArray = <TArrayItem>(value: unknown): value is TArrayItem[] => Array.isArray(value);\r\n\r\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\r\n\treturn typeof value === \"object\" && value !== null && !(value instanceof FormData) && !isArray(value);\r\n};\r\n\r\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\r\n\ttypeof value === \"function\";\r\n\r\nexport const isQueryString = (value: unknown): value is string => isString(value) && value.includes(\"=\");\r\n\r\nexport const isString = (value: unknown) => typeof value === \"string\";\r\n","import type {\r\n\tApiErrorVariant,\r\n\tBaseCallApiConfig,\r\n\tBaseCallApiExtraOptions,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tPossibleErrorNames,\r\n} from \"../types\";\r\nimport type { AnyFunction, Awaitable } from \"./type-helpers\";\r\nimport { isArray, isObject, isQueryString, isString } from \"./typeof\";\r\n\r\n// prettier-ignore\r\nexport const generateRequestKey = (url: string, config: Record<string, unknown>) => `${url} ${ampersand} ${JSON.stringify(config)}`;\r\n\r\ntype ToQueryStringFn = {\r\n\t(params: CallApiConfig[\"query\"]): string | null;\r\n\t(params: Required<CallApiConfig>[\"query\"]): string;\r\n};\r\n\r\nexport const toQueryString: ToQueryStringFn = (params) => {\r\n\tif (!params) {\r\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\r\n\r\n\t\treturn null as never;\r\n\t}\r\n\r\n\treturn new URLSearchParams(params as Record<string, string>).toString();\r\n};\r\n\r\nconst slash = \"/\";\r\nconst column = \":\";\r\nconst mergeUrlWithParams = (url: string, params: CallApiExtraOptions[\"params\"]) => {\r\n\tif (!params) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tlet newUrl = url;\r\n\r\n\tif (isArray(params)) {\r\n\t\tconst matchedParamArray = newUrl\r\n\t\t\t.split(slash)\r\n\t\t\t.filter((matchedParam) => matchedParam.startsWith(column));\r\n\r\n\t\tfor (const [index, matchedParam] of matchedParamArray.entries()) {\r\n\t\t\tconst param = params[index] as string;\r\n\t\t\tnewUrl = newUrl.replace(matchedParam, param);\r\n\t\t}\r\n\r\n\t\treturn newUrl;\r\n\t}\r\n\r\n\tfor (const [key, value] of Object.entries(params)) {\r\n\t\tnewUrl = newUrl.replace(`:${key}`, String(value));\r\n\t}\r\n\r\n\treturn newUrl;\r\n};\r\n\r\nconst questionMark = \"?\";\r\nconst ampersand = \"&\";\r\n\r\nconst mergeUrlWithQuery = (url: string, query: CallApiConfig[\"query\"]): string => {\r\n\tif (!query) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tconst queryString = toQueryString(query);\r\n\r\n\tif (queryString?.length === 0) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tif (url.endsWith(questionMark)) {\r\n\t\treturn `${url}${queryString}`;\r\n\t}\r\n\r\n\tif (url.includes(questionMark)) {\r\n\t\treturn `${url}${ampersand}${queryString}`;\r\n\t}\r\n\r\n\treturn `${url}${questionMark}${queryString}`;\r\n};\r\n\r\nexport const mergeUrlWithParamsAndQuery = (\r\n\turl: string,\r\n\tparams: CallApiExtraOptions[\"params\"],\r\n\tquery: CallApiExtraOptions[\"query\"]\r\n) => {\r\n\tconst urlWithMergedParams = mergeUrlWithParams(url, params);\r\n\r\n\treturn mergeUrlWithQuery(urlWithMergedParams, query);\r\n};\r\n\r\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\r\n\tif (!headers || isObject(headers)) {\r\n\t\treturn headers;\r\n\t}\r\n\r\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\r\n};\r\n\r\nexport const resolveHeaders = (options: {\r\n\tauth: CallApiConfig[\"auth\"];\r\n\tbaseHeaders: CallApiConfig[\"headers\"];\r\n\tbody: CallApiConfig[\"body\"];\r\n\theaders: CallApiConfig[\"headers\"];\r\n}) => {\r\n\tconst { auth, baseHeaders, body, headers } = options;\r\n\r\n\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing\r\n\tconst shouldResolveHeaders = baseHeaders || headers || body || auth;\r\n\r\n\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\r\n\t// - headers are provided\r\n\t// - The body is an object\r\n\t// - The auth option is provided\r\n\tif (!shouldResolveHeaders) return;\r\n\r\n\treturn {\r\n\t\t...(isObject(body) && {\r\n\t\t\tAccept: \"application/json\",\r\n\t\t\t\"Content-Type\": \"application/json\",\r\n\t\t}),\r\n\t\t...(isQueryString(body) && {\r\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\r\n\t\t}),\r\n\t\t...((isString(auth) || auth === null) && {\r\n\t\t\tAuthorization: `Bearer ${auth}`,\r\n\t\t}),\r\n\t\t...(isObject(auth) && {\r\n\t\t\tAuthorization: \"bearer\" in auth ? `Bearer ${auth.bearer}` : `Token ${auth.token}`,\r\n\t\t}),\r\n\t\t...objectifyHeaders(baseHeaders),\r\n\t\t...objectifyHeaders(headers),\r\n\t};\r\n};\r\n\r\nconst retryCodesLookup = {\r\n\t408: \"Request Timeout\",\r\n\t409: \"Conflict\",\r\n\t425: \"Too Early\",\r\n\t429: \"Too Many Requests\",\r\n\t500: \"Internal Server Error\",\r\n\t502: \"Bad Gateway\",\r\n\t503: \"Service Unavailable\",\r\n\t504: \"Gateway Timeout\",\r\n};\r\n\r\nexport const defaultRetryCodes: Required<BaseCallApiConfig>[\"retryCodes\"] =\r\n\tObject.keys(retryCodesLookup).map(Number);\r\n\r\nexport const defaultRetryMethods: Required<BaseCallApiConfig>[\"retryMethods\"] = [\"GET\"];\r\n\r\nexport const fetchSpecificKeys = [\r\n\t\"body\",\r\n\t\"integrity\",\r\n\t\"method\",\r\n\t\"headers\",\r\n\t\"signal\",\r\n\t\"cache\",\r\n\t\"redirect\",\r\n\t\"window\",\r\n\t\"credentials\",\r\n\t\"keepalive\",\r\n\t\"referrer\",\r\n\t\"priority\",\r\n\t\"mode\",\r\n\t\"referrerPolicy\",\r\n] satisfies Array<keyof RequestInit>;\r\n\r\nexport const omitKeys = <\r\n\tTObject extends Record<string, unknown>,\r\n\tconst TOmitArray extends Array<keyof TObject>,\r\n>(\r\n\tinitialObject: TObject,\r\n\tkeysToOmit: TOmitArray\r\n) => {\r\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\r\n\t\t([key]) => !keysToOmit.includes(key)\r\n\t);\r\n\r\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\r\n\r\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\r\n};\r\n\r\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\r\n\tinitialObject: TObject,\r\n\tkeysToPick: TPickArray\r\n) => {\r\n\tconst keysToPickSet = new Set(keysToPick);\r\n\r\n\tconst arrayFromInitObject = Object.entries(initialObject);\r\n\r\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\r\n\r\n\tconst updatedObject = Object.fromEntries(filteredArray);\r\n\r\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\r\n};\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitBaseConfig = (baseConfig: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(baseConfig, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(baseConfig, [...fetchSpecificKeys, \"requestKey\"] satisfies Array<\r\n\t\t\tkeyof CallApiConfig\r\n\t\t>) as BaseCallApiExtraOptions,\r\n\t] as const;\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitConfig = (config: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(config, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(config, fetchSpecificKeys) as CallApiExtraOptions,\r\n\t] as const;\r\n\r\nexport const handleInterceptorsMerge = <\r\n\tTBaseInterceptor extends AnyFunction<Awaitable<void>> | Array<AnyFunction<Awaitable<void>>>,\r\n\tTInterceptor extends AnyFunction<Awaitable<void>>,\r\n>(\r\n\tbaseInterceptor: TBaseInterceptor | undefined,\r\n\tinterceptor: TInterceptor | undefined,\r\n\tmergeInterceptors: CallApiExtraOptions[\"mergeInterceptors\"],\r\n\tmergedInterceptorsExecutionMode: CallApiExtraOptions[\"mergedInterceptorsExecutionMode\"]\r\n) => {\r\n\tif (isArray(baseInterceptor) && mergeInterceptors) {\r\n\t\tconst mergedInterceptor = async (ctx: Record<string, unknown>) => {\r\n\t\t\tconst interceptorArray = [...baseInterceptor, ...(interceptor ? [interceptor] : [])] as Array<\r\n\t\t\t\tAnyFunction<Awaitable<void>>\r\n\t\t\t>;\r\n\r\n\t\t\tconst uniqueInterceptorArray = [...new Set(interceptorArray)];\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"sequential\") {\r\n\t\t\t\tfor (const uniqueInterceptor of uniqueInterceptorArray) {\r\n\t\t\t\t\t// eslint-disable-next-line no-await-in-loop\r\n\t\t\t\t\tawait uniqueInterceptor(ctx);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"parallel\") {\r\n\t\t\t\tawait Promise.all(uniqueInterceptorArray.map((uniqueInterceptor) => uniqueInterceptor(ctx)));\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\treturn mergedInterceptor;\r\n\t}\r\n\r\n\treturn interceptor ?? (baseInterceptor as typeof interceptor);\r\n};\r\n\r\nexport const handleResponseType = <TResponse>(\r\n\tresponse: Response,\r\n\tparser?: Required<CallApiExtraOptions>[\"responseParser\"]\r\n) => ({\r\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\r\n\tblob: () => response.blob() as Promise<TResponse>,\r\n\tformData: () => response.formData() as Promise<TResponse>,\r\n\tjson: async () => {\r\n\t\tif (parser) {\r\n\t\t\treturn parser(await response.text());\r\n\t\t}\r\n\r\n\t\treturn response.json() as Promise<TResponse>;\r\n\t},\r\n\ttext: () => response.text() as Promise<TResponse>,\r\n});\r\n\r\nexport const getResponseData = <TResponse>(\r\n\tresponse: Response,\r\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\r\n\tparser: CallApiExtraOptions[\"responseParser\"]\r\n) => {\r\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\r\n\r\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\r\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\r\n\t}\r\n\r\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\r\n};\r\n\r\ntype SuccessInfo = {\r\n\tresponse: Response;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n\tsuccessData: unknown;\r\n};\r\n\r\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\r\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\r\nexport const resolveSuccessResult = <CallApiResult>(info: SuccessInfo): CallApiResult => {\r\n\tconst { response, resultMode, successData } = info;\r\n\r\n\tconst apiDetails = {\r\n\t\tdata: successData,\r\n\t\terror: null,\r\n\t\tresponse,\r\n\t};\r\n\r\n\tif (!resultMode) {\r\n\t\treturn apiDetails as CallApiResult;\r\n\t}\r\n\r\n\treturn {\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode] as CallApiResult;\r\n};\r\n\r\ntype ErrorInfo = {\r\n\tdefaultErrorMessage: Required<CallApiExtraOptions>[\"defaultErrorMessage\"];\r\n\terror?: unknown;\r\n\tmessage?: string;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n};\r\n\r\nexport const resolveErrorResult = <TCallApiResult>(info: ErrorInfo) => {\r\n\tconst { defaultErrorMessage, error, message: customErrorMessage, resultMode } = info;\r\n\r\n\tlet apiDetails!: ApiErrorVariant<unknown>;\r\n\r\n\tif (isHTTPErrorInstance(error)) {\r\n\t\tconst { errorData, message = defaultErrorMessage, name, response } = error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: { errorData, message, name },\r\n\t\t\tresponse,\r\n\t\t};\r\n\t}\r\n\r\n\tif (error) {\r\n\t\tconst { message, name } = error as Error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: {\r\n\t\t\t\terrorData: error as Error,\r\n\t\t\t\tmessage: customErrorMessage ?? message,\r\n\t\t\t\tname: name as PossibleErrorNames,\r\n\t\t\t},\r\n\t\t\tresponse: null,\r\n\t\t};\r\n\t}\r\n\r\n\tconst generalErrorResult = ({\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode ?? \"all\"] ?? apiDetails) as TCallApiResult;\r\n\r\n\t// prettier-ignore\r\n\tconst resolveCustomErrorInfo = ({ message }: Pick<ErrorInfo, \"message\">) => {\r\n\t\tconst errorResult = resolveErrorResult<TCallApiResult>({ ...info, message });\r\n\r\n\t\treturn errorResult.generalErrorResult;\r\n\t};\r\n\r\n\treturn { apiDetails, generalErrorResult, resolveCustomErrorInfo };\r\n};\r\n\r\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\r\n\treturn isObject(error) && error.name === \"HTTPError\";\r\n};\r\n\r\ntype ErrorDetails<TErrorResponse> = {\r\n\tdefaultErrorMessage: string;\r\n\terrorData: TErrorResponse;\r\n\tresponse: Response;\r\n};\r\n\r\ntype ErrorOptions = {\r\n\tcause?: unknown;\r\n};\r\n\r\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\r\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\r\n\tisHTTPError = true;\r\n\r\n\toverride name = \"HTTPError\" as const;\r\n\r\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\r\n\r\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\r\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\r\n\r\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\r\n\r\n\t\tthis.errorData = errorData;\r\n\t\tthis.response = response;\r\n\r\n\t\tError.captureStackTrace(this, this.constructor);\r\n\t}\r\n}\r\n\r\nexport const isHTTPErrorInstance = <TErrorResponse>(\r\n\terror: unknown\r\n): error is HTTPError<TErrorResponse> => {\r\n\treturn (\r\n\t\t// prettier-ignore\r\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\r\n\t);\r\n};\r\n\r\nconst PromiseWithResolvers = () => {\r\n\tlet reject!: (reason?: unknown) => void;\r\n\tlet resolve!: (value: unknown) => void;\r\n\r\n\tconst promise = new Promise((res, rej) => {\r\n\t\tresolve = res;\r\n\t\treject = rej;\r\n\t});\r\n\r\n\treturn { promise, reject, resolve };\r\n};\r\n\r\nexport const waitUntil = (delay: number) => {\r\n\tif (delay === 0) return;\r\n\r\n\tconst { promise, resolve } = PromiseWithResolvers();\r\n\r\n\tsetTimeout(resolve, delay);\r\n\r\n\treturn promise;\r\n};\r\n\r\nexport const executeInterceptors = <TInterceptor extends Awaitable<void>>(\r\n\t...interceptors: TInterceptor[]\r\n) => Promise.all(interceptors);\r\n"]}
|
package/dist/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{splitBaseConfig as e,splitConfig as r,defaultRetryCodes as o,defaultRetryMethods as s,handleInterceptorsMerge as t,mergeUrlWithParamsAndQuery as n,isObject as a,resolveHeaders as u,generateRequestKey as l,waitUntil as d,executeInterceptors as
|
|
1
|
+
import{splitBaseConfig as e,splitConfig as r,defaultRetryCodes as o,defaultRetryMethods as s,handleInterceptorsMerge as t,mergeUrlWithParamsAndQuery as n,isObject as a,resolveHeaders as u,generateRequestKey as l,waitUntil as d,executeInterceptors as i,getResponseData as c,HTTPError as p,resolveSuccessResult as m,resolveErrorResult as E,isFunction as g,isHTTPErrorInstance as h}from"./chunk-O3QDH76S.js";var y=(R={})=>{const[f,M]=e(R),{body:q,headers:w,signal:b,...S}=f,{onError:I,onRequest:D,onRequestError:x,onResponse:C,onResponseError:O,onSuccess:$,...A}=M,T=new Map,v=async(e,y={})=>{const[R,f]=r(y),{body:M=q,headers:P,signal:k=b,...H}=R,{onError:j,onRequest:z,onRequestError:L,onResponse:U,onResponseError:V,onSuccess:B,...F}=f,G={baseURL:"",bodySerializer:JSON.stringify,dedupeStrategy:"cancel",defaultErrorMessage:"Failed to fetch data from server!",mergedInterceptorsExecutionMode:"parallel",mergeInterceptors:!0,responseType:"json",resultMode:"all",retries:0,retryCodes:o,retryDelay:0,retryMethods:s,...A,...F},J={...{onError:t(I,j,G.mergeInterceptors,G.mergedInterceptorsExecutionMode),onRequest:t(D,z,G.mergeInterceptors,G.mergedInterceptorsExecutionMode),onRequestError:t(x,L,G.mergeInterceptors,G.mergedInterceptorsExecutionMode),onResponse:t(C,U,G.mergeInterceptors,G.mergedInterceptorsExecutionMode),onResponseError:t(O,V,G.mergeInterceptors,G.mergedInterceptorsExecutionMode),onSuccess:t($,B,G.mergeInterceptors,G.mergedInterceptorsExecutionMode)},...G},K=`${J.baseURL}${n(e,J.params,J.query)}`,N={method:"GET",body:a(M)?J.bodySerializer(M):M,headers:u({auth:J.auth,baseHeaders:w,body:M,headers:P}),...S,...H},Q="cancel"===J.dedupeStrategy||"defer"===J.dedupeStrategy,W=J.requestKey??(Q?l(K,{...N,...J}):null);null!=W&&await d(.1);const X=W?T:null,Y=X?.get(W);if(Y&&"cancel"===J.dedupeStrategy){const r=new DOMException(`Request aborted as another request to the endpoint: ${e}, with the same request options was initiated.`,"AbortError");Y.controller.abort(r)}const Z=new AbortController,_=null!=J.timeout?(ee=J.timeout,AbortSignal.timeout(ee)):null;var ee;const re=((...e)=>AbortSignal.any(e.filter(Boolean)))(Z.signal,_,k),oe={signal:re,...N},se={url:K,...oe};try{await i(J.onRequest?.({options:J,request:se})),oe.headers=u({auth:J.auth,baseHeaders:w,body:se.body,headers:se.headers}),se.headers=oe.headers;const r=Y&&"defer"===J.dedupeStrategy?Y.responsePromise:fetch(K,oe);X?.set(W,{controller:Z,responsePromise:r});const o=await r;if(!o.ok&&!re.aborted&&J.retries>0&&J.retryCodes.includes(o.status)&&J.retryMethods.includes(oe.method))return await d(J.retryDelay),await v(e,{...y,retries:J.retries-1});const s="defer"===J.dedupeStrategy||"onlyResponse"===J.resultMode||J.shouldCloneResponse;if(!o.ok){const e=await c(s?o.clone():o,J.responseType,J.responseParser);throw new p({defaultErrorMessage:J.defaultErrorMessage,errorData:e,response:o})}const t=await c(s?o.clone():o,J.responseType,J.responseParser),n=J.responseValidator?J.responseValidator(t):t;return await i(J.onSuccess?.({data:n,options:J,request:se,response:J.shouldCloneResponse?o.clone():o}),J.onResponse?.({data:n,errorData:null,options:J,request:se,response:J.shouldCloneResponse?o.clone():o})),m({response:o,resultMode:J.resultMode,successData:n})}catch(e){const{apiDetails:r,generalErrorResult:o,resolveCustomErrorInfo:s}=E({defaultErrorMessage:J.defaultErrorMessage,error:e,resultMode:J.resultMode}),t=g(J.throwOnError)?J.throwOnError({error:r.error,options:J,request:se}):J.throwOnError,n=()=>{if(t)throw r.error};if(e instanceof DOMException&&"TimeoutError"===e.name){const r=`Request timed out after ${J.timeout}ms`;return console.error(`${e.name}:`,r),n(),s({message:r})}if(e instanceof DOMException&&"AbortError"===e.name){const{message:r,name:s}=e;return console.error(`${s}:`,r),n(),o}if(h(e)){const{errorData:r,response:s}=e;return await i(J.onResponseError?.({errorData:r,options:J,request:se,response:J.shouldCloneResponse?s.clone():s}),J.onResponse?.({data:null,errorData:r,options:J,request:se,response:J.shouldCloneResponse?s.clone():s}),J.onError?.({error:e,options:J,request:se,response:J.shouldCloneResponse?s.clone():s})),n(),o}return await i(J.onRequestError?.({error:e,options:J,request:se}),J.onError?.({error:o.error,options:J,request:se,response:null})),n(),o}finally{X?.delete(W)}};return v.create=y,v},R=y();export{R as callApi,y as createFetchClient};//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/polyfills.ts","../../src/createFetchClient.ts"],"names":["callApi"],"mappings":"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","file":"index.js","sourcesContent":["// prettier-ignore\nexport const createCombinedSignal = (...signals: Array<AbortSignal | null | undefined>) => AbortSignal.any(signals.filter(Boolean));\n\nexport const createTimeoutSignal = (milliseconds: number) => AbortSignal.timeout(milliseconds);\n","import type {\r\n\tBaseCallApiConfig,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tGetCallApiResult,\r\n\tInterceptorUnion,\r\n\tRequestOptions,\r\n\tResultModeUnion,\r\n} from \"./types\";\r\nimport {\r\n\tHTTPError,\r\n\tdefaultRetryCodes,\r\n\tdefaultRetryMethods,\r\n\texecuteInterceptors,\r\n\tgenerateRequestKey,\r\n\tgetResponseData,\r\n\thandleInterceptorsMerge,\r\n\tisHTTPErrorInstance,\r\n\tmergeUrlWithParamsAndQuery,\r\n\tresolveErrorResult,\r\n\tresolveHeaders,\r\n\tresolveSuccessResult,\r\n\tsplitBaseConfig,\r\n\tsplitConfig,\r\n\twaitUntil,\r\n} from \"./utils/common\";\r\nimport { createCombinedSignal, createTimeoutSignal } from \"./utils/polyfills\";\r\nimport { isFunction, isObject } from \"./utils/typeof\";\r\n\r\nexport const createFetchClient = <\r\n\tTBaseData,\r\n\tTBaseErrorData = unknown,\r\n\tTBaseResultMode extends ResultModeUnion = ResultModeUnion,\r\n>(\r\n\tbaseConfig: BaseCallApiConfig<TBaseData, TBaseErrorData, TBaseResultMode> = {}\r\n) => {\r\n\tconst [baseFetchConfig, baseExtraOptions] = splitBaseConfig(baseConfig);\r\n\r\n\tconst {\r\n\t\tbody: baseBody,\r\n\t\theaders: baseHeaders,\r\n\t\tsignal: baseSignal,\r\n\t\t...restOfBaseFetchConfig\r\n\t} = baseFetchConfig;\r\n\r\n\tconst {\r\n\t\tonError: onBaseError,\r\n\t\tonRequest: onBaseRequest,\r\n\t\tonRequestError: onBaseRequestError,\r\n\t\tonResponse: onBaseResponse,\r\n\t\tonResponseError: onBaseResponseError,\r\n\t\tonSuccess: onBaseSuccess,\r\n\t\t...restOfBaseExtraOptions\r\n\t} = baseExtraOptions;\r\n\r\n\tconst requestInfoCache = new Map<\r\n\t\tstring | null,\r\n\t\t{ controller: AbortController; responsePromise: Promise<Response> }\r\n\t>();\r\n\r\n\tconst callApi = async <\r\n\t\tTData = TBaseData,\r\n\t\tTErrorData = TBaseErrorData,\r\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\r\n\t>(\r\n\t\turl: string,\r\n\t\tconfig: CallApiConfig<TData, TErrorData, TResultMode> = {}\r\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\r\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\r\n\r\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config);\r\n\r\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\r\n\r\n\t\t// prettier-ignore\r\n\t\tconst {\r\n\t\t\tonError,\r\n\t\t\tonRequest,\r\n\t\t\tonRequestError,\r\n\t\t\tonResponse,\r\n\t\t\tonResponseError,\r\n\t\t\tonSuccess,\r\n\t\t\t...restOfExtraOptions\r\n\t\t} = extraOptions;\r\n\r\n\t\t// == Default Extra Options\r\n\t\tconst defaultOptions = {\r\n\t\t\tbaseURL: \"\",\r\n\t\t\tbodySerializer: JSON.stringify,\r\n\t\t\tdedupeStrategy: \"cancel\",\r\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\r\n\t\t\tmergedInterceptorsExecutionMode: \"parallel\",\r\n\t\t\tmergeInterceptors: true,\r\n\t\t\tresponseType: \"json\",\r\n\t\t\tresultMode: \"all\",\r\n\t\t\tretries: 0,\r\n\t\t\tretryCodes: defaultRetryCodes,\r\n\t\t\tretryDelay: 0,\r\n\t\t\tretryMethods: defaultRetryMethods,\r\n\r\n\t\t\t...restOfBaseExtraOptions,\r\n\t\t\t...restOfExtraOptions,\r\n\t\t} satisfies Omit<CallApiExtraOptions, InterceptorUnion>;\r\n\r\n\t\tconst interceptors = {\r\n\t\t\tonError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseError,\r\n\t\t\t\tonError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonRequest: handleInterceptorsMerge(\r\n\t\t\t\tonBaseRequest,\r\n\t\t\t\tonRequest,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonRequestError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseRequestError,\r\n\t\t\t\tonRequestError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonResponse: handleInterceptorsMerge(\r\n\t\t\t\tonBaseResponse,\r\n\t\t\t\tonResponse,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonResponseError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseResponseError,\r\n\t\t\t\tonResponseError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonSuccess: handleInterceptorsMerge(\r\n\t\t\t\tonBaseSuccess,\r\n\t\t\t\tonSuccess,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t} satisfies Pick<CallApiExtraOptions, InterceptorUnion>;\r\n\r\n\t\tconst options = {\r\n\t\t\t...interceptors,\r\n\t\t\t...defaultOptions,\r\n\t\t};\r\n\r\n\t\tconst fullUrl = `${options.baseURL}${mergeUrlWithParamsAndQuery(url, options.params, options.query)}`;\r\n\r\n\t\t// == Default Request Init\r\n\t\tconst defaultRequestOptions = {\r\n\t\t\tmethod: \"GET\",\r\n\t\t\t// eslint-disable-next-line perfectionist/sort-objects\r\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\r\n\r\n\t\t\theaders: resolveHeaders({ auth: options.auth, baseHeaders, body, headers }),\r\n\r\n\t\t\t...restOfBaseFetchConfig,\r\n\t\t\t...restOfFetchConfig,\r\n\t\t} satisfies RequestInit;\r\n\r\n\t\t// prettier-ignore\r\n\t\tconst shouldHaveRequestKey = options.dedupeStrategy === \"cancel\" || options.dedupeStrategy === \"defer\";\r\n\r\n\t\tconst requestKey =\r\n\t\t\toptions.requestKey ??\r\n\t\t\t(shouldHaveRequestKey\r\n\t\t\t\t? generateRequestKey(fullUrl, { ...defaultRequestOptions, ...options })\r\n\t\t\t\t: null);\r\n\r\n\t\t// == This is required to leave the smallest window of time for the cache to be updated with the last request info, if all requests with the same key start at the same time\r\n\t\tif (requestKey != null) {\r\n\t\t\tawait waitUntil(0.1);\r\n\t\t}\r\n\r\n\t\t// == This ensures cache operations only occur when key is available\r\n\t\tconst requestInfoCacheOrNull = requestKey ? requestInfoCache : null;\r\n\r\n\t\tconst prevRequestInfo = requestInfoCacheOrNull?.get(requestKey);\r\n\r\n\t\tif (prevRequestInfo && options.dedupeStrategy === \"cancel\") {\r\n\t\t\tconst reason = new DOMException(\r\n\t\t\t\t`Request aborted as another request to the endpoint: ${url}, with the same request options was initiated.`,\r\n\t\t\t\t\"AbortError\"\r\n\t\t\t);\r\n\r\n\t\t\tprevRequestInfo.controller.abort(reason);\r\n\t\t}\r\n\r\n\t\tconst newFetchController = new AbortController();\r\n\r\n\t\tconst timeoutSignal = options.timeout != null ? createTimeoutSignal(options.timeout) : null;\r\n\r\n\t\tconst combinedSignal = createCombinedSignal(newFetchController.signal, timeoutSignal, signal);\r\n\r\n\t\tconst requestInit = {\r\n\t\t\tsignal: combinedSignal,\r\n\t\t\t...defaultRequestOptions,\r\n\t\t} satisfies RequestInit;\r\n\r\n\t\tconst request = {\r\n\t\t\turl: fullUrl,\r\n\t\t\t...requestInit,\r\n\t\t} satisfies RequestOptions;\r\n\r\n\t\ttry {\r\n\t\t\tawait executeInterceptors(options.onRequest?.({ options, request }));\r\n\r\n\t\t\t// == Incase options.auth was updated in the request interceptor\r\n\t\t\trequestInit.headers = resolveHeaders({\r\n\t\t\t\tauth: options.auth,\r\n\t\t\t\tbaseHeaders,\r\n\t\t\t\tbody: request.body,\r\n\t\t\t\theaders: request.headers,\r\n\t\t\t});\r\n\r\n\t\t\trequest.headers = requestInit.headers;\r\n\r\n\t\t\tconst shouldUsePromiseFromCache = prevRequestInfo && options.dedupeStrategy === \"defer\";\r\n\r\n\t\t\tconst responsePromise = shouldUsePromiseFromCache\r\n\t\t\t\t? prevRequestInfo.responsePromise\r\n\t\t\t\t: fetch(fullUrl, requestInit);\r\n\r\n\t\t\trequestInfoCacheOrNull?.set(requestKey, { controller: newFetchController, responsePromise });\r\n\r\n\t\t\tconst response = await responsePromise;\r\n\r\n\t\t\tconst shouldRetry =\r\n\t\t\t\t!response.ok &&\r\n\t\t\t\t!combinedSignal.aborted &&\r\n\t\t\t\toptions.retries > 0 &&\r\n\t\t\t\toptions.retryCodes.includes(response.status) &&\r\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\r\n\r\n\t\t\tif (shouldRetry) {\r\n\t\t\t\tawait waitUntil(options.retryDelay);\r\n\r\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\r\n\t\t\t}\r\n\r\n\t\t\t// == Also clone response when dedupeStrategy is set to \"defer\", to avoid error thrown from reading response.(whatever) more than once\r\n\t\t\t// == Also clone response when resultMode is set to \"onlyResponse\", to avoid error thrown from reading response.(whatever) more than once\r\n\t\t\tconst shouldCloneResponse =\r\n\t\t\t\toptions.dedupeStrategy === \"defer\" ||\r\n\t\t\t\toptions.resultMode === \"onlyResponse\" ||\r\n\t\t\t\toptions.shouldCloneResponse;\r\n\r\n\t\t\tif (!response.ok) {\r\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\r\n\t\t\t\t\tshouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\toptions.responseType,\r\n\t\t\t\t\toptions.responseParser\r\n\t\t\t\t);\r\n\r\n\t\t\t\t// == Pushing all error handling responsibilities to the catch block\r\n\t\t\t\tthrow new HTTPError({\r\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\r\n\t\t\t\t\terrorData,\r\n\t\t\t\t\tresponse,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tconst successData = await getResponseData<TData>(\r\n\t\t\t\tshouldCloneResponse ? response.clone() : response,\r\n\t\t\t\toptions.responseType,\r\n\t\t\t\toptions.responseParser\r\n\t\t\t);\r\n\r\n\t\t\tconst validSuccessData = options.responseValidator\r\n\t\t\t\t? options.responseValidator(successData)\r\n\t\t\t\t: successData;\r\n\r\n\t\t\tawait executeInterceptors(\r\n\t\t\t\toptions.onSuccess?.({\r\n\t\t\t\t\tdata: validSuccessData,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t}),\r\n\r\n\t\t\t\toptions.onResponse?.({\r\n\t\t\t\t\tdata: validSuccessData,\r\n\t\t\t\t\terrorData: null,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\treturn resolveSuccessResult<CallApiResult>({\r\n\t\t\t\tresponse,\r\n\t\t\t\tresultMode: options.resultMode,\r\n\t\t\t\tsuccessData: validSuccessData,\r\n\t\t\t});\r\n\r\n\t\t\t// == Exhaustive Error handling\r\n\t\t} catch (error) {\r\n\t\t\tconst { generalErrorResult, resolveCustomErrorInfo } = resolveErrorResult<CallApiResult>({\r\n\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\r\n\t\t\t\terror,\r\n\t\t\t\tresultMode: options.resultMode,\r\n\t\t\t});\r\n\r\n\t\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\r\n\t\t\t\t? options.throwOnError({\r\n\t\t\t\t\t\terror: (generalErrorResult as { error: never }).error,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t})\r\n\t\t\t\t: options.throwOnError;\r\n\r\n\t\t\tif (shouldThrowOnError) {\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\r\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\r\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\r\n\r\n\t\t\t\tconsole.error(`${error.name}:`, message);\r\n\r\n\t\t\t\treturn resolveCustomErrorInfo({ message });\r\n\t\t\t}\r\n\r\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\r\n\t\t\t\tconst { message, name } = error;\r\n\r\n\t\t\t\tconsole.error(`${name}:`, message);\r\n\r\n\t\t\t\treturn generalErrorResult;\r\n\t\t\t}\r\n\r\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\r\n\t\t\t\tconst { errorData, response } = error;\r\n\r\n\t\t\t\tawait executeInterceptors(\r\n\t\t\t\t\toptions.onResponseError?.({\r\n\t\t\t\t\t\terrorData,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t}),\r\n\r\n\t\t\t\t\toptions.onResponse?.({\r\n\t\t\t\t\t\tdata: null,\r\n\t\t\t\t\t\terrorData,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t}),\r\n\r\n\t\t\t\t\t// == Also call the onError interceptor\r\n\t\t\t\t\toptions.onError?.({\r\n\t\t\t\t\t\terror,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t})\r\n\t\t\t\t);\r\n\r\n\t\t\t\treturn generalErrorResult;\r\n\t\t\t}\r\n\r\n\t\t\tawait executeInterceptors(\r\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\r\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request }),\r\n\r\n\t\t\t\t// == Also call the onError interceptor\r\n\t\t\t\toptions.onError?.({\r\n\t\t\t\t\terror: (generalErrorResult as { error: never }).error,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: null,\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\treturn generalErrorResult;\r\n\r\n\t\t\t// == Removing the now unneeded AbortController from store\r\n\t\t} finally {\r\n\t\t\trequestInfoCacheOrNull?.delete(requestKey);\r\n\t\t}\r\n\t};\r\n\r\n\tcallApi.create = createFetchClient;\r\n\r\n\treturn callApi;\r\n};\r\n\r\nexport const callApi = createFetchClient();\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/polyfills.ts","../../src/createFetchClient.ts"],"names":["callApi"],"mappings":"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","file":"index.js","sourcesContent":["// prettier-ignore\nexport const createCombinedSignal = (...signals: Array<AbortSignal | null | undefined>) => AbortSignal.any(signals.filter(Boolean));\n\nexport const createTimeoutSignal = (milliseconds: number) => AbortSignal.timeout(milliseconds);\n","import type {\r\n\tBaseCallApiConfig,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tGetCallApiResult,\r\n\tInterceptorUnion,\r\n\tRequestOptions,\r\n\tResultModeUnion,\r\n} from \"./types\";\r\nimport {\r\n\tHTTPError,\r\n\tdefaultRetryCodes,\r\n\tdefaultRetryMethods,\r\n\texecuteInterceptors,\r\n\tgenerateRequestKey,\r\n\tgetResponseData,\r\n\thandleInterceptorsMerge,\r\n\tisHTTPErrorInstance,\r\n\tmergeUrlWithParamsAndQuery,\r\n\tresolveErrorResult,\r\n\tresolveHeaders,\r\n\tresolveSuccessResult,\r\n\tsplitBaseConfig,\r\n\tsplitConfig,\r\n\twaitUntil,\r\n} from \"./utils/common\";\r\nimport { createCombinedSignal, createTimeoutSignal } from \"./utils/polyfills\";\r\nimport { isFunction, isObject } from \"./utils/typeof\";\r\n\r\nexport const createFetchClient = <\r\n\tTBaseData,\r\n\tTBaseErrorData = unknown,\r\n\tTBaseResultMode extends ResultModeUnion = ResultModeUnion,\r\n>(\r\n\tbaseConfig: BaseCallApiConfig<TBaseData, TBaseErrorData, TBaseResultMode> = {}\r\n) => {\r\n\tconst [baseFetchConfig, baseExtraOptions] = splitBaseConfig(baseConfig);\r\n\r\n\tconst {\r\n\t\tbody: baseBody,\r\n\t\theaders: baseHeaders,\r\n\t\tsignal: baseSignal,\r\n\t\t...restOfBaseFetchConfig\r\n\t} = baseFetchConfig;\r\n\r\n\tconst {\r\n\t\tonError: onBaseError,\r\n\t\tonRequest: onBaseRequest,\r\n\t\tonRequestError: onBaseRequestError,\r\n\t\tonResponse: onBaseResponse,\r\n\t\tonResponseError: onBaseResponseError,\r\n\t\tonSuccess: onBaseSuccess,\r\n\t\t...restOfBaseExtraOptions\r\n\t} = baseExtraOptions;\r\n\r\n\tconst requestInfoCache = new Map<\r\n\t\tstring | null,\r\n\t\t{ controller: AbortController; responsePromise: Promise<Response> }\r\n\t>();\r\n\r\n\tconst callApi = async <\r\n\t\tTData = TBaseData,\r\n\t\tTErrorData = TBaseErrorData,\r\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\r\n\t>(\r\n\t\turl: string,\r\n\t\tconfig: CallApiConfig<TData, TErrorData, TResultMode> = {}\r\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\r\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\r\n\r\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config);\r\n\r\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\r\n\r\n\t\t// prettier-ignore\r\n\t\tconst {\r\n\t\t\tonError,\r\n\t\t\tonRequest,\r\n\t\t\tonRequestError,\r\n\t\t\tonResponse,\r\n\t\t\tonResponseError,\r\n\t\t\tonSuccess,\r\n\t\t\t...restOfExtraOptions\r\n\t\t} = extraOptions;\r\n\r\n\t\t// == Default Extra Options\r\n\t\tconst defaultOptions = {\r\n\t\t\tbaseURL: \"\",\r\n\t\t\tbodySerializer: JSON.stringify,\r\n\t\t\tdedupeStrategy: \"cancel\",\r\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\r\n\t\t\tmergedInterceptorsExecutionMode: \"parallel\",\r\n\t\t\tmergeInterceptors: true,\r\n\t\t\tresponseType: \"json\",\r\n\t\t\tresultMode: \"all\",\r\n\t\t\tretries: 0,\r\n\t\t\tretryCodes: defaultRetryCodes,\r\n\t\t\tretryDelay: 0,\r\n\t\t\tretryMethods: defaultRetryMethods,\r\n\r\n\t\t\t...restOfBaseExtraOptions,\r\n\t\t\t...restOfExtraOptions,\r\n\t\t} satisfies Omit<CallApiExtraOptions, InterceptorUnion>;\r\n\r\n\t\tconst interceptors = {\r\n\t\t\tonError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseError,\r\n\t\t\t\tonError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonRequest: handleInterceptorsMerge(\r\n\t\t\t\tonBaseRequest,\r\n\t\t\t\tonRequest,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonRequestError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseRequestError,\r\n\t\t\t\tonRequestError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonResponse: handleInterceptorsMerge(\r\n\t\t\t\tonBaseResponse,\r\n\t\t\t\tonResponse,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonResponseError: handleInterceptorsMerge(\r\n\t\t\t\tonBaseResponseError,\r\n\t\t\t\tonResponseError,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t\tonSuccess: handleInterceptorsMerge(\r\n\t\t\t\tonBaseSuccess,\r\n\t\t\t\tonSuccess,\r\n\t\t\t\tdefaultOptions.mergeInterceptors,\r\n\t\t\t\tdefaultOptions.mergedInterceptorsExecutionMode\r\n\t\t\t),\r\n\t\t} satisfies Pick<CallApiExtraOptions, InterceptorUnion>;\r\n\r\n\t\tconst options = {\r\n\t\t\t...interceptors,\r\n\t\t\t...defaultOptions,\r\n\t\t};\r\n\r\n\t\tconst fullUrl = `${options.baseURL}${mergeUrlWithParamsAndQuery(url, options.params, options.query)}`;\r\n\r\n\t\t// == Default Request Init\r\n\t\tconst defaultRequestOptions = {\r\n\t\t\tmethod: \"GET\",\r\n\t\t\t// eslint-disable-next-line perfectionist/sort-objects\r\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\r\n\r\n\t\t\theaders: resolveHeaders({ auth: options.auth, baseHeaders, body, headers }),\r\n\r\n\t\t\t...restOfBaseFetchConfig,\r\n\t\t\t...restOfFetchConfig,\r\n\t\t} satisfies RequestInit;\r\n\r\n\t\t// prettier-ignore\r\n\t\tconst shouldHaveRequestKey = options.dedupeStrategy === \"cancel\" || options.dedupeStrategy === \"defer\";\r\n\r\n\t\tconst requestKey =\r\n\t\t\toptions.requestKey ??\r\n\t\t\t(shouldHaveRequestKey\r\n\t\t\t\t? generateRequestKey(fullUrl, { ...defaultRequestOptions, ...options })\r\n\t\t\t\t: null);\r\n\r\n\t\t// == This is required to leave the smallest window of time for the cache to be updated with the last request info, if all requests with the same key start at the same time\r\n\t\tif (requestKey != null) {\r\n\t\t\tawait waitUntil(0.1);\r\n\t\t}\r\n\r\n\t\t// == This ensures cache operations only occur when key is available\r\n\t\tconst requestInfoCacheOrNull = requestKey ? requestInfoCache : null;\r\n\r\n\t\tconst prevRequestInfo = requestInfoCacheOrNull?.get(requestKey);\r\n\r\n\t\tif (prevRequestInfo && options.dedupeStrategy === \"cancel\") {\r\n\t\t\tconst reason = new DOMException(\r\n\t\t\t\t`Request aborted as another request to the endpoint: ${url}, with the same request options was initiated.`,\r\n\t\t\t\t\"AbortError\"\r\n\t\t\t);\r\n\r\n\t\t\tprevRequestInfo.controller.abort(reason);\r\n\t\t}\r\n\r\n\t\tconst newFetchController = new AbortController();\r\n\r\n\t\tconst timeoutSignal = options.timeout != null ? createTimeoutSignal(options.timeout) : null;\r\n\r\n\t\tconst combinedSignal = createCombinedSignal(newFetchController.signal, timeoutSignal, signal);\r\n\r\n\t\tconst requestInit = {\r\n\t\t\tsignal: combinedSignal,\r\n\t\t\t...defaultRequestOptions,\r\n\t\t} satisfies RequestInit;\r\n\r\n\t\tconst request = {\r\n\t\t\turl: fullUrl,\r\n\t\t\t...requestInit,\r\n\t\t} satisfies RequestOptions;\r\n\r\n\t\ttry {\r\n\t\t\tawait executeInterceptors(options.onRequest?.({ options, request }));\r\n\r\n\t\t\t// == Incase options.auth was updated in the request interceptor\r\n\t\t\trequestInit.headers = resolveHeaders({\r\n\t\t\t\tauth: options.auth,\r\n\t\t\t\tbaseHeaders,\r\n\t\t\t\tbody: request.body,\r\n\t\t\t\theaders: request.headers,\r\n\t\t\t});\r\n\r\n\t\t\trequest.headers = requestInit.headers;\r\n\r\n\t\t\tconst shouldUsePromiseFromCache = prevRequestInfo && options.dedupeStrategy === \"defer\";\r\n\r\n\t\t\tconst responsePromise = shouldUsePromiseFromCache\r\n\t\t\t\t? prevRequestInfo.responsePromise\r\n\t\t\t\t: fetch(fullUrl, requestInit);\r\n\r\n\t\t\trequestInfoCacheOrNull?.set(requestKey, { controller: newFetchController, responsePromise });\r\n\r\n\t\t\tconst response = await responsePromise;\r\n\r\n\t\t\tconst shouldRetry =\r\n\t\t\t\t!response.ok &&\r\n\t\t\t\t!combinedSignal.aborted &&\r\n\t\t\t\toptions.retries > 0 &&\r\n\t\t\t\toptions.retryCodes.includes(response.status) &&\r\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\r\n\r\n\t\t\tif (shouldRetry) {\r\n\t\t\t\tawait waitUntil(options.retryDelay);\r\n\r\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\r\n\t\t\t}\r\n\r\n\t\t\t// == Also clone response when dedupeStrategy is set to \"defer\", to avoid error thrown from reading response.(whatever) more than once\r\n\t\t\t// == Also clone response when resultMode is set to \"onlyResponse\", to avoid error thrown from reading response.(whatever) more than once\r\n\t\t\tconst shouldCloneResponse =\r\n\t\t\t\toptions.dedupeStrategy === \"defer\" ||\r\n\t\t\t\toptions.resultMode === \"onlyResponse\" ||\r\n\t\t\t\toptions.shouldCloneResponse;\r\n\r\n\t\t\tif (!response.ok) {\r\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\r\n\t\t\t\t\tshouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\toptions.responseType,\r\n\t\t\t\t\toptions.responseParser\r\n\t\t\t\t);\r\n\r\n\t\t\t\t// == Pushing all error handling responsibilities to the catch block\r\n\t\t\t\tthrow new HTTPError({\r\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\r\n\t\t\t\t\terrorData,\r\n\t\t\t\t\tresponse,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tconst successData = await getResponseData<TData>(\r\n\t\t\t\tshouldCloneResponse ? response.clone() : response,\r\n\t\t\t\toptions.responseType,\r\n\t\t\t\toptions.responseParser\r\n\t\t\t);\r\n\r\n\t\t\tconst validSuccessData = options.responseValidator\r\n\t\t\t\t? options.responseValidator(successData)\r\n\t\t\t\t: successData;\r\n\r\n\t\t\tawait executeInterceptors(\r\n\t\t\t\toptions.onSuccess?.({\r\n\t\t\t\t\tdata: validSuccessData,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t}),\r\n\r\n\t\t\t\toptions.onResponse?.({\r\n\t\t\t\t\tdata: validSuccessData,\r\n\t\t\t\t\terrorData: null,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\treturn resolveSuccessResult<CallApiResult>({\r\n\t\t\t\tresponse,\r\n\t\t\t\tresultMode: options.resultMode,\r\n\t\t\t\tsuccessData: validSuccessData,\r\n\t\t\t});\r\n\r\n\t\t\t// == Exhaustive Error handling\r\n\t\t} catch (error) {\r\n\t\t\tconst { apiDetails, generalErrorResult, resolveCustomErrorInfo } =\r\n\t\t\t\tresolveErrorResult<CallApiResult>({\r\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\r\n\t\t\t\t\terror,\r\n\t\t\t\t\tresultMode: options.resultMode,\r\n\t\t\t\t});\r\n\r\n\t\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\r\n\t\t\t\t? options.throwOnError({\r\n\t\t\t\t\t\terror: apiDetails.error,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t})\r\n\t\t\t\t: options.throwOnError;\r\n\r\n\t\t\t// eslint-disable-next-line unicorn/consistent-function-scoping\r\n\t\t\tconst handleThrowOnError = () => {\r\n\t\t\t\tif (!shouldThrowOnError) return;\r\n\r\n\t\t\t\tthrow apiDetails.error as Error;\r\n\t\t\t};\r\n\r\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\r\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\r\n\r\n\t\t\t\tconsole.error(`${error.name}:`, message);\r\n\r\n\t\t\t\thandleThrowOnError();\r\n\r\n\t\t\t\treturn resolveCustomErrorInfo({ message });\r\n\t\t\t}\r\n\r\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\r\n\t\t\t\tconst { message, name } = error;\r\n\r\n\t\t\t\tconsole.error(`${name}:`, message);\r\n\r\n\t\t\t\thandleThrowOnError();\r\n\r\n\t\t\t\treturn generalErrorResult;\r\n\t\t\t}\r\n\r\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\r\n\t\t\t\tconst { errorData, response } = error;\r\n\r\n\t\t\t\tawait executeInterceptors(\r\n\t\t\t\t\toptions.onResponseError?.({\r\n\t\t\t\t\t\terrorData,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t}),\r\n\r\n\t\t\t\t\toptions.onResponse?.({\r\n\t\t\t\t\t\tdata: null,\r\n\t\t\t\t\t\terrorData,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t}),\r\n\r\n\t\t\t\t\t// == Also call the onError interceptor\r\n\t\t\t\t\toptions.onError?.({\r\n\t\t\t\t\t\terror,\r\n\t\t\t\t\t\toptions,\r\n\t\t\t\t\t\trequest,\r\n\t\t\t\t\t\tresponse: options.shouldCloneResponse ? response.clone() : response,\r\n\t\t\t\t\t})\r\n\t\t\t\t);\r\n\r\n\t\t\t\thandleThrowOnError();\r\n\r\n\t\t\t\treturn generalErrorResult;\r\n\t\t\t}\r\n\r\n\t\t\tawait executeInterceptors(\r\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\r\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request }),\r\n\r\n\t\t\t\t// == Also call the onError interceptor\r\n\t\t\t\toptions.onError?.({\r\n\t\t\t\t\terror: (generalErrorResult as { error: never }).error,\r\n\t\t\t\t\toptions,\r\n\t\t\t\t\trequest,\r\n\t\t\t\t\tresponse: null,\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\thandleThrowOnError();\r\n\r\n\t\t\treturn generalErrorResult;\r\n\r\n\t\t\t// == Removing the now unneeded AbortController from store\r\n\t\t} finally {\r\n\t\t\trequestInfoCacheOrNull?.delete(requestKey);\r\n\t\t}\r\n\t};\r\n\r\n\tcallApi.create = createFetchClient;\r\n\r\n\treturn callApi;\r\n};\r\n\r\nexport const callApi = createFetchClient();\r\n"]}
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{HTTPError,isHTTPError,isHTTPErrorInstance,toQueryString}from"../chunk-
|
|
1
|
+
export{HTTPError,isHTTPError,isHTTPErrorInstance,toQueryString}from"../chunk-O3QDH76S.js";//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zayne-labs/callapi",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.22",
|
|
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",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"size-limit": [
|
|
61
61
|
{
|
|
62
62
|
"path": "./src/index.ts",
|
|
63
|
-
"limit": "2.
|
|
63
|
+
"limit": "2.7 kb"
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"path": "./src/utils/index.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/typeof.ts","../../src/utils/common.ts"],"names":[],"mappings":"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","file":"chunk-LJI67ND4.js","sourcesContent":["import type { AnyFunction } from \"./type-helpers\";\r\n\r\nexport const isArray = <TArrayItem>(value: unknown): value is TArrayItem[] => Array.isArray(value);\r\n\r\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\r\n\treturn typeof value === \"object\" && value !== null && !(value instanceof FormData) && !isArray(value);\r\n};\r\n\r\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\r\n\ttypeof value === \"function\";\r\n\r\nexport const isQueryString = (value: unknown): value is string => isString(value) && value.includes(\"=\");\r\n\r\nexport const isString = (value: unknown) => typeof value === \"string\";\r\n","import type {\r\n\tApiErrorVariant,\r\n\tBaseCallApiConfig,\r\n\tBaseCallApiExtraOptions,\r\n\tCallApiConfig,\r\n\tCallApiExtraOptions,\r\n\tPossibleErrorNames,\r\n\tResultModeMap,\r\n} from \"../types\";\r\nimport type { AnyFunction, Awaitable } from \"./type-helpers\";\r\nimport { isArray, isObject, isQueryString, isString } from \"./typeof\";\r\n\r\n// prettier-ignore\r\nexport const generateRequestKey = (url: string, config: Record<string, unknown>) => `${url} ${ampersand} ${JSON.stringify(config)}`;\r\n\r\ntype ToQueryStringFn = {\r\n\t(params: CallApiConfig[\"query\"]): string | null;\r\n\t(params: Required<CallApiConfig>[\"query\"]): string;\r\n};\r\n\r\nexport const toQueryString: ToQueryStringFn = (params) => {\r\n\tif (!params) {\r\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\r\n\r\n\t\treturn null as never;\r\n\t}\r\n\r\n\treturn new URLSearchParams(params as Record<string, string>).toString();\r\n};\r\n\r\nconst slash = \"/\";\r\nconst column = \":\";\r\nconst mergeUrlWithParams = (url: string, params: CallApiExtraOptions[\"params\"]) => {\r\n\tif (!params) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tlet newUrl = url;\r\n\r\n\tif (isArray(params)) {\r\n\t\tconst matchedParamArray = newUrl\r\n\t\t\t.split(slash)\r\n\t\t\t.filter((matchedParam) => matchedParam.startsWith(column));\r\n\r\n\t\tfor (const [index, matchedParam] of matchedParamArray.entries()) {\r\n\t\t\tconst param = params[index] as string;\r\n\t\t\tnewUrl = newUrl.replace(matchedParam, param);\r\n\t\t}\r\n\r\n\t\treturn newUrl;\r\n\t}\r\n\r\n\tfor (const [key, value] of Object.entries(params)) {\r\n\t\tnewUrl = newUrl.replace(`:${key}`, String(value));\r\n\t}\r\n\r\n\treturn newUrl;\r\n};\r\n\r\nconst questionMark = \"?\";\r\nconst ampersand = \"&\";\r\n\r\nconst mergeUrlWithQuery = (url: string, query: CallApiConfig[\"query\"]): string => {\r\n\tif (!query) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tconst queryString = toQueryString(query);\r\n\r\n\tif (queryString?.length === 0) {\r\n\t\treturn url;\r\n\t}\r\n\r\n\tif (url.endsWith(questionMark)) {\r\n\t\treturn `${url}${queryString}`;\r\n\t}\r\n\r\n\tif (url.includes(questionMark)) {\r\n\t\treturn `${url}${ampersand}${queryString}`;\r\n\t}\r\n\r\n\treturn `${url}${questionMark}${queryString}`;\r\n};\r\n\r\nexport const mergeUrlWithParamsAndQuery = (\r\n\turl: string,\r\n\tparams: CallApiExtraOptions[\"params\"],\r\n\tquery: CallApiExtraOptions[\"query\"]\r\n) => {\r\n\tconst urlWithMergedParams = mergeUrlWithParams(url, params);\r\n\r\n\treturn mergeUrlWithQuery(urlWithMergedParams, query);\r\n};\r\n\r\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\r\n\tif (!headers || isObject(headers)) {\r\n\t\treturn headers;\r\n\t}\r\n\r\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\r\n};\r\n\r\nexport const resolveHeaders = (options: {\r\n\tauth: CallApiConfig[\"auth\"];\r\n\tbaseHeaders: CallApiConfig[\"headers\"];\r\n\tbody: CallApiConfig[\"body\"];\r\n\theaders: CallApiConfig[\"headers\"];\r\n}) => {\r\n\tconst { auth, baseHeaders, body, headers } = options;\r\n\r\n\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing\r\n\tconst shouldResolveHeaders = baseHeaders || headers || body || auth;\r\n\r\n\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\r\n\t// - headers are provided\r\n\t// - The body is an object\r\n\t// - The auth option is provided\r\n\tif (!shouldResolveHeaders) return;\r\n\r\n\treturn {\r\n\t\t...(isObject(body) && {\r\n\t\t\tAccept: \"application/json\",\r\n\t\t\t\"Content-Type\": \"application/json\",\r\n\t\t}),\r\n\t\t...(isQueryString(body) && {\r\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\r\n\t\t}),\r\n\t\t...((isString(auth) || auth === null) && {\r\n\t\t\tAuthorization: `Bearer ${auth}`,\r\n\t\t}),\r\n\t\t...(isObject(auth) && {\r\n\t\t\tAuthorization: \"bearer\" in auth ? `Bearer ${auth.bearer}` : `Token ${auth.token}`,\r\n\t\t}),\r\n\t\t...objectifyHeaders(baseHeaders),\r\n\t\t...objectifyHeaders(headers),\r\n\t};\r\n};\r\n\r\nconst retryCodesLookup = {\r\n\t408: \"Request Timeout\",\r\n\t409: \"Conflict\",\r\n\t425: \"Too Early\",\r\n\t429: \"Too Many Requests\",\r\n\t500: \"Internal Server Error\",\r\n\t502: \"Bad Gateway\",\r\n\t503: \"Service Unavailable\",\r\n\t504: \"Gateway Timeout\",\r\n};\r\n\r\nexport const defaultRetryCodes: Required<BaseCallApiConfig>[\"retryCodes\"] =\r\n\tObject.keys(retryCodesLookup).map(Number);\r\n\r\nexport const defaultRetryMethods: Required<BaseCallApiConfig>[\"retryMethods\"] = [\"GET\"];\r\n\r\nexport const fetchSpecificKeys = [\r\n\t\"body\",\r\n\t\"integrity\",\r\n\t\"method\",\r\n\t\"headers\",\r\n\t\"signal\",\r\n\t\"cache\",\r\n\t\"redirect\",\r\n\t\"window\",\r\n\t\"credentials\",\r\n\t\"keepalive\",\r\n\t\"referrer\",\r\n\t\"priority\",\r\n\t\"mode\",\r\n\t\"referrerPolicy\",\r\n] satisfies Array<keyof RequestInit>;\r\n\r\nexport const omitKeys = <\r\n\tTObject extends Record<string, unknown>,\r\n\tconst TOmitArray extends Array<keyof TObject>,\r\n>(\r\n\tinitialObject: TObject,\r\n\tkeysToOmit: TOmitArray\r\n) => {\r\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\r\n\t\t([key]) => !keysToOmit.includes(key)\r\n\t);\r\n\r\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\r\n\r\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\r\n};\r\n\r\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\r\n\tinitialObject: TObject,\r\n\tkeysToPick: TPickArray\r\n) => {\r\n\tconst keysToPickSet = new Set(keysToPick);\r\n\r\n\tconst arrayFromInitObject = Object.entries(initialObject);\r\n\r\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\r\n\r\n\tconst updatedObject = Object.fromEntries(filteredArray);\r\n\r\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\r\n};\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitBaseConfig = (baseConfig: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(baseConfig, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(baseConfig, [...fetchSpecificKeys, \"requestKey\"] satisfies Array<\r\n\t\t\tkeyof CallApiConfig\r\n\t\t>) as BaseCallApiExtraOptions,\r\n\t] as const;\r\n\r\n// eslint-disable-next-line ts-eslint/no-explicit-any\r\nexport const splitConfig = (config: Record<string, any>) =>\r\n\t[\r\n\t\tpickKeys(config, fetchSpecificKeys) as RequestInit,\r\n\t\tomitKeys(config, fetchSpecificKeys) as CallApiExtraOptions,\r\n\t] as const;\r\n\r\nexport const handleInterceptorsMerge = <\r\n\tTBaseInterceptor extends AnyFunction<Awaitable<void>> | Array<AnyFunction<Awaitable<void>>>,\r\n\tTInterceptor extends AnyFunction<Awaitable<void>>,\r\n>(\r\n\tbaseInterceptor: TBaseInterceptor | undefined,\r\n\tinterceptor: TInterceptor | undefined,\r\n\tmergeInterceptors: CallApiExtraOptions[\"mergeInterceptors\"],\r\n\tmergedInterceptorsExecutionMode: CallApiExtraOptions[\"mergedInterceptorsExecutionMode\"]\r\n) => {\r\n\tif (isArray(baseInterceptor) && mergeInterceptors) {\r\n\t\tconst mergedInterceptor = async (ctx: Record<string, unknown>) => {\r\n\t\t\tconst interceptorArray = [...baseInterceptor, ...(interceptor ? [interceptor] : [])] as Array<\r\n\t\t\t\tAnyFunction<Awaitable<void>>\r\n\t\t\t>;\r\n\r\n\t\t\tconst uniqueInterceptorArray = [...new Set(interceptorArray)];\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"sequential\") {\r\n\t\t\t\tfor (const uniqueInterceptor of uniqueInterceptorArray) {\r\n\t\t\t\t\t// eslint-disable-next-line no-await-in-loop\r\n\t\t\t\t\tawait uniqueInterceptor(ctx);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (mergedInterceptorsExecutionMode === \"parallel\") {\r\n\t\t\t\tawait Promise.all(uniqueInterceptorArray.map((uniqueInterceptor) => uniqueInterceptor(ctx)));\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\treturn mergedInterceptor;\r\n\t}\r\n\r\n\treturn interceptor ?? (baseInterceptor as typeof interceptor);\r\n};\r\n\r\nexport const handleResponseType = <TResponse>(\r\n\tresponse: Response,\r\n\tparser?: Required<CallApiExtraOptions>[\"responseParser\"]\r\n) => ({\r\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\r\n\tblob: () => response.blob() as Promise<TResponse>,\r\n\tformData: () => response.formData() as Promise<TResponse>,\r\n\tjson: async () => {\r\n\t\tif (parser) {\r\n\t\t\treturn parser(await response.text());\r\n\t\t}\r\n\r\n\t\treturn response.json() as Promise<TResponse>;\r\n\t},\r\n\ttext: () => response.text() as Promise<TResponse>,\r\n});\r\n\r\nexport const getResponseData = <TResponse>(\r\n\tresponse: Response,\r\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\r\n\tparser: CallApiExtraOptions[\"responseParser\"]\r\n) => {\r\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\r\n\r\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\r\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\r\n\t}\r\n\r\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\r\n};\r\n\r\ntype SuccessInfo = {\r\n\tresponse: Response;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n\tsuccessData: unknown;\r\n};\r\n\r\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\r\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\r\nexport const resolveSuccessResult = <CallApiResult>(info: SuccessInfo): CallApiResult => {\r\n\tconst { response, resultMode, successData } = info;\r\n\r\n\tconst apiDetails = {\r\n\t\tdata: successData,\r\n\t\terror: null,\r\n\t\tresponse,\r\n\t};\r\n\r\n\tif (!resultMode) {\r\n\t\treturn apiDetails as CallApiResult;\r\n\t}\r\n\r\n\treturn {\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode] as CallApiResult;\r\n};\r\n\r\ntype ErrorInfo = {\r\n\tdefaultErrorMessage: Required<CallApiExtraOptions>[\"defaultErrorMessage\"];\r\n\terror?: unknown;\r\n\tmessage?: string;\r\n\tresultMode: CallApiExtraOptions[\"resultMode\"];\r\n};\r\n\r\nexport const resolveErrorResult = <CallApiResult>(info: ErrorInfo) => {\r\n\tconst { defaultErrorMessage, error, message: customErrorMessage, resultMode } = info;\r\n\r\n\tlet apiDetails!: ResultModeMap[\"all\"];\r\n\r\n\tif (isHTTPErrorInstance(error)) {\r\n\t\tconst { errorData, message = defaultErrorMessage, name, response } = error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: { errorData, message, name },\r\n\t\t\tresponse,\r\n\t\t};\r\n\t}\r\n\r\n\tif (error) {\r\n\t\tconst { message, name } = error as Error;\r\n\r\n\t\tapiDetails = {\r\n\t\t\tdata: null,\r\n\t\t\terror: {\r\n\t\t\t\terrorData: error as Error,\r\n\t\t\t\tmessage: customErrorMessage ?? message,\r\n\t\t\t\tname: name as PossibleErrorNames,\r\n\t\t\t},\r\n\t\t\tresponse: null,\r\n\t\t};\r\n\t}\r\n\r\n\tconst generalErrorResult = ({\r\n\t\tall: apiDetails,\r\n\t\tonlyError: apiDetails.error,\r\n\t\tonlyResponse: apiDetails.response,\r\n\t\tonlySuccess: apiDetails.data,\r\n\t}[resultMode ?? \"all\"] ?? apiDetails) as CallApiResult;\r\n\r\n\t// prettier-ignore\r\n\tconst resolveCustomErrorInfo = ({ message }: Pick<ErrorInfo, \"message\">) => {\r\n\t\tconst errorResult = resolveErrorResult<CallApiResult>({ ...info, message });\r\n\r\n\t\treturn errorResult.generalErrorResult;\r\n\t};\r\n\r\n\treturn { generalErrorResult, resolveCustomErrorInfo };\r\n};\r\n\r\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\r\n\treturn isObject(error) && error.name === \"HTTPError\";\r\n};\r\n\r\ntype ErrorDetails<TErrorResponse> = {\r\n\tdefaultErrorMessage: string;\r\n\terrorData: TErrorResponse;\r\n\tresponse: Response;\r\n};\r\n\r\ntype ErrorOptions = {\r\n\tcause?: unknown;\r\n};\r\n\r\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\r\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\r\n\tisHTTPError = true;\r\n\r\n\toverride name = \"HTTPError\" as const;\r\n\r\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\r\n\r\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\r\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\r\n\r\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\r\n\r\n\t\tthis.errorData = errorData;\r\n\t\tthis.response = response;\r\n\r\n\t\tError.captureStackTrace(this, this.constructor);\r\n\t}\r\n}\r\n\r\nexport const isHTTPErrorInstance = <TErrorResponse>(\r\n\terror: unknown\r\n): error is HTTPError<TErrorResponse> => {\r\n\treturn (\r\n\t\t// prettier-ignore\r\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\r\n\t);\r\n};\r\n\r\nconst PromiseWithResolvers = () => {\r\n\tlet reject!: (reason?: unknown) => void;\r\n\tlet resolve!: (value: unknown) => void;\r\n\r\n\tconst promise = new Promise((res, rej) => {\r\n\t\tresolve = res;\r\n\t\treject = rej;\r\n\t});\r\n\r\n\treturn { promise, reject, resolve };\r\n};\r\n\r\nexport const waitUntil = (delay: number) => {\r\n\tif (delay === 0) return;\r\n\r\n\tconst { promise, resolve } = PromiseWithResolvers();\r\n\r\n\tsetTimeout(resolve, delay);\r\n\r\n\treturn promise;\r\n};\r\n\r\nexport const executeInterceptors = <TInterceptor extends Awaitable<void>>(\r\n\t...interceptors: TInterceptor[]\r\n) => Promise.all(interceptors);\r\n"]}
|