@zayne-labs/callapi 0.2.3 → 0.2.5

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 CHANGED
@@ -32,15 +32,15 @@ To do this, you first need to set your `script`'s type to `module`, then import
32
32
 
33
33
  ```html
34
34
  <script type="module">
35
- import { callApi } from "https://cdn.jsdelivr.net/npm/@zayne-labs/callapi/dist/index.js";
35
+ import { callApi } from "https://cdn.jsdelivr.net/npm/@zayne-labs/callapi/dist/src/index.min.js";
36
36
  </script>
37
37
  ```
38
38
 
39
39
  ## Quick Start
40
40
 
41
- You can use callApi just like a normal `fetch` function. The only difference is you don't have to write a `response.json` or `response.text`, you could just destructure the data and data directly.
41
+ You can use callApi just like a normal `fetch` function. The only difference is you don't have to write a `response.json` or `response.text`, you could just destructure the data and error directly.
42
42
 
43
- This also means that all options for the native fetch function are supported, and you can use the same syntax to send requests.
43
+ This also means that all options for the native fetch options are supported, and you can use the same syntax to send requests.
44
44
 
45
45
  ```js
46
46
  const { data, error } = await callApi("url", fetchOptions);
@@ -56,27 +56,39 @@ To see how to use callApi with typescript for extra autocomplete convenience, vi
56
56
 
57
57
  ## Supported response types
58
58
 
59
- CallApi supports all response types offered by the fetch api like `json`, `text`,`blob` etc, so you don't have to write `response.json()`, `response.text()` or `response.blob()`.
59
+ CallApi supports all response types offered by the fetch api like `json`, `text`,`blob`,`formData` etc, so you don't have to write `response.json()`, `response.text()`, `response.formData()` etc.
60
60
 
61
- It can configure the response type by passing in the `responseType` option and setting it to the appropriate type. By default it's set to `json`.
61
+ You can configure the response type you prefer by passing in the `responseType` option and setting it to the form you want the data from the response to be in. By default it's set to `json`.
62
62
 
63
63
  ```js
64
- const { data, error } = await callApi("url", { responseType: "json" });
64
+ // Json (default)
65
+ const { data } = await callApi("url", { responseType: "json" });
66
+ // Text
67
+ const { data } = await callApi("url", {responseType: "text"});
68
+ // Blob, etc
69
+ const { data } = await callApi("url", {responseType: "blob"});
70
+
71
+
72
+ // Doing this in fetch would imply:
73
+ const response = await fetch("some-url");
74
+
75
+ const data = await response.json(); // Or response.text() or response.blob() etc
65
76
  ```
66
77
 
67
78
  ## Easy error handling when using `async`/`await`
68
79
 
69
- CallApi lets you access all errors, both http errors and javascript errors, in an `error` object. This object contains the `errorName` (eg: TypeError, SyntaxError etx) and the error message as well.
80
+ CallApi lets you access all errors, both http errors and other regular javascript errors, in an `error` object. This object contains the `errorName` (eg: 'TypeError', 'SyntaxError' etc) and the error message as well.
70
81
 
71
- If the error is an http error, the `errorName` property will be set to "HTTPError" and the `error` object will also contain a property `errorData`.
82
+ If the error is an http error, the `errorName` property will be set to "HTTPError" and the `error` object will also have a property `errorData`.
72
83
 
73
- This property contains the error response data coming from the api. If the error is not an http error but some other error, the `errorData` property will be set to `null`.
84
+ This property would contains the error response data coming from the api. If the error is not an http error but some other error, the `errorData` property will be set to `null`.
74
85
 
75
86
  ```js
76
87
  const { data, error } = await callApi("some-url");
77
88
 
78
89
  console.log(error.errorName);
79
90
  console.log(error.message);
91
+ // Will be null if not an http error, else would contain the parsed error response data
80
92
  console.log(error.errorData);
81
93
  ```
82
94
 
@@ -88,11 +100,11 @@ For extra convenience with typescript, visit the [Typescript section](#usage-wit
88
100
 
89
101
  `CallApi` automatically cancels the previous requests if the same url is called again before the previous request is resolved. This essentially only lets the last request through, hence preventing dreaded race conditions.
90
102
 
91
- What this implies is that you can use `callApi` in a `useEffect` hook for instance and it will automatically cancel the previous request if the url is called again before the previous request is resolved 🤩.
103
+ What this implies is that you can use `callApi` in a `useEffect` hook for instance and it will automatically cancel the previous request if a request is made to the same URL again, effectively only letting the last request through 🤩.
92
104
 
93
- This behavior can be disabled if you don't like it, by passing in `{ cancelPreviousRequest: false }` to the fetch options.
105
+ This behavior can be disabled if you don't like it, by setting `{ cancelRedundantRequests: false }` in the fetch options.
94
106
 
95
- You can also cancel a request to a particular url by passing the url as a parameter to the cancel property attached to callApi.
107
+ You can also cancel a request to a particular url manually, by passing that url as an argument to the `cancel` method attached to callApi.
96
108
 
97
109
  ```js
