@zayne-labs/callapi 0.7.1 → 0.7.2
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-DDD_c4ys.d.cts → index-CoVUDAa-.d.cts} +4 -6
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +2 -2
- package/dist/cjs/utils/index.d.cts +1 -1
- package/dist/esm/{index-DDD_c4ys.d.ts → index-CoVUDAa-.d.ts} +4 -6
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -1
- package/package.json +7 -3
- package/LICENSE +0 -21
|
@@ -113,7 +113,7 @@ interface ExtraOptions<TData = unknown, TErrorData = unknown, TResultMode extend
|
|
|
113
113
|
* @description Interceptor to be called when an error occurs during the fetch request OR when an error response is received from the api
|
|
114
114
|
* It is basically a combination of `onRequestError` and `onResponseError` interceptors
|
|
115
115
|
*/
|
|
116
|
-
onError?: (
|
|
116
|
+
onError?: (errorContext: ErrorContext<TErrorData>) => Promise<void> | void;
|
|
117
117
|
/** @description Interceptor to be called just before the request is made, allowing for modifications or additional operations. */
|
|
118
118
|
onRequest?: (requestContext: {
|
|
119
119
|
options: ExtraOptions;
|
|
@@ -195,7 +195,7 @@ type ResponseErrorContext<TErrorData> = Prettify<{
|
|
|
195
195
|
request: $RequestOptions;
|
|
196
196
|
response: Response;
|
|
197
197
|
}>;
|
|
198
|
-
type ErrorContext<TErrorData> =
|
|
198
|
+
type ErrorContext<TErrorData> = {
|
|
199
199
|
error: Error;
|
|
200
200
|
errorData?: null;
|
|
201
201
|
options: ExtraOptions;
|
|
@@ -207,7 +207,7 @@ type ErrorContext<TErrorData> = Prettify<{
|
|
|
207
207
|
options: ExtraOptions;
|
|
208
208
|
request: $RequestOptions;
|
|
209
209
|
response: Response;
|
|
210
|
-
}
|
|
210
|
+
};
|
|
211
211
|
interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = "all"> extends Omit<RequestInit, "body" | "method">, ExtraOptions<TData, TErrorData, TResultMode> {
|
|
212
212
|
}
|
|
213
213
|
type BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = "all"> = FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode>;
|
|
@@ -216,9 +216,7 @@ type ApiSuccessVariant<TData> = {
|
|
|
216
216
|
error: null;
|
|
217
217
|
response: Response;
|
|
218
218
|
};
|
|
219
|
-
type PossibleErrorNames =
|
|
220
|
-
_: "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | "UnknownError";
|
|
221
|
-
}["_"];
|
|
219
|
+
type PossibleErrorNames = "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | "UnknownError";
|
|
222
220
|
type ApiErrorVariant<TErrorData> = {
|
|
223
221
|
data: null;
|
|
224
222
|
error: {
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,r=Object.defineProperty,t=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,n={};((e,t)=>{for(var o in t)r(e,o,{get:t[o],enumerable:!0})})(n,{callApi:()=>E,createFetchClient:()=>w}),module.exports=(e=n,((e,n,a,i)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let l of o(n))s.call(e,l)||l===a||r(e,l,{get:()=>n[l],enumerable:!(i=t(n,l))||i.enumerable});return e})(r({},"__esModule",{value:!0}),e));var a=e=>!("object"!=typeof e||null===e||e instanceof FormData||Array.isArray(e)),i=e=>"string"==typeof e,l=(e,r)=>{if(!r)return e;const t=(e=>e?new URLSearchParams(e).toString():(console.error("toQueryString:","No query params provided!"),null))(r);return e.endsWith("?")?`${e}${t}`:e.includes("?")?`${e}&${t}`:`${e}?${t}`},u=e=>{return!e||a(e)?e:Object.fromEntries((r=e,Array.isArray(r)?e:e.entries()));var r},c=Object.keys({408:"Request Timeout",409:"Conflict",425:"Too Early",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"}).map(Number),p=["GET"],d=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],y=(e,r)=>{const t=Object.entries(e).filter((([e])=>!r.includes(e)));return Object.fromEntries(t)},f=(e,r)=>{const t=new Set(r),o=Object.entries(e).filter((([e])=>t.has(e)));return Object.fromEntries(o)},m=e=>[f(e,d),y(e,d)],
|
|
1
|
+
"use strict";var e,r=Object.defineProperty,t=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,n={};((e,t)=>{for(var o in t)r(e,o,{get:t[o],enumerable:!0})})(n,{callApi:()=>E,createFetchClient:()=>w}),module.exports=(e=n,((e,n,a,i)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let l of o(n))s.call(e,l)||l===a||r(e,l,{get:()=>n[l],enumerable:!(i=t(n,l))||i.enumerable});return e})(r({},"__esModule",{value:!0}),e));var a=e=>!("object"!=typeof e||null===e||e instanceof FormData||Array.isArray(e)),i=e=>"string"==typeof e,l=(e,r)=>{if(!r)return e;const t=(e=>e?new URLSearchParams(e).toString():(console.error("toQueryString:","No query params provided!"),null))(r);return e.endsWith("?")?`${e}${t}`:e.includes("?")?`${e}&${t}`:`${e}?${t}`},u=e=>{return!e||a(e)?e:Object.fromEntries((r=e,Array.isArray(r)?e:e.entries()));var r},c=Object.keys({408:"Request Timeout",409:"Conflict",425:"Too Early",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"}).map(Number),p=["GET"],d=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],y=(e,r)=>{const t=Object.entries(e).filter((([e])=>!r.includes(e)));return Object.fromEntries(t)},f=(e,r)=>{const t=new Set(r),o=Object.entries(e).filter((([e])=>t.has(e)));return Object.fromEntries(o)},m=e=>[f(e,d),y(e,d)],b=(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]()},h=class extends Error{errorData;isHTTPError=!0;name="HTTPError";response;constructor(e,r){const{defaultErrorMessage:t,errorData:o,response:s}=e;super(o.message??t,r),this.errorData=o,this.response=s}},w=e=>{const r=new Map,[t,o]=m(e??{}),{body:s,headers:n,signal:d,...f}=t,E=async(e,t)=>{const[w,g]=m(t??{}),{body:R=s,headers:O,signal:D=d,...T}=w,q={baseURL:"",bodySerializer:JSON.stringify,cancelRedundantRequests:!0,defaultErrorMessage:"Failed to fetch data from server!",responseType:"json",retries:0,retryCodes:c,retryDelay:0,retryMethods:p,...o,...g},$={body:a(R)?q.bodySerializer(R):R,headers:n||O||q.auth||a(R)?{...a(R)&&{Accept:"application/json","Content-Type":"application/json"},...(j=R,"string"==typeof j&&j.includes("=")&&{"Content-Type":"application/x-www-form-urlencoded"}),...i(q.auth)&&{Authorization:`Bearer ${q.auth}`},...a(q.auth)&&{Authorization:"bearer"in q.auth?`Bearer ${q.auth.bearer}`:`Token ${q.auth.token}`},...u(n),...u(O)}:void 0,method:"GET",...f,...T};var j;const v=((e,r)=>`${e} | ${JSON.stringify(r??{})}`)(e,y({...$,...q},["onRequest","onResponse","onResponseError","onError","onRequestError"])),M=r.get(v);if(M&&q.cancelRedundantRequests){const r=new DOMException(`Request aborted as another request to this same endpoint: ${e}, with the same request options was initiated.`,"AbortError");M.abort(r)}const P=new AbortController;r.set(v,P);const A=q.timeout?AbortSignal.timeout(q.timeout):null,S=AbortSignal.any([P.signal,...A?[A]:[],...D?[D]:[]]),x={signal:S,...$};try{await(q.onRequest?.({options:q,request:x}));const r=await fetch(`${q.baseURL}${l(e,q.query)}`,x);if(!r.ok&&!S.aborted&&q.retries>0&&q.retryCodes.includes(r.status)&&q.retryMethods.includes(x.method))return await(e=>{if(0===e)return;const{promise:r,resolve:t}=Promise.withResolvers();return setTimeout(t,e),r})(q.retryDelay),await E(e,{...t,retries:q.retries-1});if(!r.ok){const e=await b(q.cloneResponse?r.clone():r,q.responseType,q.responseParser);throw new h({defaultErrorMessage:q.defaultErrorMessage,errorData:e,response:r})}const o=await b(q.cloneResponse?r.clone():r,q.responseType,q.responseParser),s=q.responseValidator?q.responseValidator(o):o;return await(q.onResponse?.({data:s,options:q,request:x,response:q.cloneResponse?r.clone():r})),(e=>{const{options:r,response:t,successData:o}=e,s={data:o,error:null,response:t};return r.resultMode&&"all"!==r.resultMode?{onlyError:s.error,onlyResponse:s.response,onlySuccess:s.data}[r.resultMode]:s})({options:q,response:r,successData:s})}catch(e){const r=(e=>{const{error:r,options:t}=e;return(e={})=>{const{errorData:o,message:s,response:n}=e;if("function"==typeof t.throwOnError?t.throwOnError(r):t.throwOnError)throw r;return{data:null,error:{errorData:o??r,message:s??r?.message??t.defaultErrorMessage,name:r?.name??"UnknownError"},response:n??null}}})({error:e,options:q});if(e instanceof DOMException&&"TimeoutError"===e.name){const t=`Request timed out after ${q.timeout}ms`;return console.error(`${e.name}:`,t),r({message:t})}if(e instanceof DOMException&&"AbortError"===e.name){const t=`Request aborted due to ${e.message}`;return console.error(`${e.name}:`,t),r({message:t})}if((e=>e instanceof h||a(e)&&"HTTPError"===e.name&&!0===e.isHTTPError)(e)){const{errorData:t,response:o}=e;return await Promise.all([q.onResponseError?.({errorData:t,options:q,request:x,response:q.cloneResponse?o.clone():o}),q.onError?.({error:null,errorData:t,options:q,request:x,response:o})]),r({errorData:t,message:t?.message,response:o})}return await Promise.all([q.onRequestError?.({error:e,options:q,request:x}),q.onError?.({error:e,errorData:null,options:q,request:x,response:null})]),r()}finally{r.delete(v)}};return E.create=w,E},E=w();//# sourceMappingURL=index.cjs.map
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/typeof.ts","../../src/utils/utils.ts","../../src/createFetchClient.ts"],"sourcesContent":["export { callApi, createFetchClient } from \"./createFetchClient\";\n\nexport type {\n\t$RequestOptions,\n\tExtraOptions,\n\tFetchConfig,\n\tResponseContext,\n\tResponseErrorContext,\n\tErrorContext,\n} from \"./types\";\n","import type { AnyFunction } from \"./type-helpers\";\n\nexport const isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn (\n\t\ttypeof value === \"object\" && value !== null && !(value instanceof FormData) && !Array.isArray(value)\n\t);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n\nexport const isString = (value: unknown) => typeof value === \"string\";\n\nexport const isQueryString = (value: unknown): value is string =>\n\ttypeof value === \"string\" && value.includes(\"=\");\n","import { isArray, isFunction, isObject } from \"../typeof\";\nimport type {\n\t$BaseRequestOptions,\n\t$RequestOptions,\n\tApiErrorVariant,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"../types\";\n\n// prettier-ignore\nexport const getRequestKey = <TConfig extends Record<string, unknown>>(url: string, config?: TConfig) => `${url} | ${JSON.stringify(config ?? {})}`;\n\ntype ToQueryStringFn = {\n\t(params: ExtraOptions[\"query\"]): null | string;\n\t(params: Required<ExtraOptions>[\"query\"]): string;\n};\n\nexport const toQueryString: ToQueryStringFn = (params) => {\n\tif (!params) {\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\n\n\t\treturn null as never;\n\t}\n\n\treturn new URLSearchParams(params as Record<string, string>).toString();\n};\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = toQueryString(params);\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\tif (url.includes(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nexport const omitKeys = <\n\tTObject extends Record<string, unknown>,\n\tconst TOmitArray extends Array<keyof TObject>,\n>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype data = {\n\toptions: ExtraOptions;\n\tresponse: Response;\n\tsuccessData: unknown;\n};\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = <CallApiResult>(info: data): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = {\n\t\tdata: successData,\n\t\terror: null,\n\t\tresponse,\n\t};\n\n\tif (!options.resultMode || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlyError: apiDetails.error,\n\t\tonlyResponse: apiDetails.response,\n\t\tonlySuccess: apiDetails.data,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const getResolveErrorResultFn = <CallApiResult>($info: {\n\terror?: unknown;\n\toptions: ExtraOptions;\n}) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t\tresponse?: Response;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\terrorData: errorData ?? error,\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t\tname: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\n\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\n\treturn isObject(error) && error.name === \"HTTPError\";\n};\n\ntype ErrorDetails<TErrorResponse> = {\n\tdefaultErrorMessage: string;\n\terrorData: TErrorResponse;\n\tresponse: Response;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\n\tisHTTPError = true;\n\n\toverride name = \"HTTPError\" as const;\n\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\n\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.errorData = errorData;\n\t\tthis.response = response;\n\t}\n}\n\n// prettier-ignore\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const waitUntil = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n","import { isObject, isQueryString, isString } from \"./typeof\";\nimport type {\n\t$RequestOptions,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultModeUnion,\n} from \"./types\";\nimport {\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetRequestKey,\n\tgetResolveErrorResultFn,\n\tgetResponseData,\n\tisHTTPErrorInstance,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tomitKeys,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twaitUntil,\n} from \"./utils/utils\";\n\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData = unknown,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\tbody: baseBody,\n\t\theaders: baseHeaders,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\n\n\t\t// == Default Extra Options\n\t\tconst options = {\n\t\t\tbaseURL: \"\",\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tcancelRedundantRequests: true,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tresponseType: \"json\",\n\t\t\tretries: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryDelay: 0,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\t// == Default Fetch Config\n\t\tconst defaultFetchOptions = {\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// - The auth option is provided\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || options.auth || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isQueryString(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\n\t\t\t// - headers are provided\n\t\t\t// - The body is an object\n\t\t\tmethod: \"GET\",\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\tconst requestKey = getRequestKey(\n\t\t\turl,\n\t\t\tomitKeys({ ...defaultFetchOptions, ...options }, [\n\t\t\t\t\"onRequest\",\n\t\t\t\t\"onResponse\",\n\t\t\t\t\"onResponseError\",\n\t\t\t\t\"onError\",\n\t\t\t\t\"onRequestError\",\n\t\t\t])\n\t\t);\n\n\t\tconst prevFetchController = abortControllerStore.get(requestKey);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\n\t\t\t\t`Automatic cancelation of the previous unfinished request to the same url, with the same fetch options: ${url}`,\n\t\t\t\t\"AbortError\"\n\t\t\t);\n\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(requestKey, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\tconst combinedSignal = AbortSignal.any([\n\t\t\tnewFetchController.signal,\n\t\t\t...(timeoutSignal ? [timeoutSignal] : []),\n\t\t\t...(signal ? [signal] : []),\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\t\t\t...defaultFetchOptions,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ options, request: requestInit });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\toptions.cloneResponse ? response.clone() : response,\n\t\t\t\t\toptions.responseType,\n\t\t\t\t\toptions.responseParser\n\t\t\t\t);\n\n\t\t\t\t// == Pushing all error handling responsibilities to the catch block\n\t\t\t\tthrow new HTTPError({\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\toptions.cloneResponse ? response.clone() : response,\n\t\t\t\toptions.responseType,\n\t\t\t\toptions.responseParser\n\t\t\t);\n\n\t\t\tconst validSuccessData = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tdata: validSuccessData,\n\t\t\t\toptions,\n\t\t\t\trequest: requestInit,\n\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ options, response, successData: validSuccessData });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = getResolveErrorResultFn<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tconst message = `Request aborted due to ${error.message}`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst { errorData, response } = error;\n\n\t\t\t\tvoid (await Promise.allSettled([\n\t\t\t\t\toptions.onResponseError?.({\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t\t\t}),\n\n\t\t\t\t\t// == Also call the onError interceptor\n\t\t\t\t\toptions.onError?.({\n\t\t\t\t\t\terror: null,\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}),\n\t\t\t\t]));\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid (await Promise.allSettled([\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request: requestInit }),\n\n\t\t\t\t// == Also call the onError interceptor\n\t\t\t\toptions.onError?.({\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\terrorData: null,\n\t\t\t\t\toptions,\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\tresponse: null,\n\t\t\t\t}),\n\t\t\t]));\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(requestKey);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n"],"mappings":"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","names":["callApi"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/typeof.ts","../../src/utils/utils.ts","../../src/createFetchClient.ts"],"sourcesContent":["export { callApi, createFetchClient } from \"./createFetchClient\";\n\nexport type {\n\t$RequestOptions,\n\tExtraOptions,\n\tFetchConfig,\n\tResponseContext,\n\tResponseErrorContext,\n\tErrorContext,\n} from \"./types\";\n","import type { AnyFunction } from \"./type-helpers\";\n\nexport const isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn (\n\t\ttypeof value === \"object\" && value !== null && !(value instanceof FormData) && !Array.isArray(value)\n\t);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n\nexport const isString = (value: unknown) => typeof value === \"string\";\n\nexport const isQueryString = (value: unknown): value is string =>\n\ttypeof value === \"string\" && value.includes(\"=\");\n","import { isArray, isFunction, isObject } from \"../typeof\";\nimport type {\n\t$BaseRequestOptions,\n\t$RequestOptions,\n\tApiErrorVariant,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"../types\";\n\n// prettier-ignore\nexport const getRequestKey = <TConfig extends Record<string, unknown>>(url: string, config?: TConfig) => `${url} | ${JSON.stringify(config ?? {})}`;\n\ntype ToQueryStringFn = {\n\t(params: ExtraOptions[\"query\"]): null | string;\n\t(params: Required<ExtraOptions>[\"query\"]): string;\n};\n\nexport const toQueryString: ToQueryStringFn = (params) => {\n\tif (!params) {\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\n\n\t\treturn null as never;\n\t}\n\n\treturn new URLSearchParams(params as Record<string, string>).toString();\n};\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = toQueryString(params);\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\tif (url.includes(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nexport const omitKeys = <\n\tTObject extends Record<string, unknown>,\n\tconst TOmitArray extends Array<keyof TObject>,\n>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype data = {\n\toptions: ExtraOptions;\n\tresponse: Response;\n\tsuccessData: unknown;\n};\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = <CallApiResult>(info: data): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = {\n\t\tdata: successData,\n\t\terror: null,\n\t\tresponse,\n\t};\n\n\tif (!options.resultMode || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlyError: apiDetails.error,\n\t\tonlyResponse: apiDetails.response,\n\t\tonlySuccess: apiDetails.data,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const getResolveErrorResultFn = <CallApiResult>($info: {\n\terror?: unknown;\n\toptions: ExtraOptions;\n}) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t\tresponse?: Response;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\terrorData: errorData ?? error,\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t\tname: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\n\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\n\treturn isObject(error) && error.name === \"HTTPError\";\n};\n\ntype ErrorDetails<TErrorResponse> = {\n\tdefaultErrorMessage: string;\n\terrorData: TErrorResponse;\n\tresponse: Response;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\terrorData: ErrorDetails<TErrorResponse>[\"errorData\"];\n\tisHTTPError = true;\n\n\toverride name = \"HTTPError\" as const;\n\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, errorData, response } = errorDetails;\n\n\t\tsuper((errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.errorData = errorData;\n\t\tthis.response = response;\n\t}\n}\n\n// prettier-ignore\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const waitUntil = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n","import { isObject, isQueryString, isString } from \"./typeof\";\nimport type {\n\t$RequestOptions,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultModeUnion,\n} from \"./types\";\nimport {\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetRequestKey,\n\tgetResolveErrorResultFn,\n\tgetResponseData,\n\tisHTTPErrorInstance,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tomitKeys,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twaitUntil,\n} from \"./utils/utils\";\n\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData = unknown,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\tbody: baseBody,\n\t\theaders: baseHeaders,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\n\n\t\t// == Default Extra Options\n\t\tconst options = {\n\t\t\tbaseURL: \"\",\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tcancelRedundantRequests: true,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tresponseType: \"json\",\n\t\t\tretries: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryDelay: 0,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\t// == Default Fetch Config\n\t\tconst defaultFetchOptions = {\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// - The auth option is provided\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || options.auth || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isQueryString(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\n\t\t\t// - headers are provided\n\t\t\t// - The body is an object\n\t\t\tmethod: \"GET\",\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\tconst requestKey = getRequestKey(\n\t\t\turl,\n\t\t\tomitKeys({ ...defaultFetchOptions, ...options }, [\n\t\t\t\t\"onRequest\",\n\t\t\t\t\"onResponse\",\n\t\t\t\t\"onResponseError\",\n\t\t\t\t\"onError\",\n\t\t\t\t\"onRequestError\",\n\t\t\t])\n\t\t);\n\n\t\tconst prevFetchController = abortControllerStore.get(requestKey);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\n\t\t\t\t`Request aborted as another request to this same endpoint: ${url}, with the same request options was initiated.`,\n\t\t\t\t\"AbortError\"\n\t\t\t);\n\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(requestKey, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\tconst combinedSignal = AbortSignal.any([\n\t\t\tnewFetchController.signal,\n\t\t\t...(timeoutSignal ? [timeoutSignal] : []),\n\t\t\t...(signal ? [signal] : []),\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\t\t\t...defaultFetchOptions,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ options, request: requestInit });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\toptions.cloneResponse ? response.clone() : response,\n\t\t\t\t\toptions.responseType,\n\t\t\t\t\toptions.responseParser\n\t\t\t\t);\n\n\t\t\t\t// == Pushing all error handling responsibilities to the catch block\n\t\t\t\tthrow new HTTPError({\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\toptions.cloneResponse ? response.clone() : response,\n\t\t\t\toptions.responseType,\n\t\t\t\toptions.responseParser\n\t\t\t);\n\n\t\t\tconst validSuccessData = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tdata: validSuccessData,\n\t\t\t\toptions,\n\t\t\t\trequest: requestInit,\n\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ options, response, successData: validSuccessData });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = getResolveErrorResultFn<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tconst message = `Request aborted due to ${error.message}`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst { errorData, response } = error;\n\n\t\t\t\tvoid (await Promise.all([\n\t\t\t\t\toptions.onResponseError?.({\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t\t\t}),\n\n\t\t\t\t\t// == Also call the onError interceptor\n\t\t\t\t\toptions.onError?.({\n\t\t\t\t\t\terror: null,\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}),\n\t\t\t\t]));\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid (await Promise.all([\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request: requestInit }),\n\n\t\t\t\t// == Also call the onError interceptor\n\t\t\t\toptions.onError?.({\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\terrorData: null,\n\t\t\t\t\toptions,\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\tresponse: null,\n\t\t\t\t}),\n\t\t\t]));\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(requestKey);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,UAAU,CAAS,UAAsC,MAAM,QAAQ,KAAK;AAElF,IAAM,WAAW,CAA0C,UAAqC;AACtG,SACC,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,iBAAiB,aAAa,CAAC,MAAM,QAAQ,KAAK;AAErG;AAEO,IAAM,aAAa,CAAgC,UACzD,OAAO,UAAU;AAEX,IAAM,WAAW,CAAC,UAAmB,OAAO,UAAU;AAEtD,IAAM,gBAAgB,CAAC,UAC7B,OAAO,UAAU,YAAY,MAAM,SAAS,GAAG;;;ACJzC,IAAM,gBAAgB,CAA0C,KAAa,WAAqB,GAAG,GAAG,MAAM,KAAK,UAAU,UAAU,CAAC,CAAC,CAAC;AAO1I,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;AAEO,IAAM,qBAAqB,CAAC,KAAa,WAA0C;AACzF,MAAI,CAAC,QAAQ;AACZ,WAAO;AAAA,EACR;AAEA,QAAM,eAAe,cAAc,MAAM;AAEzC,MAAI,IAAI,SAAS,GAAG,GAAG;AACtB,WAAO,GAAG,GAAG,GAAG,YAAY;AAAA,EAC7B;AAEA,MAAI,IAAI,SAAS,GAAG,GAAG;AACtB,WAAO,GAAG,GAAG,IAAI,YAAY;AAAA,EAC9B;AAEA,SAAO,GAAG,GAAG,IAAI,YAAY;AAC9B;AAEO,IAAM,mBAAmB,CAAC,YAAwE;AACxG,MAAI,CAAC,WAAW,SAAS,OAAO,GAAG;AAClC,WAAO;AAAA,EACR;AAEA,SAAO,OAAO,YAAY,QAAQ,OAAO,IAAI,UAAU,QAAQ,QAAQ,CAAC;AACzE;AAEA,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;AAElC,IAAM,sBAA4D,CAAC,KAAK;AAExE,IAAM,oBAAoB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,WAAW,CAIvB,eACA,eACI;AACJ,QAAM,0BAA0B,OAAO,QAAQ,aAAa,EAAE;AAAA,IAC7D,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,SAAS,GAAG;AAAA,EACpC;AAEA,QAAM,gBAAgB,OAAO,YAAY,uBAAuB;AAEhE,SAAO;AACR;AAEA,IAAM,WAAW,CAChB,eACA,eACI;AACJ,QAAM,gBAAgB,IAAI,IAAI,UAAU;AAExC,QAAM,sBAAsB,OAAO,QAAQ,aAAa;AAExD,QAAM,gBAAgB,oBAAoB,OAAO,CAAC,CAAC,SAAS,MAAM,cAAc,IAAI,SAAS,CAAC;AAE9F,QAAM,gBAAgB,OAAO,YAAY,aAAa;AAEtD,SAAO;AACR;AAEO,IAAM,cAAc,CAC1B,WAC0F;AAAA,EAC1F,SAAS,QAAmC,iBAAiB;AAAA,EAC7D,SAAS,QAAmC,iBAAiB;AAC9D;AAEO,IAAM,qBAAqB,CACjC,UACA,YACK;AAAA,EACL,aAAa,MAAM,SAAS,YAAY;AAAA,EACxC,MAAM,MAAM,SAAS,KAAK;AAAA,EAC1B,UAAU,MAAM,SAAS,SAAS;AAAA,EAClC,MAAM,YAAY;AACjB,QAAI,QAAQ;AACX,aAAO,OAAO,MAAM,SAAS,KAAK,CAAC;AAAA,IACpC;AAEA,WAAO,SAAS,KAAK;AAAA,EACtB;AAAA,EACA,MAAM,MAAM,SAAS,KAAK;AAC3B;AAEO,IAAM,kBAAkB,CAC9B,UACA,cACA,WACI;AACJ,QAAM,uBAAuB,mBAA8B,UAAU,MAAM;AAE3E,MAAI,CAAC,OAAO,OAAO,sBAAsB,YAAY,GAAG;AACvD,UAAM,IAAI,MAAM,0BAA0B,YAAY,EAAE;AAAA,EACzD;AAEA,SAAO,qBAAqB,YAAY,EAAE;AAC3C;AAUO,IAAM,uBAAuB,CAAgB,SAA8B;AACjF,QAAM,EAAE,SAAS,UAAU,YAAY,IAAI;AAE3C,QAAM,aAAa;AAAA,IAClB,MAAM;AAAA,IACN,OAAO;AAAA,IACP;AAAA,EACD;AAEA,MAAI,CAAC,QAAQ,cAAc,QAAQ,eAAe,OAAO;AACxD,WAAO;AAAA,EACR;AAEA,SAAO;AAAA,IACN,WAAW,WAAW;AAAA,IACtB,cAAc,WAAW;AAAA,IACzB,aAAa,WAAW;AAAA,EACzB,EAAE,QAAQ,UAAU;AACrB;AAGO,IAAM,0BAA0B,CAAgB,UAGjD;AACL,QAAM,EAAE,OAAO,QAAQ,IAAI;AAQ3B,QAAM,qBAAqB,CAAC,OAAkB,CAAC,MAAqB;AACnE,UAAM,EAAE,WAAW,SAAS,SAAS,IAAI;AAEzC,UAAM,qBAAqB,WAAW,QAAQ,YAAY,IACvD,QAAQ,aAAa,KAAc,IACnC,QAAQ;AAEX,QAAI,oBAAoB;AACvB,YAAM;AAAA,IACP;AAEA,WAAO;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,QACN,WAAW,aAAa;AAAA,QACxB,SAAS,WAAY,OAA+B,WAAW,QAAQ;AAAA,QACvE,MAAO,OAA+B,QAAQ;AAAA,MAC/C;AAAA,MACA,UAAU,YAAY;AAAA,IACvB;AAAA,EACD;AAEA,SAAO;AACR;AAgBO,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;AAAA,EACjB;AACD;AAGO,IAAM,sBAAsB,CAClC,UACwC;AACxC,SACC,iBAAiB,aAAc,SAAS,KAAK,KAAK,MAAM,SAAS,eAAe,MAAM,gBAAgB;AAExG;AAEO,IAAM,YAAY,CAAC,UAAkB;AAC3C,MAAI,UAAU,EAAG;AAEjB,QAAM,EAAE,SAAS,QAAQ,IAAI,QAAQ,cAAc;AAEnD,aAAW,SAAS,KAAK;AAEzB,SAAO;AACR;;;ACtPO,IAAM,oBAAoB,CAKhC,eACI;AACJ,QAAM,uBAAuB,oBAAI,IAA6B;AAE9D,QAAM,CAAC,iBAAiB,gBAAgB,IAAI,YAAY,cAAc,CAAC,CAAC;AAExE,QAAM;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,GAAG;AAAA,EACJ,IAAI;AAGJ,QAAMA,WAAU,OAKf,KACA,WAC+D;AAG/D,UAAM,CAAC,aAAa,YAAY,IAAI,YAAY,UAAU,CAAC,CAAC;AAE5D,UAAM,EAAE,OAAO,UAAU,SAAS,SAAS,YAAY,GAAG,kBAAkB,IAAI;AAGhF,UAAM,UAAU;AAAA,MACf,SAAS;AAAA,MACT,gBAAgB,KAAK;AAAA,MACrB,yBAAyB;AAAA,MACzB,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,GAAG;AAAA,MACH,GAAG;AAAA,IACJ;AAGA,UAAM,sBAAsB;AAAA,MAC3B,MAAM,SAAS,IAAI,IAAI,QAAQ,eAAe,IAAI,IAAI;AAAA;AAAA,MAGtD,SACC,eAAe,WAAW,QAAQ,QAAQ,SAAS,IAAI,IACpD;AAAA,QACA,GAAI,SAAS,IAAI,KAAK;AAAA,UACrB,QAAQ;AAAA,UACR,gBAAgB;AAAA,QACjB;AAAA,QACA,GAAI,cAAc,IAAI,KAAK;AAAA,UAC1B,gBAAgB;AAAA,QACjB;AAAA,QACA,GAAI,SAAS,QAAQ,IAAI,KAAK;AAAA,UAC7B,eAAe,UAAU,QAAQ,IAAI;AAAA,QACtC;AAAA,QACA,GAAI,SAAS,QAAQ,IAAI,KAAK;AAAA,UAC7B,eACC,YAAY,QAAQ,OACjB,UAAU,QAAQ,KAAK,MAAM,KAC7B,SAAS,QAAQ,KAAK,KAAK;AAAA,QAChC;AAAA,QACA,GAAG,iBAAiB,WAAW;AAAA,QAC/B,GAAG,iBAAiB,OAAO;AAAA,MAC5B,IACC;AAAA;AAAA;AAAA;AAAA,MAKJ,QAAQ;AAAA,MAER,GAAG;AAAA,MACH,GAAG;AAAA,IACJ;AAEA,UAAM,aAAa;AAAA,MAClB;AAAA,MACA,SAAS,EAAE,GAAG,qBAAqB,GAAG,QAAQ,GAAG;AAAA,QAChD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAEA,UAAM,sBAAsB,qBAAqB,IAAI,UAAU;AAE/D,QAAI,uBAAuB,QAAQ,yBAAyB;AAC3D,YAAM,SAAS,IAAI;AAAA,QAClB,6DAA6D,GAAG;AAAA,QAChE;AAAA,MACD;AAEA,0BAAoB,MAAM,MAAM;AAAA,IACjC;AAEA,UAAM,qBAAqB,IAAI,gBAAgB;AAE/C,yBAAqB,IAAI,YAAY,kBAAkB;AAEvD,UAAM,gBAAgB,QAAQ,UAAU,YAAY,QAAQ,QAAQ,OAAO,IAAI;AAE/E,UAAM,iBAAiB,YAAY,IAAI;AAAA,MACtC,mBAAmB;AAAA,MACnB,GAAI,gBAAgB,CAAC,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,SAAS,CAAC,MAAM,IAAI,CAAC;AAAA,IAC1B,CAAC;AAED,UAAM,cAAc;AAAA,MACnB,QAAQ;AAAA,MACR,GAAG;AAAA,IACJ;AAEA,QAAI;AACH,YAAM,QAAQ,YAAY,EAAE,SAAS,SAAS,YAAY,CAAC;AAE3D,YAAM,WAAW,MAAM;AAAA,QACtB,GAAG,QAAQ,OAAO,GAAG,mBAAmB,KAAK,QAAQ,KAAK,CAAC;AAAA,QAC3D;AAAA,MACD;AAEA,YAAM,cACL,CAAC,SAAS,MACV,CAAC,eAAe,WAChB,QAAQ,UAAU,KAClB,QAAQ,WAAW,SAAS,SAAS,MAAM,KAC3C,QAAQ,aAAa,SAAS,YAAY,MAAM;AAEjD,UAAI,aAAa;AAChB,cAAM,UAAU,QAAQ,UAAU;AAElC,eAAO,MAAMA,SAAQ,KAAK,EAAE,GAAG,QAAQ,SAAS,QAAQ,UAAU,EAAE,CAAC;AAAA,MACtE;AAEA,UAAI,CAAC,SAAS,IAAI;AACjB,cAAM,YAAY,MAAM;AAAA,UACvB,QAAQ,gBAAgB,SAAS,MAAM,IAAI;AAAA,UAC3C,QAAQ;AAAA,UACR,QAAQ;AAAA,QACT;AAGA,cAAM,IAAI,UAAU;AAAA,UACnB,qBAAqB,QAAQ;AAAA,UAC7B;AAAA,UACA;AAAA,QACD,CAAC;AAAA,MACF;AAEA,YAAM,cAAc,MAAM;AAAA,QACzB,QAAQ,gBAAgB,SAAS,MAAM,IAAI;AAAA,QAC3C,QAAQ;AAAA,QACR,QAAQ;AAAA,MACT;AAEA,YAAM,mBAAmB,QAAQ,oBAC9B,QAAQ,kBAAkB,WAAW,IACrC;AAEH,YAAM,QAAQ,aAAa;AAAA,QAC1B,MAAM;AAAA,QACN;AAAA,QACA,SAAS;AAAA,QACT,UAAU,QAAQ,gBAAgB,SAAS,MAAM,IAAI;AAAA,MACtD,CAAC;AAED,aAAO,qBAAoC,EAAE,SAAS,UAAU,aAAa,iBAAiB,CAAC;AAAA,IAGhG,SAAS,OAAO;AACf,YAAM,qBAAqB,wBAAuC,EAAE,OAAO,QAAQ,CAAC;AAEpF,UAAI,iBAAiB,gBAAgB,MAAM,SAAS,gBAAgB;AACnE,cAAM,UAAU,2BAA2B,QAAQ,OAAO;AAE1D,gBAAQ,MAAM,GAAG,MAAM,IAAI,KAAK,OAAO;AAEvC,eAAO,mBAAmB,EAAE,QAAQ,CAAC;AAAA,MACtC;AAEA,UAAI,iBAAiB,gBAAgB,MAAM,SAAS,cAAc;AACjE,cAAM,UAAU,0BAA0B,MAAM,OAAO;AAEvD,gBAAQ,MAAM,GAAG,MAAM,IAAI,KAAK,OAAO;AAEvC,eAAO,mBAAmB,EAAE,QAAQ,CAAC;AAAA,MACtC;AAEA,UAAI,oBAAgC,KAAK,GAAG;AAC3C,cAAM,EAAE,WAAW,SAAS,IAAI;AAEhC,aAAM,MAAM,QAAQ,IAAI;AAAA,UACvB,QAAQ,kBAAkB;AAAA,YACzB;AAAA,YACA;AAAA,YACA,SAAS;AAAA,YACT,UAAU,QAAQ,gBAAgB,SAAS,MAAM,IAAI;AAAA,UACtD,CAAC;AAAA;AAAA,UAGD,QAAQ,UAAU;AAAA,YACjB,OAAO;AAAA,YACP;AAAA,YACA;AAAA,YACA,SAAS;AAAA,YACT;AAAA,UACD,CAAC;AAAA,QACF,CAAC;AAED,eAAO,mBAAmB;AAAA,UACzB;AAAA,UACA,SAAU,WAAmC;AAAA,UAC7C;AAAA,QACD,CAAC;AAAA,MACF;AAEA,WAAM,MAAM,QAAQ,IAAI;AAAA;AAAA,QAEvB,QAAQ,iBAAiB,EAAE,OAAuB,SAAS,SAAS,YAAY,CAAC;AAAA;AAAA,QAGjF,QAAQ,UAAU;AAAA,UACjB;AAAA,UACA,WAAW;AAAA,UACX;AAAA,UACA,SAAS;AAAA,UACT,UAAU;AAAA,QACX,CAAC;AAAA,MACF,CAAC;AAED,aAAO,mBAAmB;AAAA,IAG3B,UAAE;AACD,2BAAqB,OAAO,UAAU;AAAA,IACvC;AAAA,EACD;AAEA,EAAAA,SAAQ,SAAS;AAEjB,SAAOA;AACR;AAEO,IAAM,UAAU,kBAAkB;","names":["callApi"]}
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as ResultModeUnion, B as BaseConfig, F as FetchConfig, G as GetCallApiResult } from './index-
|
|
2
|
-
export { $ as $RequestOptions, c as ErrorContext, E as ExtraOptions, a as ResponseContext, b as ResponseErrorContext } from './index-
|
|
1
|
+
import { R as ResultModeUnion, B as BaseConfig, F as FetchConfig, G as GetCallApiResult } from './index-CoVUDAa-.cjs';
|
|
2
|
+
export { $ as $RequestOptions, c as ErrorContext, E as ExtraOptions, a as ResponseContext, b as ResponseErrorContext } from './index-CoVUDAa-.cjs';
|
|
3
3
|
|
|
4
4
|
declare const createFetchClient: <TBaseData, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
5
5
|
<TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeUnion = TBaseResultMode>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode>): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { H as HTTPError, i as isHTTPError, d as isHTTPErrorInstance, t as toQueryString } from '../index-
|
|
1
|
+
export { H as HTTPError, i as isHTTPError, d as isHTTPErrorInstance, t as toQueryString } from '../index-CoVUDAa-.cjs';
|
|
@@ -113,7 +113,7 @@ interface ExtraOptions<TData = unknown, TErrorData = unknown, TResultMode extend
|
|
|
113
113
|
* @description Interceptor to be called when an error occurs during the fetch request OR when an error response is received from the api
|
|
114
114
|
* It is basically a combination of `onRequestError` and `onResponseError` interceptors
|
|
115
115
|
*/
|
|
116
|
-
onError?: (
|
|
116
|
+
onError?: (errorContext: ErrorContext<TErrorData>) => Promise<void> | void;
|
|
117
117
|
/** @description Interceptor to be called just before the request is made, allowing for modifications or additional operations. */
|
|
118
118
|
onRequest?: (requestContext: {
|
|
119
119
|
options: ExtraOptions;
|
|
@@ -195,7 +195,7 @@ type ResponseErrorContext<TErrorData> = Prettify<{
|
|
|
195
195
|
request: $RequestOptions;
|
|
196
196
|
response: Response;
|
|
197
197
|
}>;
|
|
198
|
-
type ErrorContext<TErrorData> =
|
|
198
|
+
type ErrorContext<TErrorData> = {
|
|
199
199
|
error: Error;
|
|
200
200
|
errorData?: null;
|
|
201
201
|
options: ExtraOptions;
|
|
@@ -207,7 +207,7 @@ type ErrorContext<TErrorData> = Prettify<{
|
|
|
207
207
|
options: ExtraOptions;
|
|
208
208
|
request: $RequestOptions;
|
|
209
209
|
response: Response;
|
|
210
|
-
}
|
|
210
|
+
};
|
|
211
211
|
interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = "all"> extends Omit<RequestInit, "body" | "method">, ExtraOptions<TData, TErrorData, TResultMode> {
|
|
212
212
|
}
|
|
213
213
|
type BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = "all"> = FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode>;
|
|
@@ -216,9 +216,7 @@ type ApiSuccessVariant<TData> = {
|
|
|
216
216
|
error: null;
|
|
217
217
|
response: Response;
|
|
218
218
|
};
|
|
219
|
-
type PossibleErrorNames =
|
|
220
|
-
_: "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | "UnknownError";
|
|
221
|
-
}["_"];
|
|
219
|
+
type PossibleErrorNames = "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | "UnknownError";
|
|
222
220
|
type ApiErrorVariant<TErrorData> = {
|
|
223
221
|
data: null;
|
|
224
222
|
error: {
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as ResultModeUnion, B as BaseConfig, F as FetchConfig, G as GetCallApiResult } from './index-
|
|
2
|
-
export { $ as $RequestOptions, c as ErrorContext, E as ExtraOptions, a as ResponseContext, b as ResponseErrorContext } from './index-
|
|
1
|
+
import { R as ResultModeUnion, B as BaseConfig, F as FetchConfig, G as GetCallApiResult } from './index-CoVUDAa-.js';
|
|
2
|
+
export { $ as $RequestOptions, c as ErrorContext, E as ExtraOptions, a as ResponseContext, b as ResponseErrorContext } from './index-CoVUDAa-.js';
|
|
3
3
|
|
|
4
4
|
declare const createFetchClient: <TBaseData, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
5
5
|
<TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeUnion = TBaseResultMode>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode>): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
package/dist/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{splitConfig as e,defaultRetryCodes as r,defaultRetryMethods as o,isObject as t,isQueryString as s,isString as n,objectifyHeaders as a,getRequestKey as i,omitKeys as u,mergeUrlWithParams as l,waitUntil as
|
|
1
|
+
import{splitConfig as e,defaultRetryCodes as r,defaultRetryMethods as o,isObject as t,isQueryString as s,isString as n,objectifyHeaders as a,getRequestKey as i,omitKeys as u,mergeUrlWithParams as l,waitUntil as p,getResponseData as c,HTTPError as d,resolveSuccessResult as m,getResolveErrorResultFn as h,isHTTPErrorInstance as y}from"./chunk-YYBXXYTQ.js";var R=f=>{const w=new Map,[b,q]=e(f??{}),{body:E,headers:g,signal:D,...$}=b,M=async(R,f)=>{const[b,T]=e(f??{}),{body:A=E,headers:k,signal:x=D,...C}=b,S={baseURL:"",bodySerializer:JSON.stringify,cancelRedundantRequests:!0,defaultErrorMessage:"Failed to fetch data from server!",responseType:"json",retries:0,retryCodes:r,retryDelay:0,retryMethods:o,...q,...T},j={body:t(A)?S.bodySerializer(A):A,headers:g||k||S.auth||t(A)?{...t(A)&&{Accept:"application/json","Content-Type":"application/json"},...s(A)&&{"Content-Type":"application/x-www-form-urlencoded"},...n(S.auth)&&{Authorization:`Bearer ${S.auth}`},...t(S.auth)&&{Authorization:"bearer"in S.auth?`Bearer ${S.auth.bearer}`:`Token ${S.auth.token}`},...a(g),...a(k)}:void 0,method:"GET",...$,...C},z=i(R,u({...j,...S},["onRequest","onResponse","onResponseError","onError","onRequestError"])),O=w.get(z);if(O&&S.cancelRedundantRequests){const e=new DOMException(`Request aborted as another request to this same endpoint: ${R}, with the same request options was initiated.`,"AbortError");O.abort(e)}const P=new AbortController;w.set(z,P);const v=S.timeout?AbortSignal.timeout(S.timeout):null,B=AbortSignal.any([P.signal,...v?[v]:[],...x?[x]:[]]),Y={signal:B,...j};try{await(S.onRequest?.({options:S,request:Y}));const e=await fetch(`${S.baseURL}${l(R,S.query)}`,Y);if(!e.ok&&!B.aborted&&S.retries>0&&S.retryCodes.includes(e.status)&&S.retryMethods.includes(Y.method))return await p(S.retryDelay),await M(R,{...f,retries:S.retries-1});if(!e.ok){const r=await c(S.cloneResponse?e.clone():e,S.responseType,S.responseParser);throw new d({defaultErrorMessage:S.defaultErrorMessage,errorData:r,response:e})}const r=await c(S.cloneResponse?e.clone():e,S.responseType,S.responseParser),o=S.responseValidator?S.responseValidator(r):r;return await(S.onResponse?.({data:o,options:S,request:Y,response:S.cloneResponse?e.clone():e})),m({options:S,response:e,successData:o})}catch(e){const r=h({error:e,options:S});if(e instanceof DOMException&&"TimeoutError"===e.name){const o=`Request timed out after ${S.timeout}ms`;return console.error(`${e.name}:`,o),r({message:o})}if(e instanceof DOMException&&"AbortError"===e.name){const o=`Request aborted due to ${e.message}`;return console.error(`${e.name}:`,o),r({message:o})}if(y(e)){const{errorData:o,response:t}=e;return await Promise.all([S.onResponseError?.({errorData:o,options:S,request:Y,response:S.cloneResponse?t.clone():t}),S.onError?.({error:null,errorData:o,options:S,request:Y,response:t})]),r({errorData:o,message:o?.message,response:t})}return await Promise.all([S.onRequestError?.({error:e,options:S,request:Y}),S.onError?.({error:e,errorData:null,options:S,request:Y,response:null})]),r()}finally{w.delete(z)}};return M.create=R,M},f=R();export{f as callApi,R as createFetchClient};//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/createFetchClient.ts"],"names":["callApi"],"mappings":"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","file":"index.js","sourcesContent":["import { isObject, isQueryString, isString } from \"./typeof\";\nimport type {\n\t$RequestOptions,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultModeUnion,\n} from \"./types\";\nimport {\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetRequestKey,\n\tgetResolveErrorResultFn,\n\tgetResponseData,\n\tisHTTPErrorInstance,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tomitKeys,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twaitUntil,\n} from \"./utils/utils\";\n\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData = unknown,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\tbody: baseBody,\n\t\theaders: baseHeaders,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\n\n\t\t// == Default Extra Options\n\t\tconst options = {\n\t\t\tbaseURL: \"\",\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tcancelRedundantRequests: true,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tresponseType: \"json\",\n\t\t\tretries: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryDelay: 0,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\t// == Default Fetch Config\n\t\tconst defaultFetchOptions = {\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// - The auth option is provided\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || options.auth || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isQueryString(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\n\t\t\t// - headers are provided\n\t\t\t// - The body is an object\n\t\t\tmethod: \"GET\",\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\tconst requestKey = getRequestKey(\n\t\t\turl,\n\t\t\tomitKeys({ ...defaultFetchOptions, ...options }, [\n\t\t\t\t\"onRequest\",\n\t\t\t\t\"onResponse\",\n\t\t\t\t\"onResponseError\",\n\t\t\t\t\"onError\",\n\t\t\t\t\"onRequestError\",\n\t\t\t])\n\t\t);\n\n\t\tconst prevFetchController = abortControllerStore.get(requestKey);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\n\t\t\t\t`Automatic cancelation of the previous unfinished request to the same url, with the same fetch options: ${url}`,\n\t\t\t\t\"AbortError\"\n\t\t\t);\n\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(requestKey, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\tconst combinedSignal = AbortSignal.any([\n\t\t\tnewFetchController.signal,\n\t\t\t...(timeoutSignal ? [timeoutSignal] : []),\n\t\t\t...(signal ? [signal] : []),\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\t\t\t...defaultFetchOptions,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ options, request: requestInit });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\toptions.cloneResponse ? response.clone() : response,\n\t\t\t\t\toptions.responseType,\n\t\t\t\t\toptions.responseParser\n\t\t\t\t);\n\n\t\t\t\t// == Pushing all error handling responsibilities to the catch block\n\t\t\t\tthrow new HTTPError({\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\toptions.cloneResponse ? response.clone() : response,\n\t\t\t\toptions.responseType,\n\t\t\t\toptions.responseParser\n\t\t\t);\n\n\t\t\tconst validSuccessData = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tdata: validSuccessData,\n\t\t\t\toptions,\n\t\t\t\trequest: requestInit,\n\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ options, response, successData: validSuccessData });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = getResolveErrorResultFn<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tconst message = `Request aborted due to ${error.message}`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst { errorData, response } = error;\n\n\t\t\t\tvoid (await Promise.allSettled([\n\t\t\t\t\toptions.onResponseError?.({\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t\t\t}),\n\n\t\t\t\t\t// == Also call the onError interceptor\n\t\t\t\t\toptions.onError?.({\n\t\t\t\t\t\terror: null,\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}),\n\t\t\t\t]));\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid (await Promise.allSettled([\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request: requestInit }),\n\n\t\t\t\t// == Also call the onError interceptor\n\t\t\t\toptions.onError?.({\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\terrorData: null,\n\t\t\t\t\toptions,\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\tresponse: null,\n\t\t\t\t}),\n\t\t\t]));\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(requestKey);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/createFetchClient.ts"],"names":["callApi"],"mappings":"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","file":"index.js","sourcesContent":["import { isObject, isQueryString, isString } from \"./typeof\";\nimport type {\n\t$RequestOptions,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultModeUnion,\n} from \"./types\";\nimport {\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetRequestKey,\n\tgetResolveErrorResultFn,\n\tgetResponseData,\n\tisHTTPErrorInstance,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tomitKeys,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twaitUntil,\n} from \"./utils/utils\";\n\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData = unknown,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\tbody: baseBody,\n\t\theaders: baseHeaders,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\tconst { body = baseBody, headers, signal = baseSignal, ...restOfFetchConfig } = fetchConfig;\n\n\t\t// == Default Extra Options\n\t\tconst options = {\n\t\t\tbaseURL: \"\",\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tcancelRedundantRequests: true,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tresponseType: \"json\",\n\t\t\tretries: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryDelay: 0,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\t// == Default Fetch Config\n\t\tconst defaultFetchOptions = {\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// - The auth option is provided\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || options.auth || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isQueryString(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\n\t\t\t// - headers are provided\n\t\t\t// - The body is an object\n\t\t\tmethod: \"GET\",\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\tconst requestKey = getRequestKey(\n\t\t\turl,\n\t\t\tomitKeys({ ...defaultFetchOptions, ...options }, [\n\t\t\t\t\"onRequest\",\n\t\t\t\t\"onResponse\",\n\t\t\t\t\"onResponseError\",\n\t\t\t\t\"onError\",\n\t\t\t\t\"onRequestError\",\n\t\t\t])\n\t\t);\n\n\t\tconst prevFetchController = abortControllerStore.get(requestKey);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\n\t\t\t\t`Request aborted as another request to this same endpoint: ${url}, with the same request options was initiated.`,\n\t\t\t\t\"AbortError\"\n\t\t\t);\n\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(requestKey, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\tconst combinedSignal = AbortSignal.any([\n\t\t\tnewFetchController.signal,\n\t\t\t...(timeoutSignal ? [timeoutSignal] : []),\n\t\t\t...(signal ? [signal] : []),\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\t\t\t...defaultFetchOptions,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ options, request: requestInit });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\toptions.cloneResponse ? response.clone() : response,\n\t\t\t\t\toptions.responseType,\n\t\t\t\t\toptions.responseParser\n\t\t\t\t);\n\n\t\t\t\t// == Pushing all error handling responsibilities to the catch block\n\t\t\t\tthrow new HTTPError({\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\toptions.cloneResponse ? response.clone() : response,\n\t\t\t\toptions.responseType,\n\t\t\t\toptions.responseParser\n\t\t\t);\n\n\t\t\tconst validSuccessData = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tdata: validSuccessData,\n\t\t\t\toptions,\n\t\t\t\trequest: requestInit,\n\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ options, response, successData: validSuccessData });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = getResolveErrorResultFn<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (error instanceof DOMException && error.name === \"AbortError\") {\n\t\t\t\tconst message = `Request aborted due to ${error.message}`;\n\n\t\t\t\tconsole.error(`${error.name}:`, message);\n\n\t\t\t\treturn resolveErrorResult({ message });\n\t\t\t}\n\n\t\t\tif (isHTTPErrorInstance<TErrorData>(error)) {\n\t\t\t\tconst { errorData, response } = error;\n\n\t\t\t\tvoid (await Promise.all([\n\t\t\t\t\toptions.onResponseError?.({\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse: options.cloneResponse ? response.clone() : response,\n\t\t\t\t\t}),\n\n\t\t\t\t\t// == Also call the onError interceptor\n\t\t\t\t\toptions.onError?.({\n\t\t\t\t\t\terror: null,\n\t\t\t\t\t\terrorData,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trequest: requestInit,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}),\n\t\t\t\t]));\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t\tresponse,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid (await Promise.all([\n\t\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\t\toptions.onRequestError?.({ error: error as Error, options, request: requestInit }),\n\n\t\t\t\t// == Also call the onError interceptor\n\t\t\t\toptions.onError?.({\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\terrorData: null,\n\t\t\t\t\toptions,\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\tresponse: null,\n\t\t\t\t}),\n\t\t\t]));\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(requestKey);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\n\treturn callApi;\n};\n\nexport const callApi = createFetchClient();\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { H as HTTPError, i as isHTTPError, d as isHTTPErrorInstance, t as toQueryString } from '../index-
|
|
1
|
+
export { H as HTTPError, i as isHTTPError, d as isHTTPErrorInstance, t as toQueryString } from '../index-CoVUDAa-.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zayne-labs/callapi",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A lightweight wrapper over fetch with quality of life improvements like built-in request cancellation, retries, interceptors and more",
|
|
6
6
|
"main": "./dist/esm/index.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"@size-limit/preset-small-lib": "^11.1.4",
|
|
25
25
|
"@stylistic/eslint-plugin": "^2.6.4",
|
|
26
26
|
"@zayne-labs/tsconfig": "^0.1.1",
|
|
27
|
+
"concurrently": "^8.2.2",
|
|
27
28
|
"eslint": "^9.9.0",
|
|
28
29
|
"eslint-plugin-import-x": "^3.1.0",
|
|
29
30
|
"eslint-plugin-jsdoc": "^50.2.2",
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
"lint-staged": "^15.2.9",
|
|
37
38
|
"pkg-pr-new": "^0.0.20",
|
|
38
39
|
"prettier": "^3.3.3",
|
|
40
|
+
"publint": "^0.2.10",
|
|
39
41
|
"size-limit": "^11.1.4",
|
|
40
42
|
"terser": "^5.31.6",
|
|
41
43
|
"tsup": "^8.2.4",
|
|
@@ -77,11 +79,13 @@
|
|
|
77
79
|
"scripts": {
|
|
78
80
|
"test:check-types": "tsc --pretty --incremental -p tsconfig.json",
|
|
79
81
|
"test:format": "prettier --write --cache .",
|
|
80
|
-
"test:lint": "eslint src/**/*.ts --max-warnings 10 --report-unused-disable-directives",
|
|
82
|
+
"test:lint": "eslint src/**/*.ts --cache --max-warnings 10 --report-unused-disable-directives ",
|
|
81
83
|
"test:size": "size-limit",
|
|
84
|
+
"test:publint": "publint --strict .",
|
|
85
|
+
"test:attw": "attw --pack . --exclude-entrypoints utils",
|
|
82
86
|
"test:release": "pkg-pr-new publish",
|
|
83
87
|
"build": "tsup",
|
|
84
|
-
"build:dev": "tsup --watch",
|
|
88
|
+
"build:dev": "concurrently --prefix-colors \"#7da4f8.bold,yellow.bold\" --names TSUP,PUBLINT,ATTW \"pnpm tsup --watch\"' 'pnpm:test:publint' 'pnpm:test:attw'",
|
|
85
89
|
"version-package": "changeset version",
|
|
86
90
|
"release": "changeset publish"
|
|
87
91
|
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 Ikedigwe Ebube
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|