@zayne-labs/callapi 0.0.1 → 0.0.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/createFetchClient.cjs +9 -0
- package/dist/createFetchClient.cjs.map +1 -0
- package/dist/createFetchClient.d.cts +21 -0
- package/dist/createFetchClient.d.ts +21 -0
- package/dist/createFetchClient.js +7 -0
- package/dist/createFetchClient.js.map +1 -0
- package/dist/index.d.cts +2 -139
- package/dist/index.d.ts +2 -139
- package/dist/types-Cf2V09St.d.cts +147 -0
- package/dist/types-Cf2V09St.d.ts +147 -0
- package/dist/utils.cjs +23 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +5 -0
- package/dist/utils.js.map +1 -0
- package/package.json +4 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var utils = require('./utils');
|
|
4
|
+
|
|
5
|
+
const m=C=>{const l=new Map,[D,A]=utils.splitConfig(C??{}),{headers:p,signal:w,...M}=D,o=async(s,f)=>{const[q,S]=utils.splitConfig(f??{}),e={bodySerializer:JSON.stringify,responseType:"json",baseURL:"",retries:0,retryDelay:0,retryCodes:utils.defaultRetryCodes,retryMethods:utils.defaultRetryMethods,defaultErrorMessage:"Failed to fetch data from server!",cancelRedundantRequests:!0,...A,...S},{signal:O=w,body:a,headers:T,...x}=q,g=l.get(s);if(g&&e.cancelRedundantRequests){const t=new DOMException("Cancelled the previous unfinished request","AbortError");g.abort(t);}const c=new AbortController;l.set(s,c);const B=e.timeout?AbortSignal.timeout(e.timeout):null,E=AbortSignal.any([c.signal,B??c.signal,O??c.signal]),n={signal:E,method:"GET",body:utils.isObject(a)?e.bodySerializer(a):a,headers:p||T||utils.isObject(a)?{...utils.isObject(a)&&{"Content-Type":"application/json",Accept:"application/json"},...utils.isFormData(a)&&{"Content-Type":"multipart/form-data"},...utils.objectifyHeaders(p),...utils.objectifyHeaders(T)}:void 0,...M,...x};try{await e.onRequest?.({request:n,options:e});const t=await fetch(`${e.baseURL}${utils.mergeUrlWithParams(s,e.query)}`,n);if(!E.aborted&&e.retries!==0&&!t.ok&&e.retryCodes.includes(t.status)&&e.retryMethods.includes(n.method))return await utils.wait(e.retryDelay),await o(s,{...f,retries:e.retries-1});if(!t.ok){const u=await utils.getResponseData(t,e.responseType,e.responseParser);throw new utils.HTTPError({response:{...t,errorData:u},defaultErrorMessage:e.defaultErrorMessage})}const r=await utils.getResponseData(t,e.responseType,e.responseParser);return await e.onResponse?.({response:{...t.clone(),data:r},request:n,options:e}),utils.resolveSuccessResult({successData:r,response:t.clone(),options:e})}catch(t){const i=utils.$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"),i({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"),i({message:r})}if(utils.isHTTPErrorInstance(t)){const{errorData:r,...u}=t.response;return await e.onResponseError?.({response:{...u.clone(),errorData:r},request:n,options:e}),i({errorData:r,response:u.clone(),message:r?.message})}return await e.onRequestError?.({request:n,error:t,options:e}),i()}finally{l.delete(s);}};return o.create=m,o.isHTTPErrorInfo=utils.isHTTPErrorInfo,o.isHTTPErrorInstance=utils.isHTTPErrorInstance,o.cancel=s=>l.get(s)?.abort(),o},G=m();var k=G;
|
|
6
|
+
|
|
7
|
+
module.exports = k;
|
|
8
|
+
//# sourceMappingURL=out.js.map
|
|
9
|
+
//# sourceMappingURL=createFetchClient.cjs.map
|
|
@@ -0,0 +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.clone(), 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: response.clone(), 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.clone(), 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: response.clone(),\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"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { F as FetchConfig, G as GetCallApiResult, B as BaseConfig, H as HTTPError } from './types-Cf2V09St.cjs';
|
|
2
|
+
|
|
3
|
+
declare const callApi: {
|
|
4
|
+
<TData = unknown, TErrorData = unknown, TResultMode extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = undefined>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode> | undefined): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
5
|
+
create: <TBaseData, TBaseErrorData, TBaseResultMode extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
6
|
+
<TData_1 = TBaseData, TErrorData_1 = TBaseErrorData, TResultMode_1 extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = TBaseResultMode>(url: string, config?: FetchConfig<TData_1, TErrorData_1, TResultMode_1> | undefined): Promise<GetCallApiResult<TData_1, TErrorData_1, TResultMode_1>>;
|
|
7
|
+
create: any;
|
|
8
|
+
isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
9
|
+
errorName: "HTTPError";
|
|
10
|
+
};
|
|
11
|
+
isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
12
|
+
cancel(url: string): void | undefined;
|
|
13
|
+
};
|
|
14
|
+
isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
15
|
+
errorName: "HTTPError";
|
|
16
|
+
};
|
|
17
|
+
isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
18
|
+
cancel(url: string): void | undefined;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { callApi as default };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { F as FetchConfig, G as GetCallApiResult, B as BaseConfig, H as HTTPError } from './types-Cf2V09St.js';
|
|
2
|
+
|
|
3
|
+
declare const callApi: {
|
|
4
|
+
<TData = unknown, TErrorData = unknown, TResultMode extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = undefined>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode> | undefined): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
5
|
+
create: <TBaseData, TBaseErrorData, TBaseResultMode extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
6
|
+
<TData_1 = TBaseData, TErrorData_1 = TBaseErrorData, TResultMode_1 extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = TBaseResultMode>(url: string, config?: FetchConfig<TData_1, TErrorData_1, TResultMode_1> | undefined): Promise<GetCallApiResult<TData_1, TErrorData_1, TResultMode_1>>;
|
|
7
|
+
create: any;
|
|
8
|
+
isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
9
|
+
errorName: "HTTPError";
|
|
10
|
+
};
|
|
11
|
+
isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
12
|
+
cancel(url: string): void | undefined;
|
|
13
|
+
};
|
|
14
|
+
isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
15
|
+
errorName: "HTTPError";
|
|
16
|
+
};
|
|
17
|
+
isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
18
|
+
cancel(url: string): void | undefined;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { callApi as default };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { splitConfig, isHTTPErrorInfo, isHTTPErrorInstance, defaultRetryCodes, defaultRetryMethods, isObject, isFormData, objectifyHeaders, mergeUrlWithParams, wait, getResponseData, HTTPError, resolveSuccessResult, $resolveErrorResult } from './utils';
|
|
2
|
+
|
|
3
|
+
const m=C=>{const l=new Map,[D,A]=splitConfig(C??{}),{headers:p,signal:w,...M}=D,o=async(s,f)=>{const[q,S]=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,...A,...S},{signal:O=w,body:a,headers:T,...x}=q,g=l.get(s);if(g&&e.cancelRedundantRequests){const t=new DOMException("Cancelled the previous unfinished request","AbortError");g.abort(t);}const c=new AbortController;l.set(s,c);const B=e.timeout?AbortSignal.timeout(e.timeout):null,E=AbortSignal.any([c.signal,B??c.signal,O??c.signal]),n={signal:E,method:"GET",body:isObject(a)?e.bodySerializer(a):a,headers:p||T||isObject(a)?{...isObject(a)&&{"Content-Type":"application/json",Accept:"application/json"},...isFormData(a)&&{"Content-Type":"multipart/form-data"},...objectifyHeaders(p),...objectifyHeaders(T)}:void 0,...M,...x};try{await e.onRequest?.({request:n,options:e});const t=await fetch(`${e.baseURL}${mergeUrlWithParams(s,e.query)}`,n);if(!E.aborted&&e.retries!==0&&!t.ok&&e.retryCodes.includes(t.status)&&e.retryMethods.includes(n.method))return await wait(e.retryDelay),await o(s,{...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.clone(),data:r},request:n,options:e}),resolveSuccessResult({successData:r,response:t.clone(),options:e})}catch(t){const i=$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"),i({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"),i({message:r})}if(isHTTPErrorInstance(t)){const{errorData:r,...u}=t.response;return await e.onResponseError?.({response:{...u.clone(),errorData:r},request:n,options:e}),i({errorData:r,response:u.clone(),message:r?.message})}return await e.onRequestError?.({request:n,error:t,options:e}),i()}finally{l.delete(s);}};return o.create=m,o.isHTTPErrorInfo=isHTTPErrorInfo,o.isHTTPErrorInstance=isHTTPErrorInstance,o.cancel=s=>l.get(s)?.abort(),o},G=m();var k=G;
|
|
4
|
+
|
|
5
|
+
export { k as default };
|
|
6
|
+
//# sourceMappingURL=out.js.map
|
|
7
|
+
//# sourceMappingURL=createFetchClient.js.map
|
|
@@ -0,0 +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.clone(), 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: response.clone(), 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.clone(), 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: response.clone(),\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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,139 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
};
|
|
4
|
-
type AnyNumber = number & {
|
|
5
|
-
placeholder?: never;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
declare const fetchSpecificKeys: ("headers" | "body" | "method" | "cache" | "credentials" | "integrity" | "keepalive" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
|
|
9
|
-
declare const handleResponseType: <TResponse>(response: Response, parser?: Required<ExtraOptions>["responseParser"]) => {
|
|
10
|
-
json: () => Promise<TResponse>;
|
|
11
|
-
arrayBuffer: () => Promise<TResponse>;
|
|
12
|
-
blob: () => Promise<TResponse>;
|
|
13
|
-
formData: () => Promise<TResponse>;
|
|
14
|
-
text: () => Promise<TResponse>;
|
|
15
|
-
};
|
|
16
|
-
declare const isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
17
|
-
errorName: "HTTPError";
|
|
18
|
-
};
|
|
19
|
-
type ErrorDetails<TErrorResponse> = {
|
|
20
|
-
response: Response & {
|
|
21
|
-
errorData: TErrorResponse;
|
|
22
|
-
};
|
|
23
|
-
defaultErrorMessage: string;
|
|
24
|
-
};
|
|
25
|
-
type ErrorOptions = {
|
|
26
|
-
cause?: unknown;
|
|
27
|
-
};
|
|
28
|
-
declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {
|
|
29
|
-
response: ErrorDetails<TErrorResponse>["response"];
|
|
30
|
-
name: "HTTPError";
|
|
31
|
-
isHTTPError: boolean;
|
|
32
|
-
constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
|
|
33
|
-
}
|
|
34
|
-
declare const isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
35
|
-
|
|
36
|
-
type $RequestConfig = Pick<FetchConfig, (typeof fetchSpecificKeys)[number]>;
|
|
37
|
-
type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = ResultStyleUnion> = {
|
|
38
|
-
body?: Record<string, unknown> | RequestInit["body"];
|
|
39
|
-
method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | AnyString;
|
|
40
|
-
query?: Record<string, string | number | boolean>;
|
|
41
|
-
bodySerializer?: (bodyData: Record<string, unknown>) => string;
|
|
42
|
-
responseParser?: {
|
|
43
|
-
(data: string): unknown;
|
|
44
|
-
<TData>(data: string): TData;
|
|
45
|
-
};
|
|
46
|
-
resultMode?: TBaseResultMode;
|
|
47
|
-
cancelRedundantRequests?: boolean;
|
|
48
|
-
baseURL?: string;
|
|
49
|
-
timeout?: number;
|
|
50
|
-
defaultErrorMessage?: string;
|
|
51
|
-
throwOnError?: boolean | ((error?: Error | HTTPError<TBaseErrorData>) => boolean);
|
|
52
|
-
responseType?: keyof ReturnType<typeof handleResponseType>;
|
|
53
|
-
retries?: number;
|
|
54
|
-
retryDelay?: number;
|
|
55
|
-
retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
|
|
56
|
-
retryMethods?: Array<"GET" | "POST" | "PATCH" | "DELETE" | AnyString>;
|
|
57
|
-
meta?: Record<string, unknown>;
|
|
58
|
-
onRequest?: (requestContext: {
|
|
59
|
-
request: $RequestConfig;
|
|
60
|
-
options: ExtraOptions;
|
|
61
|
-
}) => void | Promise<void>;
|
|
62
|
-
onRequestError?: (requestContext: {
|
|
63
|
-
request: $RequestConfig;
|
|
64
|
-
error: Error;
|
|
65
|
-
options: ExtraOptions;
|
|
66
|
-
}) => void | Promise<void>;
|
|
67
|
-
onResponse?: (successContext: {
|
|
68
|
-
request: $RequestConfig;
|
|
69
|
-
response: Response & {
|
|
70
|
-
data: TBaseData;
|
|
71
|
-
};
|
|
72
|
-
options: ExtraOptions;
|
|
73
|
-
}) => void | Promise<void>;
|
|
74
|
-
onResponseError?: (errorContext: {
|
|
75
|
-
request: $RequestConfig;
|
|
76
|
-
response: Response & {
|
|
77
|
-
errorData: TBaseErrorData;
|
|
78
|
-
};
|
|
79
|
-
options: ExtraOptions;
|
|
80
|
-
}) => void | Promise<void>;
|
|
81
|
-
};
|
|
82
|
-
interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultStyleUnion = undefined> extends Omit<RequestInit, "method" | "body">, ExtraOptions<TData, TErrorData, TResultMode> {
|
|
83
|
-
}
|
|
84
|
-
interface BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = undefined> extends Omit<FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode>, "body"> {
|
|
85
|
-
}
|
|
86
|
-
type ApiSuccessVariant<TData> = {
|
|
87
|
-
dataInfo: TData;
|
|
88
|
-
errorInfo: null;
|
|
89
|
-
response: Response;
|
|
90
|
-
};
|
|
91
|
-
type PossibleErrors = "AbortError" | "TimeoutError" | "SyntaxError" | "TypeError" | "Error" | "UnknownError";
|
|
92
|
-
type ApiErrorVariant<TErrorData> = {
|
|
93
|
-
dataInfo: null;
|
|
94
|
-
errorInfo: {
|
|
95
|
-
errorName: "HTTPError";
|
|
96
|
-
errorData: TErrorData;
|
|
97
|
-
message: string;
|
|
98
|
-
};
|
|
99
|
-
response: Response;
|
|
100
|
-
} | {
|
|
101
|
-
dataInfo: null;
|
|
102
|
-
errorInfo: {
|
|
103
|
-
errorName: PossibleErrors;
|
|
104
|
-
message: string;
|
|
105
|
-
};
|
|
106
|
-
response: null;
|
|
107
|
-
};
|
|
108
|
-
type ResultStyleMap<TData = unknown, TErrorData = unknown> = {
|
|
109
|
-
all: ApiSuccessVariant<TData> | ApiErrorVariant<TErrorData>;
|
|
110
|
-
onlySuccess: TData;
|
|
111
|
-
onlyError: TErrorData;
|
|
112
|
-
onlyResponse: Response;
|
|
113
|
-
};
|
|
114
|
-
type ResultStyleUnion = {
|
|
115
|
-
_: {
|
|
116
|
-
[Key in keyof ResultStyleMap]: Key;
|
|
117
|
-
}[keyof ResultStyleMap] | undefined;
|
|
118
|
-
}["_"];
|
|
119
|
-
type GetCallApiResult<TData, TErrorData, TResultMode> = TResultMode extends NonNullable<ResultStyleUnion> ? ResultStyleMap<TData, TErrorData>[TResultMode] : ResultStyleMap<TData, TErrorData>["all"];
|
|
120
|
-
|
|
121
|
-
declare const callApi: {
|
|
122
|
-
<TData = unknown, TErrorData = unknown, TResultMode extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = undefined>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode> | undefined): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
123
|
-
create: <TBaseData, TBaseErrorData, TBaseResultMode extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
124
|
-
<TData_1 = TBaseData, TErrorData_1 = TBaseErrorData, TResultMode_1 extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = TBaseResultMode>(url: string, config?: FetchConfig<TData_1, TErrorData_1, TResultMode_1> | undefined): Promise<GetCallApiResult<TData_1, TErrorData_1, TResultMode_1>>;
|
|
125
|
-
create: any;
|
|
126
|
-
isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
127
|
-
errorName: "HTTPError";
|
|
128
|
-
};
|
|
129
|
-
isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
130
|
-
cancel(url: string): void | undefined;
|
|
131
|
-
};
|
|
132
|
-
isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
133
|
-
errorName: "HTTPError";
|
|
134
|
-
};
|
|
135
|
-
isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
136
|
-
cancel(url: string): void | undefined;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export { type BaseConfig, type FetchConfig, HTTPError, callApi, isHTTPErrorInfo, isHTTPErrorInstance };
|
|
1
|
+
export { default as callApi } from './createFetchClient.cjs';
|
|
2
|
+
export { B as BaseConfig, F as FetchConfig, H as HTTPError, i as isHTTPErrorInfo, a as isHTTPErrorInstance } from './types-Cf2V09St.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,139 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
};
|
|
4
|
-
type AnyNumber = number & {
|
|
5
|
-
placeholder?: never;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
declare const fetchSpecificKeys: ("headers" | "body" | "method" | "cache" | "credentials" | "integrity" | "keepalive" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
|
|
9
|
-
declare const handleResponseType: <TResponse>(response: Response, parser?: Required<ExtraOptions>["responseParser"]) => {
|
|
10
|
-
json: () => Promise<TResponse>;
|
|
11
|
-
arrayBuffer: () => Promise<TResponse>;
|
|
12
|
-
blob: () => Promise<TResponse>;
|
|
13
|
-
formData: () => Promise<TResponse>;
|
|
14
|
-
text: () => Promise<TResponse>;
|
|
15
|
-
};
|
|
16
|
-
declare const isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
17
|
-
errorName: "HTTPError";
|
|
18
|
-
};
|
|
19
|
-
type ErrorDetails<TErrorResponse> = {
|
|
20
|
-
response: Response & {
|
|
21
|
-
errorData: TErrorResponse;
|
|
22
|
-
};
|
|
23
|
-
defaultErrorMessage: string;
|
|
24
|
-
};
|
|
25
|
-
type ErrorOptions = {
|
|
26
|
-
cause?: unknown;
|
|
27
|
-
};
|
|
28
|
-
declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {
|
|
29
|
-
response: ErrorDetails<TErrorResponse>["response"];
|
|
30
|
-
name: "HTTPError";
|
|
31
|
-
isHTTPError: boolean;
|
|
32
|
-
constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
|
|
33
|
-
}
|
|
34
|
-
declare const isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
35
|
-
|
|
36
|
-
type $RequestConfig = Pick<FetchConfig, (typeof fetchSpecificKeys)[number]>;
|
|
37
|
-
type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = ResultStyleUnion> = {
|
|
38
|
-
body?: Record<string, unknown> | RequestInit["body"];
|
|
39
|
-
method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | AnyString;
|
|
40
|
-
query?: Record<string, string | number | boolean>;
|
|
41
|
-
bodySerializer?: (bodyData: Record<string, unknown>) => string;
|
|
42
|
-
responseParser?: {
|
|
43
|
-
(data: string): unknown;
|
|
44
|
-
<TData>(data: string): TData;
|
|
45
|
-
};
|
|
46
|
-
resultMode?: TBaseResultMode;
|
|
47
|
-
cancelRedundantRequests?: boolean;
|
|
48
|
-
baseURL?: string;
|
|
49
|
-
timeout?: number;
|
|
50
|
-
defaultErrorMessage?: string;
|
|
51
|
-
throwOnError?: boolean | ((error?: Error | HTTPError<TBaseErrorData>) => boolean);
|
|
52
|
-
responseType?: keyof ReturnType<typeof handleResponseType>;
|
|
53
|
-
retries?: number;
|
|
54
|
-
retryDelay?: number;
|
|
55
|
-
retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
|
|
56
|
-
retryMethods?: Array<"GET" | "POST" | "PATCH" | "DELETE" | AnyString>;
|
|
57
|
-
meta?: Record<string, unknown>;
|
|
58
|
-
onRequest?: (requestContext: {
|
|
59
|
-
request: $RequestConfig;
|
|
60
|
-
options: ExtraOptions;
|
|
61
|
-
}) => void | Promise<void>;
|
|
62
|
-
onRequestError?: (requestContext: {
|
|
63
|
-
request: $RequestConfig;
|
|
64
|
-
error: Error;
|
|
65
|
-
options: ExtraOptions;
|
|
66
|
-
}) => void | Promise<void>;
|
|
67
|
-
onResponse?: (successContext: {
|
|
68
|
-
request: $RequestConfig;
|
|
69
|
-
response: Response & {
|
|
70
|
-
data: TBaseData;
|
|
71
|
-
};
|
|
72
|
-
options: ExtraOptions;
|
|
73
|
-
}) => void | Promise<void>;
|
|
74
|
-
onResponseError?: (errorContext: {
|
|
75
|
-
request: $RequestConfig;
|
|
76
|
-
response: Response & {
|
|
77
|
-
errorData: TBaseErrorData;
|
|
78
|
-
};
|
|
79
|
-
options: ExtraOptions;
|
|
80
|
-
}) => void | Promise<void>;
|
|
81
|
-
};
|
|
82
|
-
interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultStyleUnion = undefined> extends Omit<RequestInit, "method" | "body">, ExtraOptions<TData, TErrorData, TResultMode> {
|
|
83
|
-
}
|
|
84
|
-
interface BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = undefined> extends Omit<FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode>, "body"> {
|
|
85
|
-
}
|
|
86
|
-
type ApiSuccessVariant<TData> = {
|
|
87
|
-
dataInfo: TData;
|
|
88
|
-
errorInfo: null;
|
|
89
|
-
response: Response;
|
|
90
|
-
};
|
|
91
|
-
type PossibleErrors = "AbortError" | "TimeoutError" | "SyntaxError" | "TypeError" | "Error" | "UnknownError";
|
|
92
|
-
type ApiErrorVariant<TErrorData> = {
|
|
93
|
-
dataInfo: null;
|
|
94
|
-
errorInfo: {
|
|
95
|
-
errorName: "HTTPError";
|
|
96
|
-
errorData: TErrorData;
|
|
97
|
-
message: string;
|
|
98
|
-
};
|
|
99
|
-
response: Response;
|
|
100
|
-
} | {
|
|
101
|
-
dataInfo: null;
|
|
102
|
-
errorInfo: {
|
|
103
|
-
errorName: PossibleErrors;
|
|
104
|
-
message: string;
|
|
105
|
-
};
|
|
106
|
-
response: null;
|
|
107
|
-
};
|
|
108
|
-
type ResultStyleMap<TData = unknown, TErrorData = unknown> = {
|
|
109
|
-
all: ApiSuccessVariant<TData> | ApiErrorVariant<TErrorData>;
|
|
110
|
-
onlySuccess: TData;
|
|
111
|
-
onlyError: TErrorData;
|
|
112
|
-
onlyResponse: Response;
|
|
113
|
-
};
|
|
114
|
-
type ResultStyleUnion = {
|
|
115
|
-
_: {
|
|
116
|
-
[Key in keyof ResultStyleMap]: Key;
|
|
117
|
-
}[keyof ResultStyleMap] | undefined;
|
|
118
|
-
}["_"];
|
|
119
|
-
type GetCallApiResult<TData, TErrorData, TResultMode> = TResultMode extends NonNullable<ResultStyleUnion> ? ResultStyleMap<TData, TErrorData>[TResultMode] : ResultStyleMap<TData, TErrorData>["all"];
|
|
120
|
-
|
|
121
|
-
declare const callApi: {
|
|
122
|
-
<TData = unknown, TErrorData = unknown, TResultMode extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = undefined>(url: string, config?: FetchConfig<TData, TErrorData, TResultMode> | undefined): Promise<GetCallApiResult<TData, TErrorData, TResultMode>>;
|
|
123
|
-
create: <TBaseData, TBaseErrorData, TBaseResultMode extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
|
|
124
|
-
<TData_1 = TBaseData, TErrorData_1 = TBaseErrorData, TResultMode_1 extends "all" | "onlySuccess" | "onlyError" | "onlyResponse" | undefined = TBaseResultMode>(url: string, config?: FetchConfig<TData_1, TErrorData_1, TResultMode_1> | undefined): Promise<GetCallApiResult<TData_1, TErrorData_1, TResultMode_1>>;
|
|
125
|
-
create: any;
|
|
126
|
-
isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
127
|
-
errorName: "HTTPError";
|
|
128
|
-
};
|
|
129
|
-
isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
130
|
-
cancel(url: string): void | undefined;
|
|
131
|
-
};
|
|
132
|
-
isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
133
|
-
errorName: "HTTPError";
|
|
134
|
-
};
|
|
135
|
-
isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
136
|
-
cancel(url: string): void | undefined;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export { type BaseConfig, type FetchConfig, HTTPError, callApi, isHTTPErrorInfo, isHTTPErrorInstance };
|
|
1
|
+
export { default as callApi } from './createFetchClient.js';
|
|
2
|
+
export { B as BaseConfig, F as FetchConfig, H as HTTPError, i as isHTTPErrorInfo, a as isHTTPErrorInstance } from './types-Cf2V09St.js';
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
type AnyString = string & {
|
|
2
|
+
placeholder?: never;
|
|
3
|
+
};
|
|
4
|
+
type AnyNumber = number & {
|
|
5
|
+
placeholder?: never;
|
|
6
|
+
};
|
|
7
|
+
type AnyFunction = (...args: any[]) => any;
|
|
8
|
+
|
|
9
|
+
declare const mergeUrlWithParams: (url: string, params: ExtraOptions["query"]) => string;
|
|
10
|
+
declare const objectifyHeaders: (headers: RequestInit["headers"]) => Record<string, string> | undefined;
|
|
11
|
+
declare const defaultRetryCodes: Required<BaseConfig>["retryCodes"];
|
|
12
|
+
declare const defaultRetryMethods: Required<BaseConfig>["retryMethods"];
|
|
13
|
+
declare const fetchSpecificKeys: ("headers" | "body" | "method" | "cache" | "credentials" | "integrity" | "keepalive" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
|
|
14
|
+
declare const splitConfig: <TObject extends object>(config: TObject) => ["body" extends keyof TObject ? $RequestConfig : $BaseRequestConfig, ExtraOptions];
|
|
15
|
+
declare const handleResponseType: <TResponse>(response: Response, parser?: Required<ExtraOptions>["responseParser"]) => {
|
|
16
|
+
json: () => Promise<TResponse>;
|
|
17
|
+
arrayBuffer: () => Promise<TResponse>;
|
|
18
|
+
blob: () => Promise<TResponse>;
|
|
19
|
+
formData: () => Promise<TResponse>;
|
|
20
|
+
text: () => Promise<TResponse>;
|
|
21
|
+
};
|
|
22
|
+
declare const getResponseData: <TResponse>(response: Response, responseType: keyof ReturnType<typeof handleResponseType>, parser: ExtraOptions["responseParser"]) => Promise<TResponse>;
|
|
23
|
+
type DataInfo = {
|
|
24
|
+
successData: unknown;
|
|
25
|
+
options: ExtraOptions;
|
|
26
|
+
response: Response;
|
|
27
|
+
};
|
|
28
|
+
declare const resolveSuccessResult: <CallApiResult>(info: DataInfo) => CallApiResult;
|
|
29
|
+
declare const $resolveErrorResult: <CallApiResult>($info: {
|
|
30
|
+
error?: unknown;
|
|
31
|
+
options: ExtraOptions;
|
|
32
|
+
}) => (info?: {
|
|
33
|
+
response?: Response | undefined;
|
|
34
|
+
errorData?: unknown;
|
|
35
|
+
message?: string | undefined;
|
|
36
|
+
}) => CallApiResult;
|
|
37
|
+
declare const isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
38
|
+
errorName: "HTTPError";
|
|
39
|
+
};
|
|
40
|
+
type ErrorDetails<TErrorResponse> = {
|
|
41
|
+
response: Response & {
|
|
42
|
+
errorData: TErrorResponse;
|
|
43
|
+
};
|
|
44
|
+
defaultErrorMessage: string;
|
|
45
|
+
};
|
|
46
|
+
type ErrorOptions = {
|
|
47
|
+
cause?: unknown;
|
|
48
|
+
};
|
|
49
|
+
declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {
|
|
50
|
+
response: ErrorDetails<TErrorResponse>["response"];
|
|
51
|
+
name: "HTTPError";
|
|
52
|
+
isHTTPError: boolean;
|
|
53
|
+
constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
|
|
54
|
+
}
|
|
55
|
+
declare const isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
56
|
+
declare const wait: (delay: number) => Promise<unknown> | undefined;
|
|
57
|
+
declare const isFormData: (value: unknown) => boolean;
|
|
58
|
+
declare const isObject: <TObject extends Record<string, unknown>>(value: unknown) => value is TObject;
|
|
59
|
+
declare const isFunction: <TFunction extends AnyFunction>(value: unknown) => value is TFunction;
|
|
60
|
+
|
|
61
|
+
type $RequestConfig = Pick<FetchConfig, (typeof fetchSpecificKeys)[number]>;
|
|
62
|
+
type $BaseRequestConfig = Omit<$RequestConfig, "body">;
|
|
63
|
+
type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = ResultStyleUnion> = {
|
|
64
|
+
body?: Record<string, unknown> | RequestInit["body"];
|
|
65
|
+
method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | AnyString;
|
|
66
|
+
query?: Record<string, string | number | boolean>;
|
|
67
|
+
bodySerializer?: (bodyData: Record<string, unknown>) => string;
|
|
68
|
+
responseParser?: {
|
|
69
|
+
(data: string): unknown;
|
|
70
|
+
<TData>(data: string): TData;
|
|
71
|
+
};
|
|
72
|
+
resultMode?: TBaseResultMode;
|
|
73
|
+
cancelRedundantRequests?: boolean;
|
|
74
|
+
baseURL?: string;
|
|
75
|
+
timeout?: number;
|
|
76
|
+
defaultErrorMessage?: string;
|
|
77
|
+
throwOnError?: boolean | ((error?: Error | HTTPError<TBaseErrorData>) => boolean);
|
|
78
|
+
responseType?: keyof ReturnType<typeof handleResponseType>;
|
|
79
|
+
retries?: number;
|
|
80
|
+
retryDelay?: number;
|
|
81
|
+
retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
|
|
82
|
+
retryMethods?: Array<"GET" | "POST" | "PATCH" | "DELETE" | AnyString>;
|
|
83
|
+
meta?: Record<string, unknown>;
|
|
84
|
+
onRequest?: (requestContext: {
|
|
85
|
+
request: $RequestConfig;
|
|
86
|
+
options: ExtraOptions;
|
|
87
|
+
}) => void | Promise<void>;
|
|
88
|
+
onRequestError?: (requestContext: {
|
|
89
|
+
request: $RequestConfig;
|
|
90
|
+
error: Error;
|
|
91
|
+
options: ExtraOptions;
|
|
92
|
+
}) => void | Promise<void>;
|
|
93
|
+
onResponse?: (successContext: {
|
|
94
|
+
request: $RequestConfig;
|
|
95
|
+
response: Response & {
|
|
96
|
+
data: TBaseData;
|
|
97
|
+
};
|
|
98
|
+
options: ExtraOptions;
|
|
99
|
+
}) => void | Promise<void>;
|
|
100
|
+
onResponseError?: (errorContext: {
|
|
101
|
+
request: $RequestConfig;
|
|
102
|
+
response: Response & {
|
|
103
|
+
errorData: TBaseErrorData;
|
|
104
|
+
};
|
|
105
|
+
options: ExtraOptions;
|
|
106
|
+
}) => void | Promise<void>;
|
|
107
|
+
};
|
|
108
|
+
interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultStyleUnion = undefined> extends Omit<RequestInit, "method" | "body">, ExtraOptions<TData, TErrorData, TResultMode> {
|
|
109
|
+
}
|
|
110
|
+
interface BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = undefined> extends Omit<FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode>, "body"> {
|
|
111
|
+
}
|
|
112
|
+
type ApiSuccessVariant<TData> = {
|
|
113
|
+
dataInfo: TData;
|
|
114
|
+
errorInfo: null;
|
|
115
|
+
response: Response;
|
|
116
|
+
};
|
|
117
|
+
type PossibleErrors = "AbortError" | "TimeoutError" | "SyntaxError" | "TypeError" | "Error" | "UnknownError";
|
|
118
|
+
type ApiErrorVariant<TErrorData> = {
|
|
119
|
+
dataInfo: null;
|
|
120
|
+
errorInfo: {
|
|
121
|
+
errorName: "HTTPError";
|
|
122
|
+
errorData: TErrorData;
|
|
123
|
+
message: string;
|
|
124
|
+
};
|
|
125
|
+
response: Response;
|
|
126
|
+
} | {
|
|
127
|
+
dataInfo: null;
|
|
128
|
+
errorInfo: {
|
|
129
|
+
errorName: PossibleErrors;
|
|
130
|
+
message: string;
|
|
131
|
+
};
|
|
132
|
+
response: null;
|
|
133
|
+
};
|
|
134
|
+
type ResultStyleMap<TData = unknown, TErrorData = unknown> = {
|
|
135
|
+
all: ApiSuccessVariant<TData> | ApiErrorVariant<TErrorData>;
|
|
136
|
+
onlySuccess: TData;
|
|
137
|
+
onlyError: TErrorData;
|
|
138
|
+
onlyResponse: Response;
|
|
139
|
+
};
|
|
140
|
+
type ResultStyleUnion = {
|
|
141
|
+
_: {
|
|
142
|
+
[Key in keyof ResultStyleMap]: Key;
|
|
143
|
+
}[keyof ResultStyleMap] | undefined;
|
|
144
|
+
}["_"];
|
|
145
|
+
type GetCallApiResult<TData, TErrorData, TResultMode> = TResultMode extends NonNullable<ResultStyleUnion> ? ResultStyleMap<TData, TErrorData>[TResultMode] : ResultStyleMap<TData, TErrorData>["all"];
|
|
146
|
+
|
|
147
|
+
export { $resolveErrorResult as $, type BaseConfig as B, type FetchConfig as F, type GetCallApiResult as G, HTTPError as H, isHTTPErrorInstance as a, defaultRetryMethods as b, isFormData as c, defaultRetryCodes as d, isObject as e, fetchSpecificKeys as f, getResponseData as g, handleResponseType as h, isHTTPErrorInfo as i, isFunction as j, mergeUrlWithParams as m, objectifyHeaders as o, resolveSuccessResult as r, splitConfig as s, wait as w };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
type AnyString = string & {
|
|
2
|
+
placeholder?: never;
|
|
3
|
+
};
|
|
4
|
+
type AnyNumber = number & {
|
|
5
|
+
placeholder?: never;
|
|
6
|
+
};
|
|
7
|
+
type AnyFunction = (...args: any[]) => any;
|
|
8
|
+
|
|
9
|
+
declare const mergeUrlWithParams: (url: string, params: ExtraOptions["query"]) => string;
|
|
10
|
+
declare const objectifyHeaders: (headers: RequestInit["headers"]) => Record<string, string> | undefined;
|
|
11
|
+
declare const defaultRetryCodes: Required<BaseConfig>["retryCodes"];
|
|
12
|
+
declare const defaultRetryMethods: Required<BaseConfig>["retryMethods"];
|
|
13
|
+
declare const fetchSpecificKeys: ("headers" | "body" | "method" | "cache" | "credentials" | "integrity" | "keepalive" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
|
|
14
|
+
declare const splitConfig: <TObject extends object>(config: TObject) => ["body" extends keyof TObject ? $RequestConfig : $BaseRequestConfig, ExtraOptions];
|
|
15
|
+
declare const handleResponseType: <TResponse>(response: Response, parser?: Required<ExtraOptions>["responseParser"]) => {
|
|
16
|
+
json: () => Promise<TResponse>;
|
|
17
|
+
arrayBuffer: () => Promise<TResponse>;
|
|
18
|
+
blob: () => Promise<TResponse>;
|
|
19
|
+
formData: () => Promise<TResponse>;
|
|
20
|
+
text: () => Promise<TResponse>;
|
|
21
|
+
};
|
|
22
|
+
declare const getResponseData: <TResponse>(response: Response, responseType: keyof ReturnType<typeof handleResponseType>, parser: ExtraOptions["responseParser"]) => Promise<TResponse>;
|
|
23
|
+
type DataInfo = {
|
|
24
|
+
successData: unknown;
|
|
25
|
+
options: ExtraOptions;
|
|
26
|
+
response: Response;
|
|
27
|
+
};
|
|
28
|
+
declare const resolveSuccessResult: <CallApiResult>(info: DataInfo) => CallApiResult;
|
|
29
|
+
declare const $resolveErrorResult: <CallApiResult>($info: {
|
|
30
|
+
error?: unknown;
|
|
31
|
+
options: ExtraOptions;
|
|
32
|
+
}) => (info?: {
|
|
33
|
+
response?: Response | undefined;
|
|
34
|
+
errorData?: unknown;
|
|
35
|
+
message?: string | undefined;
|
|
36
|
+
}) => CallApiResult;
|
|
37
|
+
declare const isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
|
|
38
|
+
errorName: "HTTPError";
|
|
39
|
+
};
|
|
40
|
+
type ErrorDetails<TErrorResponse> = {
|
|
41
|
+
response: Response & {
|
|
42
|
+
errorData: TErrorResponse;
|
|
43
|
+
};
|
|
44
|
+
defaultErrorMessage: string;
|
|
45
|
+
};
|
|
46
|
+
type ErrorOptions = {
|
|
47
|
+
cause?: unknown;
|
|
48
|
+
};
|
|
49
|
+
declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {
|
|
50
|
+
response: ErrorDetails<TErrorResponse>["response"];
|
|
51
|
+
name: "HTTPError";
|
|
52
|
+
isHTTPError: boolean;
|
|
53
|
+
constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
|
|
54
|
+
}
|
|
55
|
+
declare const isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
|
|
56
|
+
declare const wait: (delay: number) => Promise<unknown> | undefined;
|
|
57
|
+
declare const isFormData: (value: unknown) => boolean;
|
|
58
|
+
declare const isObject: <TObject extends Record<string, unknown>>(value: unknown) => value is TObject;
|
|
59
|
+
declare const isFunction: <TFunction extends AnyFunction>(value: unknown) => value is TFunction;
|
|
60
|
+
|
|
61
|
+
type $RequestConfig = Pick<FetchConfig, (typeof fetchSpecificKeys)[number]>;
|
|
62
|
+
type $BaseRequestConfig = Omit<$RequestConfig, "body">;
|
|
63
|
+
type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = ResultStyleUnion> = {
|
|
64
|
+
body?: Record<string, unknown> | RequestInit["body"];
|
|
65
|
+
method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | AnyString;
|
|
66
|
+
query?: Record<string, string | number | boolean>;
|
|
67
|
+
bodySerializer?: (bodyData: Record<string, unknown>) => string;
|
|
68
|
+
responseParser?: {
|
|
69
|
+
(data: string): unknown;
|
|
70
|
+
<TData>(data: string): TData;
|
|
71
|
+
};
|
|
72
|
+
resultMode?: TBaseResultMode;
|
|
73
|
+
cancelRedundantRequests?: boolean;
|
|
74
|
+
baseURL?: string;
|
|
75
|
+
timeout?: number;
|
|
76
|
+
defaultErrorMessage?: string;
|
|
77
|
+
throwOnError?: boolean | ((error?: Error | HTTPError<TBaseErrorData>) => boolean);
|
|
78
|
+
responseType?: keyof ReturnType<typeof handleResponseType>;
|
|
79
|
+
retries?: number;
|
|
80
|
+
retryDelay?: number;
|
|
81
|
+
retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
|
|
82
|
+
retryMethods?: Array<"GET" | "POST" | "PATCH" | "DELETE" | AnyString>;
|
|
83
|
+
meta?: Record<string, unknown>;
|
|
84
|
+
onRequest?: (requestContext: {
|
|
85
|
+
request: $RequestConfig;
|
|
86
|
+
options: ExtraOptions;
|
|
87
|
+
}) => void | Promise<void>;
|
|
88
|
+
onRequestError?: (requestContext: {
|
|
89
|
+
request: $RequestConfig;
|
|
90
|
+
error: Error;
|
|
91
|
+
options: ExtraOptions;
|
|
92
|
+
}) => void | Promise<void>;
|
|
93
|
+
onResponse?: (successContext: {
|
|
94
|
+
request: $RequestConfig;
|
|
95
|
+
response: Response & {
|
|
96
|
+
data: TBaseData;
|
|
97
|
+
};
|
|
98
|
+
options: ExtraOptions;
|
|
99
|
+
}) => void | Promise<void>;
|
|
100
|
+
onResponseError?: (errorContext: {
|
|
101
|
+
request: $RequestConfig;
|
|
102
|
+
response: Response & {
|
|
103
|
+
errorData: TBaseErrorData;
|
|
104
|
+
};
|
|
105
|
+
options: ExtraOptions;
|
|
106
|
+
}) => void | Promise<void>;
|
|
107
|
+
};
|
|
108
|
+
interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultStyleUnion = undefined> extends Omit<RequestInit, "method" | "body">, ExtraOptions<TData, TErrorData, TResultMode> {
|
|
109
|
+
}
|
|
110
|
+
interface BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = undefined> extends Omit<FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode>, "body"> {
|
|
111
|
+
}
|
|
112
|
+
type ApiSuccessVariant<TData> = {
|
|
113
|
+
dataInfo: TData;
|
|
114
|
+
errorInfo: null;
|
|
115
|
+
response: Response;
|
|
116
|
+
};
|
|
117
|
+
type PossibleErrors = "AbortError" | "TimeoutError" | "SyntaxError" | "TypeError" | "Error" | "UnknownError";
|
|
118
|
+
type ApiErrorVariant<TErrorData> = {
|
|
119
|
+
dataInfo: null;
|
|
120
|
+
errorInfo: {
|
|
121
|
+
errorName: "HTTPError";
|
|
122
|
+
errorData: TErrorData;
|
|
123
|
+
message: string;
|
|
124
|
+
};
|
|
125
|
+
response: Response;
|
|
126
|
+
} | {
|
|
127
|
+
dataInfo: null;
|
|
128
|
+
errorInfo: {
|
|
129
|
+
errorName: PossibleErrors;
|
|
130
|
+
message: string;
|
|
131
|
+
};
|
|
132
|
+
response: null;
|
|
133
|
+
};
|
|
134
|
+
type ResultStyleMap<TData = unknown, TErrorData = unknown> = {
|
|
135
|
+
all: ApiSuccessVariant<TData> | ApiErrorVariant<TErrorData>;
|
|
136
|
+
onlySuccess: TData;
|
|
137
|
+
onlyError: TErrorData;
|
|
138
|
+
onlyResponse: Response;
|
|
139
|
+
};
|
|
140
|
+
type ResultStyleUnion = {
|
|
141
|
+
_: {
|
|
142
|
+
[Key in keyof ResultStyleMap]: Key;
|
|
143
|
+
}[keyof ResultStyleMap] | undefined;
|
|
144
|
+
}["_"];
|
|
145
|
+
type GetCallApiResult<TData, TErrorData, TResultMode> = TResultMode extends NonNullable<ResultStyleUnion> ? ResultStyleMap<TData, TErrorData>[TResultMode] : ResultStyleMap<TData, TErrorData>["all"];
|
|
146
|
+
|
|
147
|
+
export { $resolveErrorResult as $, type BaseConfig as B, type FetchConfig as F, type GetCallApiResult as G, HTTPError as H, isHTTPErrorInstance as a, defaultRetryMethods as b, isFormData as c, defaultRetryCodes as d, isObject as e, fetchSpecificKeys as f, getResponseData as g, handleResponseType as h, isHTTPErrorInfo as i, isFunction as j, mergeUrlWithParams as m, objectifyHeaders as o, resolveSuccessResult as r, splitConfig as s, wait as w };
|
package/dist/utils.cjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const m=(e,r)=>{if(!r)return e;const o=new URLSearchParams(r).toString();return e.includes("?")&&!e.endsWith("?")?`${e}&${o}`:e.endsWith("?")?`${e}${o}`:`${e}?${o}`},b=e=>!e||i(e)?e:Object.fromEntries(d(e)?e:e.entries()),p={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"},g=Object.keys(p).map(Number),j=["GET"],c=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],l=(e,r)=>{const o=Object.entries(e).filter(([s])=>!r.includes(s));return Object.fromEntries(o)},T=(e,r)=>{const o=new Set(r),s=Object.entries(e).filter(([a])=>o.has(a));return Object.fromEntries(s)},x=e=>[T(e,c),l(e,c)],f=(e,r)=>({json:async()=>r?r(await e.text()):e.json(),arrayBuffer:()=>e.arrayBuffer(),blob:()=>e.blob(),formData:()=>e.formData(),text:()=>e.text()}),w=(e,r,o)=>{const t=f(e,o);if(!Object.hasOwn(t,r))throw new Error(`Invalid response type: ${r}`);return t[r]()},k=e=>{const{options:r,response:o,successData:t}=e,s={dataInfo:t,errorInfo:null,response:o};return r.resultMode===void 0||r.resultMode==="all"?s:{onlySuccess:s.dataInfo,onlyError:s.errorInfo,onlyResponse:s.response}[r.resultMode]},P=e=>{const{error:r,options:o}=e;return (s={})=>{const{errorData:n,message:a,response:u}=s;if(E(o.throwOnError)?o.throwOnError(r):o.throwOnError)throw r;return {dataInfo:null,errorInfo:{errorName:r?.name??"UnknownError",message:a??r?.message??o.defaultErrorMessage,...!!n&&{errorData:n}},response:u??null}}},A=e=>i(e)&&e.errorName==="HTTPError";class y extends Error{response;name="HTTPError";isHTTPError=!0;constructor(r,o){const{defaultErrorMessage:t,response:s}=r;super(s.errorData.message??t,o),this.response=s;}}const h=e=>e instanceof y||i(e)&&e.name==="HTTPError"&&e.isHTTPError===!0,C=e=>{if(e===0)return;const{promise:r,resolve:o}=Promise.withResolvers();return setTimeout(o,e),r},d=e=>Array.isArray(e),R=e=>e instanceof FormData,i=e=>typeof e=="object"&&e!==null&&!R(e)&&!Array.isArray(e),E=e=>typeof e=="function";
|
|
4
|
+
|
|
5
|
+
exports.$resolveErrorResult = P;
|
|
6
|
+
exports.HTTPError = y;
|
|
7
|
+
exports.defaultRetryCodes = g;
|
|
8
|
+
exports.defaultRetryMethods = j;
|
|
9
|
+
exports.fetchSpecificKeys = c;
|
|
10
|
+
exports.getResponseData = w;
|
|
11
|
+
exports.handleResponseType = f;
|
|
12
|
+
exports.isFormData = R;
|
|
13
|
+
exports.isFunction = E;
|
|
14
|
+
exports.isHTTPErrorInfo = A;
|
|
15
|
+
exports.isHTTPErrorInstance = h;
|
|
16
|
+
exports.isObject = i;
|
|
17
|
+
exports.mergeUrlWithParams = m;
|
|
18
|
+
exports.objectifyHeaders = b;
|
|
19
|
+
exports.resolveSuccessResult = k;
|
|
20
|
+
exports.splitConfig = x;
|
|
21
|
+
exports.wait = C;
|
|
22
|
+
//# sourceMappingURL=out.js.map
|
|
23
|
+
//# sourceMappingURL=utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts"],"names":["mergeUrlWithParams","url","params","paramsString","objectifyHeaders","headers","isObject","isArray","retryCodesLookup","defaultRetryCodes","defaultRetryMethods","fetchSpecificKeys","omitKeys","initialObject","keysToOmit","arrayFromFilteredObject","key","pickKeys","keysToPick","keysToPickSet","filteredArray","objectKey","splitConfig","config","handleResponseType","response","parser","getResponseData","responseType","RESPONSE_TYPE_LOOKUP","resolveSuccessResult","info","options","successData","apiDetails","$resolveErrorResult","$info","error","errorData","message","isFunction","isHTTPErrorInfo","errorInfo","HTTPError","errorDetails","errorOptions","defaultErrorMessage","isHTTPErrorInstance","wait","delay","promise","resolve","value","isFormData"],"mappings":"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","sourcesContent":["import type { AnyFunction } from \"./type-helpers\";\nimport type {\n\t$BaseRequestConfig,\n\t$RequestConfig,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = new URLSearchParams(params as Record<string, string>).toString();\n\n\tif (url.includes(\"?\") && !url.endsWith(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nconst omitKeys = <TObject extends Record<string, unknown>, const TOmitArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestConfig : $BaseRequestConfig, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser<TResponse>(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype DataInfo = {\n\tsuccessData: unknown;\n\toptions: ExtraOptions;\n\tresponse: Response;\n};\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = <CallApiResult>(info: DataInfo): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = { dataInfo: successData, errorInfo: null, response };\n\n\tif (options.resultMode === undefined || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlySuccess: apiDetails.dataInfo,\n\t\tonlyError: apiDetails.errorInfo,\n\t\tonlyResponse: apiDetails.response,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const $resolveErrorResult = <CallApiResult>($info: { error?: unknown; options: ExtraOptions }) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\tresponse?: Response;\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdataInfo: null,\n\t\t\terrorInfo: {\n\t\t\t\terrorName: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t\t...(Boolean(errorData) && { errorData }),\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\nexport const isHTTPErrorInfo = (\n\terrorInfo: Record<string, unknown> | null\n): errorInfo is { errorName: \"HTTPError\" } => isObject(errorInfo) && errorInfo.errorName === \"HTTPError\";\n\ntype ErrorDetails<TErrorResponse> = {\n\tresponse: Response & { errorData: TErrorResponse };\n\tdefaultErrorMessage: string;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\toverride name = \"HTTPError\" as const;\n\n\tisHTTPError = true;\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, response } = errorDetails;\n\n\t\tsuper((response.errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.response = response;\n\t}\n}\n\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError ||\n\t\t(isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const wait = (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\nconst isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isFormData = (value: unknown) => value instanceof FormData;\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn typeof value === \"object\" && value !== null && !isFormData(value) && !Array.isArray(value);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n"]}
|
package/dist/utils.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { $ as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, b as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, c as isFormData, j as isFunction, i as isHTTPErrorInfo, a as isHTTPErrorInstance, e as isObject, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, w as wait } from './types-Cf2V09St.cjs';
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { $ as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, b as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, c as isFormData, j as isFunction, i as isHTTPErrorInfo, a as isHTTPErrorInstance, e as isObject, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, w as wait } from './types-Cf2V09St.js';
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const m=(e,r)=>{if(!r)return e;const o=new URLSearchParams(r).toString();return e.includes("?")&&!e.endsWith("?")?`${e}&${o}`:e.endsWith("?")?`${e}${o}`:`${e}?${o}`},b=e=>!e||i(e)?e:Object.fromEntries(d(e)?e:e.entries()),p={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"},g=Object.keys(p).map(Number),j=["GET"],c=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],l=(e,r)=>{const o=Object.entries(e).filter(([s])=>!r.includes(s));return Object.fromEntries(o)},T=(e,r)=>{const o=new Set(r),s=Object.entries(e).filter(([a])=>o.has(a));return Object.fromEntries(s)},x=e=>[T(e,c),l(e,c)],f=(e,r)=>({json:async()=>r?r(await e.text()):e.json(),arrayBuffer:()=>e.arrayBuffer(),blob:()=>e.blob(),formData:()=>e.formData(),text:()=>e.text()}),w=(e,r,o)=>{const t=f(e,o);if(!Object.hasOwn(t,r))throw new Error(`Invalid response type: ${r}`);return t[r]()},k=e=>{const{options:r,response:o,successData:t}=e,s={dataInfo:t,errorInfo:null,response:o};return r.resultMode===void 0||r.resultMode==="all"?s:{onlySuccess:s.dataInfo,onlyError:s.errorInfo,onlyResponse:s.response}[r.resultMode]},P=e=>{const{error:r,options:o}=e;return (s={})=>{const{errorData:n,message:a,response:u}=s;if(E(o.throwOnError)?o.throwOnError(r):o.throwOnError)throw r;return {dataInfo:null,errorInfo:{errorName:r?.name??"UnknownError",message:a??r?.message??o.defaultErrorMessage,...!!n&&{errorData:n}},response:u??null}}},A=e=>i(e)&&e.errorName==="HTTPError";class y extends Error{response;name="HTTPError";isHTTPError=!0;constructor(r,o){const{defaultErrorMessage:t,response:s}=r;super(s.errorData.message??t,o),this.response=s;}}const h=e=>e instanceof y||i(e)&&e.name==="HTTPError"&&e.isHTTPError===!0,C=e=>{if(e===0)return;const{promise:r,resolve:o}=Promise.withResolvers();return setTimeout(o,e),r},d=e=>Array.isArray(e),R=e=>e instanceof FormData,i=e=>typeof e=="object"&&e!==null&&!R(e)&&!Array.isArray(e),E=e=>typeof e=="function";
|
|
2
|
+
|
|
3
|
+
export { P as $resolveErrorResult, y as HTTPError, g as defaultRetryCodes, j as defaultRetryMethods, c as fetchSpecificKeys, w as getResponseData, f as handleResponseType, R as isFormData, E as isFunction, A as isHTTPErrorInfo, h as isHTTPErrorInstance, i as isObject, m as mergeUrlWithParams, b as objectifyHeaders, k as resolveSuccessResult, x as splitConfig, C as wait };
|
|
4
|
+
//# sourceMappingURL=out.js.map
|
|
5
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts"],"names":["mergeUrlWithParams","url","params","paramsString","objectifyHeaders","headers","isObject","isArray","retryCodesLookup","defaultRetryCodes","defaultRetryMethods","fetchSpecificKeys","omitKeys","initialObject","keysToOmit","arrayFromFilteredObject","key","pickKeys","keysToPick","keysToPickSet","filteredArray","objectKey","splitConfig","config","handleResponseType","response","parser","getResponseData","responseType","RESPONSE_TYPE_LOOKUP","resolveSuccessResult","info","options","successData","apiDetails","$resolveErrorResult","$info","error","errorData","message","isFunction","isHTTPErrorInfo","errorInfo","HTTPError","errorDetails","errorOptions","defaultErrorMessage","isHTTPErrorInstance","wait","delay","promise","resolve","value","isFormData"],"mappings":"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","sourcesContent":["import type { AnyFunction } from \"./type-helpers\";\nimport type {\n\t$BaseRequestConfig,\n\t$RequestConfig,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = new URLSearchParams(params as Record<string, string>).toString();\n\n\tif (url.includes(\"?\") && !url.endsWith(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nconst omitKeys = <TObject extends Record<string, unknown>, const TOmitArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestConfig : $BaseRequestConfig, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser<TResponse>(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype DataInfo = {\n\tsuccessData: unknown;\n\toptions: ExtraOptions;\n\tresponse: Response;\n};\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = <CallApiResult>(info: DataInfo): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = { dataInfo: successData, errorInfo: null, response };\n\n\tif (options.resultMode === undefined || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlySuccess: apiDetails.dataInfo,\n\t\tonlyError: apiDetails.errorInfo,\n\t\tonlyResponse: apiDetails.response,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const $resolveErrorResult = <CallApiResult>($info: { error?: unknown; options: ExtraOptions }) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\tresponse?: Response;\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdataInfo: null,\n\t\t\terrorInfo: {\n\t\t\t\terrorName: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t\t...(Boolean(errorData) && { errorData }),\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\nexport const isHTTPErrorInfo = (\n\terrorInfo: Record<string, unknown> | null\n): errorInfo is { errorName: \"HTTPError\" } => isObject(errorInfo) && errorInfo.errorName === \"HTTPError\";\n\ntype ErrorDetails<TErrorResponse> = {\n\tresponse: Response & { errorData: TErrorResponse };\n\tdefaultErrorMessage: string;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\toverride name = \"HTTPError\" as const;\n\n\tisHTTPError = true;\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, response } = errorDetails;\n\n\t\tsuper((response.errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.response = response;\n\t}\n}\n\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError ||\n\t\t(isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const wait = (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\nconst isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isFormData = (value: unknown) => value instanceof FormData;\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn typeof value === \"object\" && value !== null && !isFormData(value) && !Array.isArray(value);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zayne-labs/callapi",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.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
|
"repository": "ryan-zayne/callApi",
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
"require": "./dist/index.cjs"
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
28
31
|
"files": [
|
|
29
32
|
"dist"
|
|
30
33
|
],
|