98
110
  callApi("some-url");
@@ -179,17 +191,42 @@ callApi("some-url", { body: data });
179
191
 
180
192
  ## ✔️ Authorization header helpers
181
193
 
182
- If you provide callApi with an `auth` property, it will generate an Authorization Header for you.
194
+ If you provide callApi with an `auth` property, it will conveniently generate an Authorization Header for you.
183
195
 
184
196
  If you pass in a `string` (commonly for tokens) , it will generate a Bearer Auth.
185
197
 
198
+ But if you pass in an `object`, you would have two options to chose from:
199
+
200
+ - Use `bearer` option if you want to generate a Bearer Auth Header.
201
+ - Use `token` if you want to generate a Token Auth Header.
202
+
186
203
  ```js
204
+ // Passing a string
187
205
  callApi("some-url", { auth: "token12345" });
188
206
 
189
207
  // The above request can be written in Fetch like this:
190
208
  fetch("some-url", {
191
209
  headers: { Authorization: `Bearer token12345` },
192
210
  });
211
+
212
+ // Passing an object:
213
+
214
+ // For Bearer Auth
215
+ callApi("some-url", { auth: { bearer: "token12345" } });
216
+ // For Token Auth
217
+ callApi("some-url", { auth: { token: "token12345" } });
218
+
219
+ // The above requests can be written in Fetch like this:
220
+
221
+ // For Bearer Auth
222
+ fetch("some-url", {
223
+ headers: { Authorization: `Bearer token12345` },
224
+ });
225
+
226
+ // For Token Auth
227
+ fetch("some-url", {
228
+ headers: { Authorization: `Token token12345` },
229
+ });
193
230
  ```
194
231
 
195
232
  ## ✔️ Creating a callApi Instance
