@zayne-labs/callapi 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +536 -0
- package/dist/createFetchClient.cjs +3 -2
- package/dist/createFetchClient.cjs.map +1 -1
- package/dist/createFetchClient.d.cts +5 -17
- package/dist/createFetchClient.d.ts +5 -17
- package/dist/createFetchClient.js +4 -3
- package/dist/createFetchClient.js.map +1 -1
- package/dist/index.cjs +8 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/types-CGXvcfe9.d.cts +241 -0
- package/dist/types-CGXvcfe9.d.ts +241 -0
- package/dist/utils.cjs +14 -14
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +4 -2
- package/dist/utils.js.map +1 -1
- package/package.json +2 -3
- package/dist/types-B8arQl4O.d.cts +0 -147
- package/dist/types-B8arQl4O.d.ts +0 -147
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isObject, isFormData, isString } from './typeof';
|
|
2
|
+
import { splitConfig, defaultRetryCodes, defaultRetryMethods, objectifyHeaders, mergeUrlWithParams, waitUntil, getResponseData, HTTPError, resolveSuccessResult, $resolveErrorResult, isHTTPErrorInstance } from './utils';
|
|
2
3
|
|
|
3
|
-
const m
|
|
4
|
+
const b=m=>{const i=new Map,[C,D]=splitConfig(m??{}),{headers:p,body:w,signal:A,...M}=C,l=async(o,f)=>{const[q,B]=splitConfig(f??{}),e={bodySerializer:JSON.stringify,responseType:"json",baseURL:"",retries:0,retryDelay:0,retryCodes:defaultRetryCodes,retryMethods:defaultRetryMethods,defaultErrorMessage:"Failed to fetch data from server!",cancelRedundantRequests:!0,...D,...B},{signal:O=A,body:s=w,headers:g,...x}=q,R=i.get(o);if(R&&e.cancelRedundantRequests){const t=new DOMException("Cancelled the previous unfinished request","AbortError");R.abort(t);}const c=new AbortController;i.set(o,c);const S=e.timeout?AbortSignal.timeout(e.timeout):null,T=AbortSignal.any([c.signal,S??c.signal,O??c.signal]),a={signal:T,method:"GET",body:isObject(s)?e.bodySerializer(s):s,headers:p||g||e.auth||isObject(s)?{...isObject(s)&&{"Content-Type":"application/json",Accept:"application/json"},...isFormData(s)&&{"Content-Type":"multipart/form-data"},...isString(s)&&{"Content-Type":"application/x-www-form-urlencoded"},...!!e.auth&&{Authorization:`Bearer ${e.auth}`},...objectifyHeaders(p),...objectifyHeaders(g)}:void 0,...M,...x};try{await e.onRequest?.({request:a,options:e});const t=await fetch(`${e.baseURL}${mergeUrlWithParams(o,e.query)}`,a);if(!t.ok&&!T.aborted&&e.retries>0&&e.retryCodes.includes(t.status)&&e.retryMethods.includes(a.method))return await waitUntil(e.retryDelay),await l(o,{...f,retries:e.retries-1});if(!t.ok){const u=await getResponseData(t,e.responseType,e.responseParser);throw new HTTPError({response:{...t,errorData:u},defaultErrorMessage:e.defaultErrorMessage})}const r=await getResponseData(t,e.responseType,e.responseParser);return await e.onResponse?.({response:{...t,data:r},request:a,options:e}),resolveSuccessResult({successData:r,response:t,options:e})}catch(t){const n=$resolveErrorResult({error:t,options:e});if(t instanceof DOMException&&t.name==="TimeoutError"){const r=`Request timed out after ${e.timeout}ms`;return console.info(`%cTimeoutError: ${r}`,"color: red; font-weight: 500; font-size: 14px;"),console.trace("TimeoutError"),n({message:r})}if(t instanceof DOMException&&t.name==="AbortError"){const r="Request was cancelled";return console.info(`%AbortError: ${r}`,"color: red; font-weight: 500; font-size: 14px;"),console.trace("AbortError"),n({message:r})}if(isHTTPErrorInstance(t)){const{errorData:r,...u}=t.response;return await e.onResponseError?.({response:{...u,errorData:r},request:a,options:e}),n({errorData:r,response:u,message:r?.message})}return await e.onRequestError?.({request:a,error:t,options:e}),n()}finally{i.delete(o);}};return l.create=b,l.cancel=o=>i.get(o)?.abort(),l};
|
|
4
5
|
|
|
5
|
-
export {
|
|
6
|
+
export { b as createFetchClient };
|
|
6
7
|
//# sourceMappingURL=out.js.map
|
|
7
8
|
//# sourceMappingURL=createFetchClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/createFetchClient.ts"],"names":["$resolveErrorResult","HTTPError","defaultRetryCodes","defaultRetryMethods","getResponseData","isFormData","isHTTPErrorInfo","isHTTPErrorInstance","isObject","mergeUrlWithParams","objectifyHeaders","resolveSuccessResult","splitConfig","wait","createFetchClient","baseConfig","abortControllerStore","baseFetchConfig","baseExtraOptions","baseHeaders","baseSignal","restOfBaseFetchConfig","callApi","url","config","fetchConfig","extraOptions","options","signal","body","headers","restOfFetchConfig","prevFetchController","reason","newFetchController","timeoutSignal","combinedSignal","requestInit","response","errorData","successData","error","resolveErrorResult","message","createFetchClient_default"],"mappings":"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","sourcesContent":["import type {\n\t$RequestConfig,\n\tAbortSignalWithAny,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultStyleUnion,\n} from \"./types\";\nimport {\n\t$resolveErrorResult,\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetResponseData,\n\tisFormData,\n\tisHTTPErrorInfo,\n\tisHTTPErrorInstance,\n\tisObject,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twait,\n} from \"./utils\";\n\nconst createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData,\n\tTBaseResultMode extends ResultStyleUnion = 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 { headers: baseHeaders, signal: baseSignal, ...restOfBaseFetchConfig } = baseFetchConfig;\n\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultStyleUnion = 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 options = {\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tresponseType: \"json\",\n\t\t\tbaseURL: \"\",\n\t\t\tretries: 0,\n\t\t\tretryDelay: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tcancelRedundantRequests: true,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\tconst { signal = baseSignal, body, headers, ...restOfFetchConfig } = fetchConfig;\n\n\t\tconst prevFetchController = abortControllerStore.get(url);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\"Cancelled the previous unfinished request\", \"AbortError\");\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(url, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\t// FIXME - Remove this type cast once TS updates its lib-dom types for AbortSignal to include the any() method\n\t\tconst combinedSignal = (AbortSignal as AbortSignalWithAny).any([\n\t\t\tnewFetchController.signal,\n\t\t\ttimeoutSignal ?? newFetchController.signal,\n\t\t\tsignal ?? newFetchController.signal,\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\n\t\t\tmethod: \"GET\",\n\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// == Return undefined if there are no headers provided or if the body is not an object\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isFormData(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"multipart/form-data\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestConfig;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ request: requestInit, options });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries !== 0 &&\n\t\t\t\t!response.ok &&\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 wait(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\tresponse,\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\tresponse: { ...response, errorData },\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\tresponse,\n\t\t\t\toptions.responseType,\n\t\t\t\toptions.responseParser\n\t\t\t);\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tresponse: { ...response, data: successData },\n\t\t\t\trequest: requestInit,\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ successData, response, options });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = $resolveErrorResult<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.info(`%cTimeoutError: ${message}`, \"color: red; font-weight: 500; font-size: 14px;\");\n\t\t\t\tconsole.trace(\"TimeoutError\");\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 was cancelled`;\n\n\t\t\t\tconsole.info(`%AbortError: ${message}`, \"color: red; font-weight: 500; font-size: 14px;\");\n\t\t\t\tconsole.trace(\"AbortError\");\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.response;\n\n\t\t\t\tawait options.onResponseError?.({\n\t\t\t\t\tresponse: { ...response, errorData },\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\toptions,\n\t\t\t\t});\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\tawait options.onRequestError?.({ request: requestInit, error: error as Error, options });\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(url);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\tcallApi.isHTTPErrorInfo = isHTTPErrorInfo;\n\tcallApi.isHTTPErrorInstance = isHTTPErrorInstance;\n\tcallApi.cancel = (url: string) => abortControllerStore.get(url)?.abort();\n\n\treturn callApi;\n};\n\nconst callApi = createFetchClient();\n\nexport default callApi;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/createFetchClient.ts"],"names":["isFormData","isObject","isString","$resolveErrorResult","HTTPError","defaultRetryCodes","defaultRetryMethods","getResponseData","isHTTPErrorInstance","mergeUrlWithParams","objectifyHeaders","resolveSuccessResult","splitConfig","waitUntil","createFetchClient","baseConfig","abortControllerStore","baseFetchConfig","baseExtraOptions","baseHeaders","baseBody","baseSignal","restOfBaseFetchConfig","callApi","url","config","fetchConfig","extraOptions","options","signal","body","headers","restOfFetchConfig","prevFetchController","reason","newFetchController","timeoutSignal","combinedSignal","requestInit","response","errorData","successData","error","resolveErrorResult","message"],"mappings":"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","sourcesContent":["import { isFormData, isObject, isString } from \"./typeof\";\nimport type {\n\t$RequestOptions,\n\tAbortSignalWithAny,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tGetCallApiResult,\n\tPossibleErrorObject,\n\tResultModeUnion,\n} from \"./types\";\nimport {\n\t$resolveErrorResult,\n\tHTTPError,\n\tdefaultRetryCodes,\n\tdefaultRetryMethods,\n\tgetResponseData,\n\tisHTTPErrorInstance,\n\tmergeUrlWithParams,\n\tobjectifyHeaders,\n\tresolveSuccessResult,\n\tsplitConfig,\n\twaitUntil,\n} from \"./utils\";\n\nconst createFetchClient = <TBaseData, TBaseErrorData, TBaseResultMode extends ResultModeUnion = undefined>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\theaders: baseHeaders,\n\t\tbody: baseBody,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\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 options = {\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tresponseType: \"json\",\n\t\t\tbaseURL: \"\",\n\t\t\tretries: 0,\n\t\t\tretryDelay: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tcancelRedundantRequests: true,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\tconst { signal = baseSignal, body = baseBody, headers, ...restOfFetchConfig } = fetchConfig;\n\n\t\tconst prevFetchController = abortControllerStore.get(url);\n\n\t\tif (prevFetchController && options.cancelRedundantRequests) {\n\t\t\tconst reason = new DOMException(\"Cancelled the previous unfinished request\", \"AbortError\");\n\t\t\tprevFetchController.abort(reason);\n\t\t}\n\n\t\tconst newFetchController = new AbortController();\n\n\t\tabortControllerStore.set(url, newFetchController);\n\n\t\tconst timeoutSignal = options.timeout ? AbortSignal.timeout(options.timeout) : null;\n\n\t\t// FIXME - Remove this type cast once TS updates its lib-dom types for AbortSignal to include the any() method\n\t\tconst combinedSignal = (AbortSignal as AbortSignalWithAny).any([\n\t\t\tnewFetchController.signal,\n\t\t\ttimeoutSignal ?? newFetchController.signal,\n\t\t\tsignal ?? newFetchController.signal,\n\t\t]);\n\n\t\tconst requestInit = {\n\t\t\tsignal: combinedSignal,\n\n\t\t\tmethod: \"GET\",\n\n\t\t\tbody: isObject(body) ? options.bodySerializer(body) : body,\n\n\t\t\t// == Return undefined if the following conditions are not met (so that native fetch would auto set the correct headers):\n\t\t\t// - headers are provided\n\t\t\t// - The body is an object\n\t\t\t// - The auth option is provided\n\t\t\theaders:\n\t\t\t\tbaseHeaders || headers || options.auth || isObject(body)\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...(isObject(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isFormData(body) && {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"multipart/form-data\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isString(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...(Boolean(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...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ request: requestInit, options });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\tresponse,\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\tresponse: { ...response, errorData },\n\t\t\t\t\tdefaultErrorMessage: options.defaultErrorMessage,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst successData = await getResponseData<TData>(\n\t\t\t\tresponse,\n\t\t\t\toptions.responseType,\n\t\t\t\toptions.responseParser\n\t\t\t);\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tresponse: { ...response, data: successData },\n\t\t\t\trequest: requestInit,\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ successData, response, options });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = $resolveErrorResult<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.info(`%cTimeoutError: ${message}`, \"color: red; font-weight: 500; font-size: 14px;\");\n\t\t\t\tconsole.trace(\"TimeoutError\");\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 was cancelled`;\n\n\t\t\t\tconsole.info(`%AbortError: ${message}`, \"color: red; font-weight: 500; font-size: 14px;\");\n\t\t\t\tconsole.trace(\"AbortError\");\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.response;\n\n\t\t\t\tawait options.onResponseError?.({\n\t\t\t\t\tresponse: { ...response, errorData },\n\t\t\t\t\trequest: requestInit,\n\t\t\t\t\toptions,\n\t\t\t\t});\n\n\t\t\t\treturn resolveErrorResult({\n\t\t\t\t\terrorData,\n\t\t\t\t\tresponse,\n\t\t\t\t\tmessage: (errorData as PossibleErrorObject)?.message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// == At this point only the request errors exist, so the request error interceptor is called\n\t\t\tawait options.onRequestError?.({ request: requestInit, error: error as Error, options });\n\n\t\t\treturn resolveErrorResult();\n\n\t\t\t// == Removing the now unneeded AbortController from store\n\t\t} finally {\n\t\t\tabortControllerStore.delete(url);\n\t\t}\n\t};\n\n\tcallApi.create = createFetchClient;\n\n\tcallApi.cancel = (url: string) => abortControllerStore.get(url)?.abort();\n\n\treturn callApi;\n};\n\nexport { createFetchClient };\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -3,27 +3,24 @@
|
|
|
3
3
|
var createFetchClient = require('./createFetchClient');
|
|
4
4
|
var utils = require('./utils');
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const e=createFetchClient.createFetchClient();
|
|
7
7
|
|
|
8
|
-
var createFetchClient__default = /*#__PURE__*/_interopDefault(createFetchClient);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Object.defineProperty(exports, "callApi", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () { return createFetchClient__default.default; }
|
|
15
|
-
});
|
|
16
8
|
Object.defineProperty(exports, "HTTPError", {
|
|
17
9
|
enumerable: true,
|
|
18
10
|
get: function () { return utils.HTTPError; }
|
|
19
11
|
});
|
|
20
|
-
Object.defineProperty(exports, "
|
|
12
|
+
Object.defineProperty(exports, "isHTTPError", {
|
|
21
13
|
enumerable: true,
|
|
22
|
-
get: function () { return utils.
|
|
14
|
+
get: function () { return utils.isHTTPError; }
|
|
23
15
|
});
|
|
24
16
|
Object.defineProperty(exports, "isHTTPErrorInstance", {
|
|
25
17
|
enumerable: true,
|
|
26
18
|
get: function () { return utils.isHTTPErrorInstance; }
|
|
27
19
|
});
|
|
20
|
+
Object.defineProperty(exports, "toQueryString", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return utils.toQueryString; }
|
|
23
|
+
});
|
|
24
|
+
exports.callApi = e;
|
|
28
25
|
//# sourceMappingURL=out.js.map
|
|
29
26
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["createFetchClient","callApi","HTTPError","isHTTPError","isHTTPErrorInstance","toQueryString"],"mappings":"AAAA,OAAS,qBAAAA,MAAyB,sBAE3B,MAAMC,EAAUD,EAAkB,EAUzC,OAAS,aAAAE,EAAW,eAAAC,EAAa,uBAAAC,EAAqB,iBAAAC,MAAqB","sourcesContent":["import { createFetchClient } from \"./createFetchClient\";\n\nexport const callApi = createFetchClient();\n\nexport type {\n\tFetchConfig,\n\t$RequestOptions,\n\tExtraOptions,\n\tResponseContext,\n\tResponseErrorContext,\n} from \"./types\";\n\nexport { HTTPError, isHTTPError, isHTTPErrorInstance, toQueryString } from \"./utils\";\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
import { R as ResultModeUnion, F as FetchConfig, G as GetCallApiResult, B as BaseConfig } from './types-CGXvcfe9.cjs';
|
|
2
|
+
export { $ as $RequestOptions, E as ExtraOptions, H as HTTPError, a as ResponseContext, b as ResponseErrorContext, i as isHTTPError, c as isHTTPErrorInstance, t as toQueryString } from './types-CGXvcfe9.cjs';
|
|
3
|
+
|
|
4
|
+
declare const callApi: {
|
|
5
|
+
<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = undefined>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode> | undefined): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
6
|
+
create: <TBaseData, TBaseErrorData, TBaseResultMode extends ResultModeUnion = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
7
|
+
<TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeUnion = TBaseResultMode>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode>): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
8
|
+
create: any;
|
|
9
|
+
cancel(url: string): void | undefined;
|
|
10
|
+
};
|
|
11
|
+
cancel(url: string): void | undefined;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { FetchConfig, callApi };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
import { R as ResultModeUnion, F as FetchConfig, G as GetCallApiResult, B as BaseConfig } from './types-CGXvcfe9.js';
|
|
2
|
+
export { $ as $RequestOptions, E as ExtraOptions, H as HTTPError, a as ResponseContext, b as ResponseErrorContext, i as isHTTPError, c as isHTTPErrorInstance, t as toQueryString } from './types-CGXvcfe9.js';
|
|
3
|
+
|
|
4
|
+
declare const callApi: {
|
|
5
|
+
<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = undefined>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode> | undefined): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
6
|
+
create: <TBaseData, TBaseErrorData, TBaseResultMode extends ResultModeUnion = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
7
|
+
<TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeUnion = TBaseResultMode>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode>): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
8
|
+
create: any;
|
|
9
|
+
cancel(url: string): void | undefined;
|
|
10
|
+
};
|
|
11
|
+
cancel(url: string): void | undefined;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { FetchConfig, callApi };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export { HTTPError,
|
|
1
|
+
import { createFetchClient } from './createFetchClient';
|
|
2
|
+
export { HTTPError, isHTTPError, isHTTPErrorInstance, toQueryString } from './utils';
|
|
3
|
+
|
|
4
|
+
const e=createFetchClient();
|
|
5
|
+
|
|
6
|
+
export { e as callApi };
|
|
3
7
|
//# sourceMappingURL=out.js.map
|
|
4
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["createFetchClient","callApi","HTTPError","isHTTPError","isHTTPErrorInstance","toQueryString"],"mappings":"AAAA,OAAS,qBAAAA,MAAyB,sBAE3B,MAAMC,EAAUD,EAAkB,EAUzC,OAAS,aAAAE,EAAW,eAAAC,EAAa,uBAAAC,EAAqB,iBAAAC,MAAqB","sourcesContent":["import { createFetchClient } from \"./createFetchClient\";\n\nexport const callApi = createFetchClient();\n\nexport type {\n\tFetchConfig,\n\t$RequestOptions,\n\tExtraOptions,\n\tResponseContext,\n\tResponseErrorContext,\n} from \"./types\";\n\nexport { HTTPError, isHTTPError, isHTTPErrorInstance, toQueryString } from \"./utils\";\n"]}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
type AnyString = string & {
|
|
2
|
+
placeholder?: never;
|
|
3
|
+
};
|
|
4
|
+
type AnyNumber = number & {
|
|
5
|
+
placeholder?: never;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type ToQueryStringFn = {
|
|
9
|
+
(params: Required<ExtraOptions>["query"]): string;
|
|
10
|
+
(params: ExtraOptions["query"]): string | null;
|
|
11
|
+
};
|
|
12
|
+
declare const toQueryString: ToQueryStringFn;
|
|
13
|
+
declare const mergeUrlWithParams: (url: string, params: ExtraOptions["query"]) => string;
|
|
14
|
+
declare const objectifyHeaders: (headers: RequestInit["headers"]) => Record<string, string> | undefined;
|
|
15
|
+
declare const defaultRetryCodes: Required<BaseConfig>["retryCodes"];
|
|
16
|
+
declare const defaultRetryMethods: Required<BaseConfig>["retryMethods"];
|
|
17
|
+
declare const fetchSpecificKeys: ("body" | "method" | "headers" | "cache" | "credentials" | "integrity" | "keepalive" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
|
|
18
|
+
declare const splitConfig: <TObject extends object>(config: TObject) => ["body" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions];
|
|
19
|
+
declare const handleResponseType: <TResponse>(response: Response, parser?: Required<ExtraOptions>["responseParser"]) => {
|
|
20
|
+
json: () => Promise<Record<string, unknown> | TResponse>;
|
|
21
|
+
arrayBuffer: () => Promise<TResponse>;
|
|
22
|
+
blob: () => Promise<TResponse>;
|
|
23
|
+
formData: () => Promise<TResponse>;
|
|
24
|
+
text: () => Promise<TResponse>;
|
|
25
|
+
};
|
|
26
|
+
declare const getResponseData: <TResponse>(response: Response, responseType: keyof ReturnType<typeof handleResponseType>, parser: ExtraOptions["responseParser"]) => Promise<Record<string, unknown> | TResponse>;
|
|
27
|
+
type data = {
|
|
28
|
+
successData: unknown;
|
|
29
|
+
options: ExtraOptions;
|
|
30
|
+
response: Response;
|
|
31
|
+
};
|
|
32
|
+
declare const resolveSuccessResult: <CallApiResult>(info: data) => CallApiResult;
|
|
33
|
+
declare const $resolveErrorResult: <CallApiResult>($info: {
|
|
34
|
+
error?: unknown;
|
|
35
|
+
options: ExtraOptions;
|
|
36
|
+
}) => (info?: {
|
|
37
|
+
response?: Response;
|
|
38
|
+
errorData?: unknown;
|
|
39
|
+
message?: string;
|
|
40
|
+
}) => CallApiResult;
|
|
41
|
+
declare const isHTTPError: <TErrorData>(error: ApiErrorVariant<TErrorData>["error"] | null) => error is {
|
|
42
|
+
errorName: "HTTPError";
|
|
43
|
+
errorData: TErrorData;
|
|
44
|
+
message: string;
|
|
45
|
+
};
|
|
46
|
+
type ErrorDetails<TErrorResponse> = {
|
|
47
|
+
response: Response & {
|
|
48
|
+
errorData: TErrorResponse;
|
|
49
|
+
};
|
|
50
|
+
defaultErrorMessage: string;
|
|
51
|
+
};
|
|
52
|
+
type ErrorOptions = {
|
|
53
|
+
cause?: unknown;
|
|
54
|
+
};
|
|
55
|
+
declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {
|
|
56
|
+
response: ErrorDetails<TErrorResponse>["response"];
|
|
57
|
+
name: "HTTPError";
|
|
58
|
+
isHTTPError: boolean;
|
|
59
|
+
constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
|
|
60
|
+
}
|
|
61
|
+
declare const isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
62
|
+
declare const waitUntil: (delay: number) => Promise<unknown> | undefined;
|
|
63
|
+
|
|
64
|
+
type $RequestOptions = Pick<FetchConfig, (typeof fetchSpecificKeys)[number]>;
|
|
65
|
+
type $BaseRequestOptions = Omit<$RequestOptions, "body">;
|
|
66
|
+
type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = ResultModeUnion> = {
|
|
67
|
+
/** Optional body of the request, can be a object or any other supported body type. */
|
|
68
|
+
body?: Record<string, unknown> | RequestInit["body"];
|
|
69
|
+
/**
|
|
70
|
+
* @description HTTP method for the request.
|
|
71
|
+
* @default "GET"
|
|
72
|
+
*/
|
|
73
|
+
method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | AnyString;
|
|
74
|
+
/**
|
|
75
|
+
* @description Query parameters to append to the URL.
|
|
76
|
+
*/
|
|
77
|
+
query?: Record<string, string | number | boolean>;
|
|
78
|
+
/**
|
|
79
|
+
* @description Authorization header value.
|
|
80
|
+
*/
|
|
81
|
+
auth?: string;
|
|
82
|
+
/**
|
|
83
|
+
* @description Custom function to serialize the body object into a string.
|
|
84
|
+
*/
|
|
85
|
+
bodySerializer?: (bodyData: Record<string, unknown>) => string;
|
|
86
|
+
/**
|
|
87
|
+
* @description Custom function to parse the response string into a object.
|
|
88
|
+
*/
|
|
89
|
+
responseParser?: (responseString: string) => Record<string, unknown>;
|
|
90
|
+
/**
|
|
91
|
+
* @description Mode of the result, can influence how results are handled or returned.
|
|
92
|
+
* Can be set to "all" | "onlySuccess" | "onlyError" | "onlyResponse".
|
|
93
|
+
* @default "all"
|
|
94
|
+
*/
|
|
95
|
+
resultMode?: TBaseResultMode;
|
|
96
|
+
/**
|
|
97
|
+
* @description If true, cancels previous unfinished requests to the same URL.
|
|
98
|
+
* @default true
|
|
99
|
+
*/
|
|
100
|
+
cancelRedundantRequests?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* @description Base URL to be prepended to all request URLs
|
|
103
|
+
*/
|
|
104
|
+
baseURL?: string;
|
|
105
|
+
/**
|
|
106
|
+
* @description Request timeout in milliseconds
|
|
107
|
+
*/
|
|
108
|
+
timeout?: number;
|
|
109
|
+
/**
|
|
110
|
+
* @description Default error message to use if none is provided from a response.
|
|
111
|
+
* @default "Failed to fetch data from server!"
|
|
112
|
+
*/
|
|
113
|
+
defaultErrorMessage?: string;
|
|
114
|
+
/**
|
|
115
|
+
* If true or the function returns true, throws errors instead of returning them
|
|
116
|
+
* The function is passed the error object and can be used to conditionally throw the error
|
|
117
|
+
* @default false
|
|
118
|
+
*/
|
|
119
|
+
throwOnError?: boolean | ((error?: Error | HTTPError<TBaseErrorData>) => boolean);
|
|
120
|
+
/**
|
|
121
|
+
* @description Expected response type, affects how response is parsed
|
|
122
|
+
* @default "json"
|
|
123
|
+
*/
|
|
124
|
+
responseType?: keyof ReturnType<typeof handleResponseType>;
|
|
125
|
+
/**
|
|
126
|
+
* @description Number of retry attempts for failed requests
|
|
127
|
+
* @default 0
|
|
128
|
+
*/
|
|
129
|
+
retries?: number;
|
|
130
|
+
/**
|
|
131
|
+
* @description Delay between retries in milliseconds
|
|
132
|
+
* @default 500
|
|
133
|
+
*/
|
|
134
|
+
retryDelay?: number;
|
|
135
|
+
/**
|
|
136
|
+
* @description HTTP status codes that trigger a retry
|
|
137
|
+
* @default [409, 425, 429, 500, 502, 503, 504]
|
|
138
|
+
*/
|
|
139
|
+
retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
|
|
140
|
+
/**
|
|
141
|
+
* HTTP methods that are allowed to retry
|
|
142
|
+
* @default ["GET", "POST"]
|
|
143
|
+
*/
|
|
144
|
+
retryMethods?: Array<"GET" | "POST" | AnyString>;
|
|
145
|
+
/**
|
|
146
|
+
* @description an optional field you can fill with additional information,
|
|
147
|
+
* to associate with the request, typically used for logging or tracing.
|
|
148
|
+
*
|
|
149
|
+
* A good use case for this, would be to use the info to handle specific cases in any of the shared interceptors.
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* const callMainApi = callApi.create({
|
|
153
|
+
* baseURL: "https://main-api.com",
|
|
154
|
+
* onResponseError: ({ response, options }) => {
|
|
155
|
+
* if (options.meta?.userId) {
|
|
156
|
+
* console.error(`User ${options.meta.userId} made an error`);
|
|
157
|
+
* }
|
|
158
|
+
* },
|
|
159
|
+
* });
|
|
160
|
+
*
|
|
161
|
+
* const response = await callMainApi({
|
|
162
|
+
* url: "https://example.com/api/data",
|
|
163
|
+
* meta: { userId: "123" },
|
|
164
|
+
* });
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
meta?: Record<string, unknown>;
|
|
168
|
+
/** @description Interceptor to be called just before the request is made, allowing for modifications or additional operations. */
|
|
169
|
+
onRequest?: (requestContext: {
|
|
170
|
+
request: $RequestOptions;
|
|
171
|
+
options: ExtraOptions;
|
|
172
|
+
}) => void | Promise<void>;
|
|
173
|
+
/** @description Interceptor to be called when an error occurs during the fetch request. */
|
|
174
|
+
onRequestError?: (requestErrorContext: {
|
|
175
|
+
error: Error;
|
|
176
|
+
request: $RequestOptions;
|
|
177
|
+
options: ExtraOptions;
|
|
178
|
+
}) => void | Promise<void>;
|
|
179
|
+
/** @description Interceptor to be called when a successful response is received from the api. */
|
|
180
|
+
onResponse?: (responseContext: ResponseContext<TBaseData>) => void | Promise<void>;
|
|
181
|
+
/** @description Interceptor to be called when an error response is received from the api. */
|
|
182
|
+
onResponseError?: (responseErrorContext: ResponseErrorContext<TBaseErrorData>) => void | Promise<void>;
|
|
183
|
+
};
|
|
184
|
+
type ResponseContext<TData> = {
|
|
185
|
+
_: {
|
|
186
|
+
response: Response & {
|
|
187
|
+
data: TData;
|
|
188
|
+
};
|
|
189
|
+
request: $RequestOptions;
|
|
190
|
+
options: ExtraOptions;
|
|
191
|
+
};
|
|
192
|
+
}["_"];
|
|
193
|
+
type ResponseErrorContext<TErrorData> = {
|
|
194
|
+
_: {
|
|
195
|
+
response: Response & {
|
|
196
|
+
errorData: TErrorData;
|
|
197
|
+
};
|
|
198
|
+
request: $RequestOptions;
|
|
199
|
+
options: ExtraOptions;
|
|
200
|
+
};
|
|
201
|
+
}["_"];
|
|
202
|
+
interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = undefined> extends Omit<RequestInit, "method" | "body">, ExtraOptions<TData, TErrorData, TResultMode> {
|
|
203
|
+
}
|
|
204
|
+
interface BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = undefined> extends FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode> {
|
|
205
|
+
}
|
|
206
|
+
type ApiSuccessVariant<TData> = {
|
|
207
|
+
data: TData;
|
|
208
|
+
error: null;
|
|
209
|
+
response: Response;
|
|
210
|
+
};
|
|
211
|
+
type PossibleErrors = "AbortError" | "TimeoutError" | "SyntaxError" | "TypeError" | "Error" | "UnknownError";
|
|
212
|
+
type ApiErrorVariant<TErrorData> = {
|
|
213
|
+
data: null;
|
|
214
|
+
error: {
|
|
215
|
+
errorName: "HTTPError";
|
|
216
|
+
errorData: TErrorData;
|
|
217
|
+
message: string;
|
|
218
|
+
};
|
|
219
|
+
response: Response;
|
|
220
|
+
} | {
|
|
221
|
+
data: null;
|
|
222
|
+
error: {
|
|
223
|
+
errorName: PossibleErrors;
|
|
224
|
+
message: string;
|
|
225
|
+
};
|
|
226
|
+
response: null;
|
|
227
|
+
};
|
|
228
|
+
type ResultModeMap<TData = unknown, TErrorData = unknown> = {
|
|
229
|
+
all: ApiSuccessVariant<TData> | ApiErrorVariant<TErrorData>;
|
|
230
|
+
onlySuccess: ApiSuccessVariant<TData>["data"];
|
|
231
|
+
onlyError: ApiErrorVariant<TErrorData>["error"];
|
|
232
|
+
onlyResponse: Response;
|
|
233
|
+
};
|
|
234
|
+
type ResultModeUnion = {
|
|
235
|
+
_: {
|
|
236
|
+
[Key in keyof ResultModeMap]: Key;
|
|
237
|
+
}[keyof ResultModeMap] | undefined;
|
|
238
|
+
}["_"];
|
|
239
|
+
type GetCallApiResult<TData, TErrorData, TResultMode> = TResultMode extends NonNullable<ResultModeUnion> ? ResultModeMap<TData, TErrorData>[TResultMode] : ResultModeMap<TData, TErrorData>["all"];
|
|
240
|
+
|
|
241
|
+
export { type $RequestOptions as $, type BaseConfig as B, type ExtraOptions as E, type FetchConfig as F, type GetCallApiResult as G, HTTPError as H, type ResultModeUnion as R, type ResponseContext as a, type ResponseErrorContext as b, isHTTPErrorInstance as c, defaultRetryCodes as d, defaultRetryMethods as e, fetchSpecificKeys as f, getResponseData as g, handleResponseType as h, isHTTPError as i, $resolveErrorResult as j, mergeUrlWithParams as m, objectifyHeaders as o, resolveSuccessResult as r, splitConfig as s, toQueryString as t, waitUntil as w };
|