@@ -541,7 +578,7 @@ const callAnotherApi = callApi.create({
541
578
  - `retryDelay`: Delay between retries in milliseconds. (default: 500)
542
579
  - `retryCodes`: HTTP status codes that trigger a retry. (default: [409, 425, 429, 500, 502, 503, 504])
543
580
  - `retryMethods`: HTTP methods that are allowed to retry. (default: ["GET", "POST"])
544
- - `meta`: An optional field for additional information, typically used for logging or tracing.
581
+ - `meta`: An optional field that can contain additional information about a request, which could be helpful in differentiating between different requests in a shared interceptor.
545
582
  - `onRequest`: Interceptor called just before the request is made, allowing for modifications or additional operations.
546
583
  - `onRequestError`: Interceptor called when an error occurs during the fetch request.
547
584
  - `onResponse`: Interceptor called when a successful response is received from the API.
@@ -1,4 +1,4 @@
1
- import { R as ResultModeUnion, B as BaseConfig, F as FetchConfig, G as GetCallApiResult } from './types-DfUaOAyg.cjs';
1
+ import { R as ResultModeUnion, B as BaseConfig, F as FetchConfig, G as GetCallApiResult } from './types-CAxhtQRR.cjs';
2
2
  import './type-helpers-Dibitydy.cjs';
3
3
 
4
4
  declare const createFetchClient: <TBaseData, TBaseErrorData, TBaseResultMode extends ResultModeUnion = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
@@ -1,4 +1,4 @@
1
- import { R as ResultModeUnion, B as BaseConfig, F as FetchConfig, G as GetCallApiResult } from './types-D17lSUr9.js';
1
+ import { R as ResultModeUnion, B as BaseConfig, F as FetchConfig, G as GetCallApiResult } from './types-BFhLAZSM.js';
2
2
  import './type-helpers-Dibitydy.js';
3
3
 
4
4
  declare const createFetchClient: <TBaseData, TBaseErrorData, TBaseResultMode extends ResultModeUnion = undefined>(baseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>) => {
package/dist/index.d.cts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { callApi, createFetchClient } from './createFetchClient.cjs';
2
- export { $ as $RequestOptions, E as ExtraOptions, F as FetchConfig, H as HTTPError, a as ResponseContext, b as ResponseErrorContext, i as isHTTPError, c as isHTTPErrorInstance, t as toQueryString } from './types-DfUaOAyg.cjs';
2
+ export { $ as $RequestOptions, E as ExtraOptions, F as FetchConfig, H as HTTPError, a as ResponseContext, b as ResponseErrorContext, i as isHTTPError, c as isHTTPErrorInstance, t as toQueryString } from './types-CAxhtQRR.cjs';
3
3
  import './type-helpers-Dibitydy.cjs';
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { callApi, createFetchClient } from './createFetchClient.js';
2
- export { $ as $RequestOptions, E as ExtraOptions, F as FetchConfig, H as HTTPError, a as ResponseContext, b as ResponseErrorContext, i as isHTTPError, c as isHTTPErrorInstance, t as toQueryString } from './types-D17lSUr9.js';
2
+ export { $ as $RequestOptions, E as ExtraOptions, F as FetchConfig, H as HTTPError, a as ResponseContext, b as ResponseErrorContext, i as isHTTPError, c as isHTTPErrorInstance, t as toQueryString } from './types-BFhLAZSM.js';
3
3
  import './type-helpers-Dibitydy.js';
@@ -3,9 +3,9 @@
3
3
  var _typeof = require('./typeof');
4
4
  var utils = require('./utils');
5
5
 
6
- const b=m=>{const l=new Map,[D,C]=utils.splitConfig(m??{}),{headers:p,body:w,signal:A,...M}=D,c=async(s,f)=>{const[q,B]=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,...C,...B},{signal:O=A,body:o=w,headers:g,...x}=q,R=l.get(s);if(R&&e.cancelRedundantRequests){const t=new DOMException("Cancelled the previous unfinished request","AbortError");R.abort(t);}const u=new AbortController;l.set(s,u);const S=e.timeout?AbortSignal.timeout(e.timeout):null,T=AbortSignal.any([u.signal,S??u.signal,O??u.signal]),a={signal:T,method:"GET",body:_typeof.isObject(o)?e.bodySerializer(o):o,headers:p||g||e.auth||_typeof.isObject(o)?{..._typeof.isObject(o)&&{"Content-Type":"application/json",Accept:"application/json"},..._typeof.isFormData(o)&&{"Content-Type":"multipart/form-data"},..._typeof.isString(o)&&{"Content-Type":"application/x-www-form-urlencoded"},...!!e.auth&&{Authorization:`Bearer ${e.auth}`},...utils.objectifyHeaders(p),...utils.objectifyHeaders(g)}:void 0,...M,...x};try{await e.onRequest?.({request:a,options:e});const t=await fetch(`${e.baseURL}${utils.mergeUrlWithParams(s,e.query)}`,a);if(!t.ok&&!T.aborted&&e.retries>0&&e.retryCodes.includes(t.status)&&e.retryMethods.includes(a.method))return await utils.waitUntil(e.retryDelay),await c(s,{...f,retries:e.retries-1});if(!t.ok){const F=await utils.getResponseData(t,e.responseType,e.responseParser);throw new utils.HTTPError({response:{...t,errorData:F},defaultErrorMessage:e.defaultErrorMessage})}const r=await utils.getResponseData(t,e.responseType,e.responseParser),i=e.responseValidator?e.responseValidator(r):r;return await e.onResponse?.({response:{...t,data:i},request:a,options:e}),utils.resolveSuccessResult({successData:i,response:t,options:e})}catch(t){const n=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"),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(utils.isHTTPErrorInstance(t)){const{errorData:r,...i}=t.response;return await e.onResponseError?.({response:{...i,errorData:r},request:a,options:e}),n({errorData:r,response:i,message:r?.message})}return await e.onRequestError?.({request:a,error:t,options:e}),n()}finally{l.delete(s);}};return c.create=b,c.cancel=s=>l.get(s)?.abort(),c},V=b();
6
+ const m=D=>{const l=new Map,[C,A]=utils.splitConfig(D??{}),{headers:p,body:w,signal:M,...q}=C,c=async(o,f)=>{const[B,O]=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,...O},{signal:x=M,body:s=w,headers:g,...S}=B,h=l.get(o);if(h&&e.cancelRedundantRequests){const t=new DOMException("Cancelled the previous unfinished request","AbortError");h.abort(t);}const u=new AbortController;l.set(o,u);const $=e.timeout?AbortSignal.timeout(e.timeout):null,T=AbortSignal.any([u.signal,$??u.signal,x??u.signal]),a={signal:T,method:"GET",body:_typeof.isObject(s)?e.bodySerializer(s):s,headers:p||g||e.auth||_typeof.isObject(s)?{..._typeof.isObject(s)&&{"Content-Type":"application/json",Accept:"application/json"},..._typeof.isFormData(s)&&{"Content-Type":"multipart/form-data"},..._typeof.isString(s)&&{"Content-Type":"application/x-www-form-urlencoded"},..._typeof.isString(e.auth)&&{Authorization:`Bearer ${e.auth}`},..._typeof.isObject(e.auth)&&{Authorization:"bearer"in e.auth?`Bearer ${e.auth.bearer}`:`Token ${e.auth.token}`},...utils.objectifyHeaders(p),...utils.objectifyHeaders(g)}:void 0,...q,...S};try{await e.onRequest?.({request:a,options:e});const t=await fetch(`${e.baseURL}${utils.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 utils.waitUntil(e.retryDelay),await c(o,{...f,retries:e.retries-1});if(!t.ok){const F=await utils.getResponseData(t,e.responseType,e.responseParser);throw new utils.HTTPError({response:{...t,errorData:F},defaultErrorMessage:e.defaultErrorMessage})}const r=await utils.getResponseData(t,e.responseType,e.responseParser),i=e.responseValidator?e.responseValidator(r):r;return await e.onResponse?.({response:{...t,data:i},request:a,options:e}),utils.resolveSuccessResult({successData:i,response:t,options:e})}catch(t){const n=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"),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(utils.isHTTPErrorInstance(t)){const{errorData:r,...i}=t.response;return await e.onResponseError?.({response:{...i,errorData:r},request:a,options:e}),n({errorData:r,response:i,message:r?.message})}return await e.onRequestError?.({request:a,error:t,options:e}),n()}finally{l.delete(o);}};return c.create=m,c.cancel=o=>l.get(o)?.abort(),c},V=m();
7
7
 
8
8
  exports.callApi = V;
9
- exports.createFetchClient = b;
9
+ exports.createFetchClient = m;
10
10
  //# sourceMappingURL=out.js.map
11
11
  //# sourceMappingURL=createFetchClient.cjs.map
@@ -1 +1 @@
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","validSuccessData","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\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\theaders: baseHeaders,\n\t\tbody: baseBody,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\t/** Default Options */\n\t\tconst options = {\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tresponseType: \"json\",\n\t\t\tbaseURL: \"\",\n\t\t\tretries: 0,\n\t\t\tretryDelay: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tcancelRedundantRequests: true,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\tconst { 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\tconst validSuccessData = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tresponse: { ...response, data: validSuccessData },\n\t\t\t\trequest: requestInit,\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ successData: validSuccessData, response, options });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = $resolveErrorResult<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.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 const callApi = createFetchClient();\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","validSuccessData","error","resolveErrorResult","message"],"mappings":"AAAA,OAAS,cAAAA,EAAY,YAAAC,EAAU,YAAAC,MAAgB,WAW/C,OACC,uBAAAC,EACA,aAAAC,EACA,qBAAAC,EACA,uBAAAC,EACA,mBAAAC,EACA,uBAAAC,EACA,sBAAAC,EACA,oBAAAC,EACA,wBAAAC,EACA,eAAAC,EACA,aAAAC,MACM,UAEA,MAAMC,EAKZC,GACI,CACJ,MAAMC,EAAuB,IAAI,IAE3B,CAACC,EAAiBC,CAAgB,EAAIN,EAAYG,GAAc,CAAC,CAAC,EAElE,CACL,QAASI,EACT,KAAMC,EACN,OAAQC,EACR,GAAGC,CACJ,EAAIL,EAGEM,EAAU,MAKfC,EACAC,IAC+D,CAG/D,KAAM,CAACC,EAAaC,CAAY,EAAIf,EAAYa,GAAU,CAAC,CAAC,EAGtDG,EAAU,CACf,eAAgB,KAAK,UACrB,aAAc,OACd,QAAS,GACT,QAAS,EACT,WAAY,EACZ,WAAYvB,EACZ,aAAcC,EACd,oBAAqB,oCACrB,wBAAyB,GACzB,GAAGY,EACH,GAAGS,CACJ,EAEM,CAAE,OAAAE,EAASR,EAAY,KAAAS,EAAOV,EAAU,QAAAW,EAAS,GAAGC,CAAkB,EAAIN,EAE1EO,EAAsBjB,EAAqB,IAAIQ,CAAG,EAExD,GAAIS,GAAuBL,EAAQ,wBAAyB,CAC3D,MAAMM,EAAS,IAAI,aAAa,4CAA6C,YAAY,EACzFD,EAAoB,MAAMC,CAAM,CACjC,CAEA,MAAMC,EAAqB,IAAI,gBAE/BnB,EAAqB,IAAIQ,EAAKW,CAAkB,EAEhD,MAAMC,EAAgBR,EAAQ,QAAU,YAAY,QAAQA,EAAQ,OAAO,EAAI,KAGzES,EAAkB,YAAmC,IAAI,CAC9DF,EAAmB,OACnBC,GAAiBD,EAAmB,OACpCN,GAAUM,EAAmB,MAC9B,CAAC,EAEKG,EAAc,CACnB,OAAQD,EAER,OAAQ,MAER,KAAMpC,EAAS6B,CAAI,EAAIF,EAAQ,eAAeE,CAAI,EAAIA,EAMtD,QACCX,GAAeY,GAAWH,EAAQ,MAAQ3B,EAAS6B,CAAI,EACpD,CACA,GAAI7B,EAAS6B,CAAI,GAAK,CACrB,eAAgB,mBAChB,OAAQ,kBACT,EACA,GAAI9B,EAAW8B,CAAI,GAAK,CACvB,eAAgB,qBACjB,EACA,GAAI5B,EAAS4B,CAAI,GAAK,CACrB,eAAgB,mCACjB,EACA,GAAI5B,EAAS0B,EAAQ,IAAI,GAAK,CAC7B,cAAe,UAAUA,EAAQ,IAAI,EACtC,EACA,GAAI3B,EAAS2B,EAAQ,IAAI,GAAK,CAC7B,cACC,WAAYA,EAAQ,KACjB,UAAUA,EAAQ,KAAK,MAAM,GAC7B,SAASA,EAAQ,KAAK,KAAK,EAChC,EACA,GAAGlB,EAAiBS,CAAW,EAC/B,GAAGT,EAAiBqB,CAAO,CAC5B,EACC,OAEJ,GAAGT,EACH,GAAGU,CACJ,EAEA,GAAI,CACH,MAAMJ,EAAQ,YAAY,CAAE,QAASU,EAAa,QAAAV,CAAQ,CAAC,EAE3D,MAAMW,EAAW,MAAM,MACtB,GAAGX,EAAQ,OAAO,GAAGnB,EAAmBe,EAAKI,EAAQ,KAAK,CAAC,GAC3DU,CACD,EASA,GANC,CAACC,EAAS,IACV,CAACF,EAAe,SAChBT,EAAQ,QAAU,GAClBA,EAAQ,WAAW,SAASW,EAAS,MAAM,GAC3CX,EAAQ,aAAa,SAASU,EAAY,MAAM,EAGhD,aAAMzB,EAAUe,EAAQ,UAAU,EAE3B,MAAML,EAAQC,EAAK,CAAE,GAAGC,EAAQ,QAASG,EAAQ,QAAU,CAAE,CAAC,EAGtE,GAAI,CAACW,EAAS,GAAI,CACjB,MAAMC,EAAY,MAAMjC,EACvBgC,EACAX,EAAQ,aACRA,EAAQ,cACT,EAGA,MAAM,IAAIxB,EAAU,CACnB,SAAU,CAAE,GAAGmC,EAAU,UAAAC,CAAU,EACnC,oBAAqBZ,EAAQ,mBAC9B,CAAC,CACF,CAEA,MAAMa,EAAc,MAAMlC,EACzBgC,EACAX,EAAQ,aACRA,EAAQ,cACT,EAEMc,EAAmBd,EAAQ,kBAC9BA,EAAQ,kBAAkBa,CAAW,EACrCA,EAEH,aAAMb,EAAQ,aAAa,CAC1B,SAAU,CAAE,GAAGW,EAAU,KAAMG,CAAiB,EAChD,QAASJ,EACT,QAAAV,CACD,CAAC,EAEMjB,EAAoC,CAAE,YAAa+B,EAAkB,SAAAH,EAAU,QAAAX,CAAQ,CAAC,CAGhG,OAASe,EAAO,CACf,MAAMC,EAAqBzC,EAAmC,CAAE,MAAAwC,EAAO,QAAAf,CAAQ,CAAC,EAEhF,GAAIe,aAAiB,cAAgBA,EAAM,OAAS,eAAgB,CACnE,MAAME,EAAU,2BAA2BjB,EAAQ,OAAO,KAE1D,eAAQ,KAAK,mBAAmBiB,CAAO,GAAI,gDAAgD,EAC3F,QAAQ,MAAM,cAAc,EAErBD,EAAmB,CAAE,QAAAC,CAAQ,CAAC,CACtC,CAEA,GAAIF,aAAiB,cAAgBA,EAAM,OAAS,aAAc,CACjE,MAAME,EAAU,wBAEhB,eAAQ,KAAK,gBAAgBA,CAAO,GAAI,gDAAgD,EACxF,QAAQ,MAAM,YAAY,EAEnBD,EAAmB,CAAE,QAAAC,CAAQ,CAAC,CACtC,CAEA,GAAIrC,EAAgCmC,CAAK,EAAG,CAC3C,KAAM,CAAE,UAAAH,EAAW,GAAGD,CAAS,EAAII,EAAM,SAEzC,aAAMf,EAAQ,kBAAkB,CAC/B,SAAU,CAAE,GAAGW,EAAU,UAAAC,CAAU,EACnC,QAASF,EACT,QAAAV,CACD,CAAC,EAEMgB,EAAmB,CACzB,UAAAJ,EACA,SAAAD,EACA,QAAUC,GAAmC,OAC9C,CAAC,CACF,CAGA,aAAMZ,EAAQ,iBAAiB,CAAE,QAASU,EAAa,MAAOK,EAAgB,QAAAf,CAAQ,CAAC,EAEhFgB,EAAmB,CAG3B,QAAE,CACD5B,EAAqB,OAAOQ,CAAG,CAChC,CACD,EAEA,OAAAD,EAAQ,OAAST,EAEjBS,EAAQ,OAAUC,GAAgBR,EAAqB,IAAIQ,CAAG,GAAG,MAAM,EAEhED,CACR,EAEaA,EAAUT,EAAkB","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\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\theaders: baseHeaders,\n\t\tbody: baseBody,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\t/** Default Options */\n\t\tconst options = {\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tresponseType: \"json\",\n\t\t\tbaseURL: \"\",\n\t\t\tretries: 0,\n\t\t\tretryDelay: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tcancelRedundantRequests: true,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\tconst { 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...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ request: requestInit, options });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\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\tconst validSuccessData = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tresponse: { ...response, data: validSuccessData },\n\t\t\t\trequest: requestInit,\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ successData: validSuccessData, response, options });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = $resolveErrorResult<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.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 const callApi = createFetchClient();\n"]}
@@ -1,8 +1,8 @@
1
1
  import { isObject, isFormData, isString } from './typeof';
2
2
  import { splitConfig, defaultRetryCodes, defaultRetryMethods, objectifyHeaders, mergeUrlWithParams, waitUntil, getResponseData, HTTPError, resolveSuccessResult, $resolveErrorResult, isHTTPErrorInstance } from './utils';
3
3
 
4
- const b=m=>{const l=new Map,[D,C]=splitConfig(m??{}),{headers:p,body:w,signal:A,...M}=D,c=async(s,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,...C,...B},{signal:O=A,body:o=w,headers:g,...x}=q,R=l.get(s);if(R&&e.cancelRedundantRequests){const t=new DOMException("Cancelled the previous unfinished request","AbortError");R.abort(t);}const u=new AbortController;l.set(s,u);const S=e.timeout?AbortSignal.timeout(e.timeout):null,T=AbortSignal.any([u.signal,S??u.signal,O??u.signal]),a={signal:T,method:"GET",body:isObject(o)?e.bodySerializer(o):o,headers:p||g||e.auth||isObject(o)?{...isObject(o)&&{"Content-Type":"application/json",Accept:"application/json"},...isFormData(o)&&{"Content-Type":"multipart/form-data"},...isString(o)&&{"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(s,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 c(s,{...f,retries:e.retries-1});if(!t.ok){const F=await getResponseData(t,e.responseType,e.responseParser);throw new HTTPError({response:{...t,errorData:F},defaultErrorMessage:e.defaultErrorMessage})}const r=await getResponseData(t,e.responseType,e.responseParser),i=e.responseValidator?e.responseValidator(r):r;return await e.onResponse?.({response:{...t,data:i},request:a,options:e}),resolveSuccessResult({successData:i,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,...i}=t.response;return await e.onResponseError?.({response:{...i,errorData:r},request:a,options:e}),n({errorData:r,response:i,message:r?.message})}return await e.onRequestError?.({request:a,error:t,options:e}),n()}finally{l.delete(s);}};return c.create=b,c.cancel=s=>l.get(s)?.abort(),c},V=b();
4
+ const m=D=>{const l=new Map,[C,A]=splitConfig(D??{}),{headers:p,body:w,signal:M,...q}=C,c=async(o,f)=>{const[B,O]=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,...O},{signal:x=M,body:s=w,headers:g,...S}=B,h=l.get(o);if(h&&e.cancelRedundantRequests){const t=new DOMException("Cancelled the previous unfinished request","AbortError");h.abort(t);}const u=new AbortController;l.set(o,u);const $=e.timeout?AbortSignal.timeout(e.timeout):null,T=AbortSignal.any([u.signal,$??u.signal,x??u.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"},...isString(e.auth)&&{Authorization:`Bearer ${e.auth}`},...isObject(e.auth)&&{Authorization:"bearer"in e.auth?`Bearer ${e.auth.bearer}`:`Token ${e.auth.token}`},...objectifyHeaders(p),...objectifyHeaders(g)}:void 0,...q,...S};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 c(o,{...f,retries:e.retries-1});if(!t.ok){const F=await getResponseData(t,e.responseType,e.responseParser);throw new HTTPError({response:{...t,errorData:F},defaultErrorMessage:e.defaultErrorMessage})}const r=await getResponseData(t,e.responseType,e.responseParser),i=e.responseValidator?e.responseValidator(r):r;return await e.onResponse?.({response:{...t,data:i},request:a,options:e}),resolveSuccessResult({successData:i,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,...i}=t.response;return await e.onResponseError?.({response:{...i,errorData:r},request:a,options:e}),n({errorData:r,response:i,message:r?.message})}return await e.onRequestError?.({request:a,error:t,options:e}),n()}finally{l.delete(o);}};return c.create=m,c.cancel=o=>l.get(o)?.abort(),c},V=m();
5
5
 
6
- export { V as callApi, b as createFetchClient };
6
+ export { V as callApi, m as createFetchClient };
7
7
  //# sourceMappingURL=out.js.map
8
8
  //# sourceMappingURL=createFetchClient.js.map
@@ -1 +1 @@
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","validSuccessData","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\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\theaders: baseHeaders,\n\t\tbody: baseBody,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\t/** Default Options */\n\t\tconst options = {\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tresponseType: \"json\",\n\t\t\tbaseURL: \"\",\n\t\t\tretries: 0,\n\t\t\tretryDelay: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tcancelRedundantRequests: true,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\tconst { 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\tconst validSuccessData = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tresponse: { ...response, data: validSuccessData },\n\t\t\t\trequest: requestInit,\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ successData: validSuccessData, response, options });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = $resolveErrorResult<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.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 const callApi = createFetchClient();\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","validSuccessData","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\nexport const createFetchClient = <\n\tTBaseData,\n\tTBaseErrorData,\n\tTBaseResultMode extends ResultModeUnion = undefined,\n>(\n\tbaseConfig?: BaseConfig<TBaseData, TBaseErrorData, TBaseResultMode>\n) => {\n\tconst abortControllerStore = new Map<string, AbortController>();\n\n\tconst [baseFetchConfig, baseExtraOptions] = splitConfig(baseConfig ?? {});\n\n\tconst {\n\t\theaders: baseHeaders,\n\t\tbody: baseBody,\n\t\tsignal: baseSignal,\n\t\t...restOfBaseFetchConfig\n\t} = baseFetchConfig;\n\n\t/* eslint-disable complexity */\n\tconst callApi = async <\n\t\tTData = TBaseData,\n\t\tTErrorData = TBaseErrorData,\n\t\tTResultMode extends ResultModeUnion = TBaseResultMode,\n\t>(\n\t\turl: string,\n\t\tconfig?: FetchConfig<TData, TErrorData, TResultMode>\n\t): Promise<GetCallApiResult<TData, TErrorData, TResultMode>> => {\n\t\ttype CallApiResult = GetCallApiResult<TData, TErrorData, TResultMode>;\n\n\t\tconst [fetchConfig, extraOptions] = splitConfig(config ?? {});\n\n\t\t/** Default Options */\n\t\tconst options = {\n\t\t\tbodySerializer: JSON.stringify,\n\t\t\tresponseType: \"json\",\n\t\t\tbaseURL: \"\",\n\t\t\tretries: 0,\n\t\t\tretryDelay: 0,\n\t\t\tretryCodes: defaultRetryCodes,\n\t\t\tretryMethods: defaultRetryMethods,\n\t\t\tdefaultErrorMessage: \"Failed to fetch data from server!\",\n\t\t\tcancelRedundantRequests: true,\n\t\t\t...baseExtraOptions,\n\t\t\t...extraOptions,\n\t\t} satisfies ExtraOptions;\n\n\t\tconst { 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...(isString(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${options.auth}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(isObject(options.auth) && {\n\t\t\t\t\t\t\t\tAuthorization:\n\t\t\t\t\t\t\t\t\t\"bearer\" in options.auth\n\t\t\t\t\t\t\t\t\t\t? `Bearer ${options.auth.bearer}`\n\t\t\t\t\t\t\t\t\t\t: `Token ${options.auth.token}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...objectifyHeaders(baseHeaders),\n\t\t\t\t\t\t\t...objectifyHeaders(headers),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\n\t\t\t...restOfBaseFetchConfig,\n\t\t\t...restOfFetchConfig,\n\t\t} satisfies $RequestOptions;\n\n\t\ttry {\n\t\t\tawait options.onRequest?.({ request: requestInit, options });\n\n\t\t\tconst response = await fetch(\n\t\t\t\t`${options.baseURL}${mergeUrlWithParams(url, options.query)}`,\n\t\t\t\trequestInit\n\t\t\t);\n\n\t\t\tconst shouldRetry =\n\t\t\t\t!response.ok &&\n\t\t\t\t!combinedSignal.aborted &&\n\t\t\t\toptions.retries > 0 &&\n\t\t\t\toptions.retryCodes.includes(response.status) &&\n\t\t\t\toptions.retryMethods.includes(requestInit.method);\n\n\t\t\tif (shouldRetry) {\n\t\t\t\tawait waitUntil(options.retryDelay);\n\n\t\t\t\treturn await callApi(url, { ...config, retries: options.retries - 1 });\n\t\t\t}\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorData = await getResponseData<TErrorData>(\n\t\t\t\t\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\tconst validSuccessData = options.responseValidator\n\t\t\t\t? options.responseValidator(successData)\n\t\t\t\t: successData;\n\n\t\t\tawait options.onResponse?.({\n\t\t\t\tresponse: { ...response, data: validSuccessData },\n\t\t\t\trequest: requestInit,\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\treturn resolveSuccessResult<CallApiResult>({ successData: validSuccessData, response, options });\n\n\t\t\t// == Exhaustive Error handling\n\t\t} catch (error) {\n\t\t\tconst resolveErrorResult = $resolveErrorResult<CallApiResult>({ error, options });\n\n\t\t\tif (error instanceof DOMException && error.name === \"TimeoutError\") {\n\t\t\t\tconst message = `Request timed out after ${options.timeout}ms`;\n\n\t\t\t\tconsole.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 const callApi = createFetchClient();\n"]}
@@ -73,7 +73,11 @@ type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode
73
73
  /**
74
74
  * @description Authorization header value.
75
75
  */
76
- auth?: string;
76
+ auth?: string | {
77
+ bearer: string;
78
+ } | {
79
+ token: string;
80
+ };
77
81
  /**
78
82
  * @description Custom function to validate the response data.
79
83
  */
@@ -73,7 +73,11 @@ type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode
73
73
  /**
74
74
  * @description Authorization header value.
75
75
  */
76
- auth?: string;
76
+ auth?: string | {
77
+ bearer: string;
78
+ } | {
79
+ token: string;
80
+ };
77
81
  /**
78
82
  * @description Custom function to validate the response data.
79
83
  */
package/dist/utils.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- export { j as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, e as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, i as isHTTPError, c as isHTTPErrorInstance, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, t as toQueryString, w as waitUntil } from './types-DfUaOAyg.cjs';
1
+ export { j as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, e as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, i as isHTTPError, c as isHTTPErrorInstance, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, t as toQueryString, w as waitUntil } from './types-CAxhtQRR.cjs';
2
2
  import './type-helpers-Dibitydy.cjs';
package/dist/utils.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { j as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, e as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, i as isHTTPError, c as isHTTPErrorInstance, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, t as toQueryString, w as waitUntil } from './types-D17lSUr9.js';
1
+ export { j as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, e as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, i as isHTTPError, c as isHTTPErrorInstance, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, t as toQueryString, w as waitUntil } from './types-BFhLAZSM.js';
2
2
  import './type-helpers-Dibitydy.js';
package/package.json CHANGED
@@ -1,14 +1,20 @@
1
1
  {
2
2
  "name": "@zayne-labs/callapi",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "description": "A lightweight wrapper over fetch with quality of life improvements like built-in request cancellation, retries, interceptors and more",
6
6
  "main": "./dist/src/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
- "import": "./dist/src/index.js",
11
- "require": "./dist/src/index.cjs"
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/src/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/src/index.cjs"
17
+ }
12
18
  }
13
19
  },
14
20
  "publishConfig": {