From ac1fabeac9863a5fa8138650f433695e5fb24e76 Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 2 Oct 2024 22:20:39 +0200 Subject: [PATCH] chore: Build --- dist/browser/index.global.js | 2 +- dist/browser/index.global.js.map | 2 +- dist/browser/index.mjs | 2 +- dist/browser/index.mjs.map | 2 +- dist/node/index.js | 2 +- dist/node/index.js.map | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dist/browser/index.global.js b/dist/browser/index.global.js index 67d026f..e8ff398 100644 --- a/dist/browser/index.global.js +++ b/dist/browser/index.global.js @@ -1,2 +1,2 @@ -"use strict";var fetchff=(()=>{var M=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var Oe=Object.prototype.hasOwnProperty;var Fe=(e,t,n)=>t in e?M(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Ie=(e,t)=>{for(var n in t)M(e,n,{get:t[n],enumerable:!0})},qe=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of xe(t))!Oe.call(e,r)&&r!==n&&M(e,r,{get:()=>t[r],enumerable:!(a=we(t,r))||a.enumerable});return e};var Ae=e=>qe(M({},"__esModule",{value:!0}),e);var w=(e,t,n)=>Fe(e,typeof t!="symbol"?t+"":t,n);var Be={};Ie(Be,{createApiFetcher:()=>Ue,fetchf:()=>Se});async function T(e,t){if(t){if(typeof t=="function"){let n=await t(e);n&&Object.assign(e,n)}else if(Array.isArray(t))for(let n of t){let a=await n(e);a&&Object.assign(e,a)}}}var _=class extends Error{constructor(n,a,r){super(n);w(this,"response");w(this,"request");w(this,"config");w(this,"status");w(this,"statusText");this.name="ResponseError",this.message=n,this.status=r.status,this.statusText=r.statusText,this.request=a,this.config=a,this.response=r}};var Q="application/",A=Q+"json",L="Content-Type",C="undefined",E="object",v="string",j="AbortError",ie="TimeoutError",le="CanceledError",N="GET",ue="HEAD";function W(e){return e instanceof URLSearchParams}function fe(e){let t="";for(let n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t+=n+":"+e[n]);return t}function X(e){let t={},n=Object.keys(e);n.sort();for(let a=0,r=n.length;a{o=typeof o=="function"?o():o,o=o===null||o===void 0?"":o,n[n.length]=a(f)+"="+a(o)},u=(f,o)=>{let p,g,R;if(f)if(Array.isArray(o))for(p=0,g=o.length;p{let a=n.substring(1);return t[a]?String(t[a]):n}):e}function Re(e){let t=typeof e;if(t===C||e===null)return!1;if(t===v||t==="number"||t==="boolean"||Array.isArray(e))return!0;if(Buffer.isBuffer(e)||e instanceof Date)return!1;if(t===E){let n=Object.getPrototypeOf(e);if(n===Object.prototype||n===null||typeof e.toJSON=="function")return!0}return!1}async function Z(e){return new Promise(t=>setTimeout(()=>t(!0),e))}function ee(e){return e&&typeof e===E&&typeof e.data!==C&&Object.keys(e).length===1?ee(e.data):e}function me(e){if(!e)return{};let t={};if(e instanceof Headers)e.forEach((n,a)=>{t[a]=n});else if(typeof e===E&&e!==null)for(let[n,a]of Object.entries(e))t[n.toLowerCase()]=a;return t}function J(e,t){e&&t in e&&delete e[t]}var H=new Map;async function ye(e,t,n=0,a=!1,r=!0){let u=Date.now(),m=H.get(e);if(m){let o=m[3],p=m[0],g=m[1];if(!o&&u-m[2]{let o=new DOMException(`${e.url} aborted due to timeout`,ie);$(e,o)},t):null;return H.set(e,[y,f,u,a]),y}async function $(e,t=null){let n=H.get(e);if(n){let a=n[0],r=n[1];t&&!a.signal.aborted&&a.abort(t),r!==null&&clearTimeout(r),H.delete(e)}}async function he(e){var a;if(!(e!=null&&e.body))return null;let t=String(((a=e.headers)==null?void 0:a.get(L))||"").split(";")[0],n;try{if(t.includes(A)||t.includes("+json"))n=await e.json();else if(t.includes("multipart/form-data"))n=await e.formData();else if(t.includes(Q+"octet-stream"))n=await e.blob();else if(t.includes(Q+"x-www-form-urlencoded"))n=await e.formData();else if(t.includes("text/"))n=await e.text();else try{n=await e.clone().json()}catch(r){n=await e.text()}}catch(r){n=null}return n}function G(e){let t=0;for(let n=0,a=e.length;n{R+=i+"="+s+"&"}),R=G(R);else if(typeof Blob!==C&&r instanceof Blob||typeof File!==C&&r instanceof File)R="BF"+r.size+r.type;else if(r instanceof ArrayBuffer||ArrayBuffer.isView(r))R="AB"+r.byteLength;else{let s=typeof r===E?X(r):String(r);R=G(JSON.stringify(s))}return n+t+u+m+y+f+o+p+g+R}function Ne(e,t){return t?Date.now()-e>t*1e3:!1}function Pe(e,t){let n=te.get(e);if(n){if(!Ne(n.timestamp,t))return n;te.delete(e)}return null}function De(e,t,n=!1){te.set(e,{data:t,isLoading:n,timestamp:Date.now()})}var He={method:N,strategy:"reject",timeout:3e4,dedupeTime:1e3,defaultResponse:null,headers:{Accept:A+", text/plain, */*","Accept-Encoding":"gzip, deflate, br",[L]:A+";charset=utf-8"},retry:{delay:1e3,maxDelay:3e4,resetTimeout:!0,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function z(e){let t={...He,...e},n=t.fetcher,a=(n==null?void 0:n.create(t))||null,r=()=>a,u=(s,i)=>typeof s[i]!==C?s[i]:t[i],m=(...s)=>{var i;(i=t.logger)!=null&&i.warn&&t.logger.warn(...s)},y=(s,i)=>{let d=u(i,"method").toUpperCase(),P=d===N||d===ue,l=de(s,u(i,"urlPathParams")),h=u(i,"params"),U=u(i,"body")||u(i,"data"),D;P||(D=U);let S=u(i,"withCredentials")?"include":u(i,"credentials"),x=h?pe(l,h):l,k=x.includes("://")?"":u(i,"baseURL")||u(i,"apiUrl");return D&&typeof D!==v&&!W(D)&&Re(D)&&(D=JSON.stringify(D)),{...i,credentials:S,body:D,method:d,url:k+x}},f=async(s,i)=>{p(s)||m("API ERROR",s),await T(s,i==null?void 0:i.onError),await T(s,t==null?void 0:t.onError)},o=async(s,i,d)=>{let P=p(s),l=u(d,"strategy"),h=u(d,"rejectCancelled");if(!(P&&!h)){if(l==="silent")await new Promise(()=>null);else if(l==="reject")return Promise.reject(s)}return R(i,d,s)},p=s=>s.name===j||s.name===le,g=async(s,i=null)=>{var ae;let d=i||{},P={...t,...d},l=null,h=y(s,P),{timeout:U,cancellable:D,dedupeTime:ne,pollingInterval:S,shouldStopPolling:x,cacheTime:B,cacheKey:k}=P,b;if(k?b=k(h):b=ge(h),B&&b){let I=P.cacheBuster;if(!I||!I(h)){let c=Pe(b,B);if(c)return c.data}}let{retries:Y=0,delay:Ee,backoff:Ce,retryOn:K,shouldRetry:se,maxDelay:Te,resetTimeout:be}=P.retry,O=0,V=0,F=Ee,re=Y>0?Y:0;for(;O<=re;)try{let c={signal:(await ye(h,U,ne,D,!!(U&&(!re||be)))).signal,...h};if(await T(c,d==null?void 0:d.onRequest),await T(c,t==null?void 0:t.onRequest),n!==null&&a!==null?l=await a.request(c):l=await fetch(c.url,c),l instanceof Response&&(l.config=c,l.data=await he(l),!l.ok))throw new _(`${c.url} failed! Status: ${l.status||null}`,c,l);if(await T(l,d==null?void 0:d.onResponse),await T(l,t==null?void 0:t.onResponse),$(h),S&&(!x||!x(l,V))){V++,m(`Polling attempt ${V}...`),await Z(S);continue}let q=R(l,c);if(B&&b){let oe=c.skipCache;(!oe||!oe(q,c))&&De(b,q)}return q}catch(I){let c=I,q=((ae=c==null?void 0:c.response)==null?void 0:ae.status)||(c==null?void 0:c.status)||0;if(O===Y||!(!se||await se(c,O))||!(K!=null&&K.includes(q)))return await f(c,h),$(h),o(c,l,h);m(`Attempt ${O+1} failed. Retry in ${F}ms.`),await Z(F),F*=Ce,F=Math.min(F,Te),O++}return R(l,h)},R=(s,i,d=null)=>{let P=u(i,"defaultResponse");if(!s)return{ok:!1,error:d,data:P,headers:null,config:i};J(d,"response"),J(d,"request"),J(d,"config");let l=s==null?void 0:s.data;return(l==null||typeof l===E&&Object.keys(l).length===0)&&(l=P),u(i,"flattenResponse")&&(s.data=ee(l)),s instanceof Response?{body:s.body,bodyUsed:s.bodyUsed,formData:s.formData,ok:s.ok,redirected:s.redirected,type:s.type,url:s.url,status:s.status,statusText:s.statusText,blob:s.blob.bind(s),json:s.json.bind(s),text:s.text.bind(s),clone:s.clone.bind(s),arrayBuffer:s.arrayBuffer.bind(s),error:d,data:l,headers:me(s.headers),config:i}:s};return{getInstance:r,buildConfig:y,config:e,request:g}}function Ue(e){let t=e.endpoints,n=z(e);function a(){return n.getInstance()}function r(y){return console.error(`Add ${y} to 'endpoints'.`),Promise.resolve(null)}async function u(y,f={}){let o=t[y]||{url:y};return await n.request(o.url,{...o,...f})}let m={config:e,endpoints:t,requestHandler:n,getInstance:a,request:u};return new Proxy(m,{get(y,f){return f in m?m[f]:t[f]?m.request.bind(null,f):r.bind(null,f)}})}async function Se(e,t={}){return z(t).request(e,t)}return Ae(Be);})(); +"use strict";var fetchff=(()=>{var _=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var qe=Object.getOwnPropertyNames;var Fe=Object.prototype.hasOwnProperty;var Ie=(e,t,n)=>t in e?_(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Ae=(e,t)=>{for(var n in t)_(e,n,{get:t[n],enumerable:!0})},He=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of qe(t))!Fe.call(e,a)&&a!==n&&_(e,a,{get:()=>t[a],enumerable:!(r=Oe(t,a))||r.enumerable});return e};var Ne=e=>He(_({},"__esModule",{value:!0}),e);var x=(e,t,n)=>Ie(e,typeof t!="symbol"?t+"":t,n);var Be={};Ae(Be,{createApiFetcher:()=>Se,fetchf:()=>ke});async function b(e,t){if(t){if(typeof t=="function"){let n=await t(e);n&&Object.assign(e,n)}else if(Array.isArray(t))for(let n of t){let r=await n(e);r&&Object.assign(e,r)}}}var Q=class extends Error{constructor(n,r,a){super(n);x(this,"response");x(this,"request");x(this,"config");x(this,"status");x(this,"statusText");this.name="ResponseError",this.message=n,this.status=a.status,this.statusText=a.statusText,this.request=r,this.config=r,this.response=a}};var L="application/",H=L+"json",v="Content-Type",C="undefined",E="object",j="string",J="AbortError",ue="TimeoutError",ce="CanceledError",N="GET",fe="HEAD";function X(e){return e instanceof URLSearchParams}function de(e){let t="";for(let n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t+=n+":"+e[n]);return t}function Z(e){let t={},n=Object.keys(e);n.sort();for(let r=0,a=n.length;r{o=typeof o=="function"?o():o,o=o===null||o===void 0?"":o,n[n.length]=r(f)+"="+r(o)},d=(f,o)=>{let p,P,m;if(f)if(Array.isArray(o))for(p=0,P=o.length;p{let r=n.substring(1);return t[r]?String(t[r]):n}):e}function ye(e){let t=typeof e;if(t===C||e===null)return!1;if(t===j||t==="number"||t==="boolean"||Array.isArray(e))return!0;if(Buffer.isBuffer(e)||e instanceof Date)return!1;if(t===E){let n=Object.getPrototypeOf(e);if(n===Object.prototype||n===null||typeof e.toJSON=="function")return!0}return!1}async function ee(e){return new Promise(t=>setTimeout(()=>t(!0),e))}function te(e){return e&&typeof e===E&&typeof e.data!==C&&Object.keys(e).length===1?te(e.data):e}function he(e){if(!e)return{};let t={};if(e instanceof Headers)e.forEach((n,r)=>{t[r]=n});else if(typeof e===E&&e!==null)for(let[n,r]of Object.entries(e))t[n.toLowerCase()]=r;return t}function $(e,t){e&&t in e&&delete e[t]}var U=new Map;async function ge(e,t,n=0,r=!1,a=!0){let d=Date.now(),g=U.get(e);if(g){let o=g[3],p=g[0],P=g[1];if(!o&&d-g[2]{let o=new DOMException(`${e.url} aborted due to timeout`,ue);G(e,o)},t):null;return U.set(e,[R,f,d,r]),R}async function G(e,t=null){let n=U.get(e);if(n){let r=n[0],a=n[1];t&&!r.signal.aborted&&r.abort(t),a!==null&&clearTimeout(a),U.delete(e)}}async function Pe(e){var r;if(!(e!=null&&e.body))return null;let t=String(((r=e.headers)==null?void 0:r.get(v))||"").split(";")[0],n;try{if(t.includes(H)||t.includes("+json"))n=await e.json();else if(t.includes("multipart/form-data"))n=await e.formData();else if(t.includes(L+"octet-stream"))n=await e.blob();else if(t.includes(L+"x-www-form-urlencoded"))n=await e.formData();else if(t.includes("text/"))n=await e.text();else try{n=await e.clone().json()}catch(a){n=await e.text()}}catch(a){n=null}return n}function z(e){let t=0;for(let n=0,r=e.length;n{m+=s+"="+T+"&"}),m=z(m);else if(typeof Blob!==C&&a instanceof Blob||typeof File!==C&&a instanceof File)m="BF"+a.size+a.type;else if(a instanceof ArrayBuffer||ArrayBuffer.isView(a))m="AB"+a.byteLength;else{let T=typeof a===E?Z(a):String(a);m=z(JSON.stringify(T))}return n+t+d+g+R+f+o+p+P+m}function Ue(e,t){return t?Date.now()-e>t*1e3:!1}function Ee(e,t){let n=ne.get(e);if(n){if(!Ue(n.timestamp,t))return n;ne.delete(e)}return null}function Ce(e,t,n=!1){ne.set(e,{data:t,isLoading:n,timestamp:Date.now()})}var se={method:N,strategy:"reject",timeout:3e4,dedupeTime:1e3,defaultResponse:null,headers:{Accept:H+", text/plain, */*","Accept-Encoding":"gzip, deflate, br",[v]:H+";charset=utf-8"},retry:{delay:1e3,maxDelay:3e4,resetTimeout:!0,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function K(e){let t={...se,...e},n=(s,i,l,y)=>{y[s]&&(i[s]={...l[s],...y[s]})};n("retry",t,se,e),n("headers",t,se,e);let r=(s,i)=>typeof s[i]!==C?s[i]:t[i],a=r(e,"fetcher"),d=(a==null?void 0:a.create(t))||null,g=()=>d,R=(s,...i)=>{let l=r(s,"logger");l!=null&&l.warn&&l.warn(...i)},f=(s,i)=>{let l=r(i,"method").toUpperCase(),y=l===N||l===fe,u=me(s,r(i,"urlPathParams")),h=r(i,"params"),S=r(i,"body")||r(i,"data"),D;y||(D=S);let k=r(i,"withCredentials")?"include":r(i,"credentials"),O=h?Re(u,h):u,M=O.includes("://")?"":r(i,"baseURL")||r(i,"apiUrl");return D&&typeof D!==j&&!X(D)&&ye(D)&&(D=JSON.stringify(D)),{...i,credentials:k,body:D,method:l,url:M+O}},o=async(s,i)=>{P(s)||R(i,"API ERROR",s),await b(s,i==null?void 0:i.onError),await b(s,t==null?void 0:t.onError)},p=async(s,i,l)=>{let y=P(s),u=r(l,"strategy"),h=r(l,"rejectCancelled");if(!(y&&!h)){if(u==="silent")await new Promise(()=>null);else if(u==="reject")return Promise.reject(s)}return T(i,l,s)},P=s=>s.name===J||s.name===ce,m=async(s,i=null)=>{var ie;let l=i||{},y={...t,...l};n("retry",y,t,l),n("headers",y,t,l);let u=null,h=f(s,y),{timeout:S,cancellable:D,dedupeTime:re,pollingInterval:k,shouldStopPolling:O,cacheTime:B,cacheKey:M}=y,w;if(M?w=M(h):w=De(h),B&&w){let I=y.cacheBuster;if(!I||!I(h)){let c=Ee(w,B);if(c)return c.data}}let{retries:Y=0,delay:Te,backoff:be,retryOn:V,shouldRetry:ae,maxDelay:we,resetTimeout:xe}=y.retry,q=0,W=0,F=Te,oe=Y>0?Y:0;for(;q<=oe;)try{let c={signal:(await ge(h,S,re,D,!!(S&&(!oe||xe)))).signal,...h};if(await b(c,l==null?void 0:l.onRequest),await b(c,t==null?void 0:t.onRequest),a!==null&&d!==null?u=await d.request(c):u=await fetch(c.url,c),u instanceof Response&&(u.config=c,u.data=await Pe(u),!u.ok))throw new Q(`${c.url} failed! Status: ${u.status||null}`,c,u);if(await b(u,l==null?void 0:l.onResponse),await b(u,t==null?void 0:t.onResponse),G(h),k&&(!O||!O(u,W))){W++,R(c,"Polling attempt "+W+"..."),await ee(k);continue}let A=T(u,c);if(B&&w){let le=c.skipCache;(!le||!le(A,c))&&Ce(w,A)}return A}catch(I){let c=I,A=((ie=c==null?void 0:c.response)==null?void 0:ie.status)||(c==null?void 0:c.status)||0;if(q===Y||!(!ae||await ae(c,q))||!(V!=null&&V.includes(A)))return await o(c,h),G(h),p(c,u,h);R(y,`Attempt ${q+1} failed. Retry in ${F}ms.`),await ee(F),F*=be,F=Math.min(F,we),q++}return T(u,h)},T=(s,i,l=null)=>{let y=r(i,"defaultResponse");if(!s)return{ok:!1,error:l,data:y,headers:null,config:i};$(l,"response"),$(l,"request"),$(l,"config");let u=s==null?void 0:s.data;return(u==null||typeof u===E&&Object.keys(u).length===0)&&(u=y),r(i,"flattenResponse")&&(s.data=te(u)),s instanceof Response?{body:s.body,bodyUsed:s.bodyUsed,formData:s.formData,ok:s.ok,redirected:s.redirected,type:s.type,url:s.url,status:s.status,statusText:s.statusText,blob:s.blob.bind(s),json:s.json.bind(s),text:s.text.bind(s),clone:s.clone.bind(s),arrayBuffer:s.arrayBuffer.bind(s),error:l,data:u,headers:he(s.headers),config:i}:s};return{getInstance:g,buildConfig:f,config:e,request:m}}function Se(e){let t=e.endpoints,n=K(e);function r(){return n.getInstance()}function a(R){return console.error(`Add ${R} to 'endpoints'.`),Promise.resolve(null)}async function d(R,f={}){let o=t[R]||{url:R};return await n.request(o.url,{...o,...f})}let g={config:e,endpoints:t,requestHandler:n,getInstance:r,request:d};return new Proxy(g,{get(R,f){return f in g?g[f]:t[f]?g.request.bind(null,f):a.bind(null,f)}})}async function ke(e,t={}){return K(t).request(e,t)}return Ne(Be);})(); //# sourceMappingURL=index.global.js.map \ No newline at end of file diff --git a/dist/browser/index.global.js.map b/dist/browser/index.global.js.map index 756583b..aa05147 100644 --- a/dist/browser/index.global.js.map +++ b/dist/browser/index.global.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/index.ts","../../src/interceptor-manager.ts","../../src/response-error.ts","../../src/constants.ts","../../src/utils.ts","../../src/queue-manager.ts","../../src/response-parser.ts","../../src/hash.ts","../../src/cache-manager.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"sourcesContent":["import { createRequestHandler } from './request-handler';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestHandlerConfig,\n} from './types';\n\n/**\n * Simple wrapper for request fetching.\n * It abstracts the creation of RequestHandler, making it easy to perform API requests.\n *\n * @param {string | URL | globalThis.Request} url - Request URL.\n * @param {RequestHandlerConfig} config - Configuration object for the request handler.\n * @returns {Promise>} Response Data.\n */\nexport async function fetchf(\n url: string,\n config: RequestHandlerConfig = {},\n): Promise> {\n return createRequestHandler(config).request(url, config);\n}\n\nexport * from './types';\nexport * from './api-handler';\n","type InterceptorFunction = (object: T) => Promise;\n\n/**\n * Applies interceptors to the object. Interceptors can be a single function or an array of functions.\n *\n * @template T - Type of the object.\n * @template I - Type of interceptors.\n *\n * @param {T} object - The object to process.\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptor<\n T extends object,\n I = InterceptorFunction | InterceptorFunction[],\n>(object: T, interceptors?: I): Promise {\n if (!interceptors) {\n return;\n }\n\n if (typeof interceptors === 'function') {\n const value = await interceptors(object);\n\n if (value) {\n Object.assign(object, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(object);\n\n if (value) {\n Object.assign(object, value);\n }\n }\n }\n}\n","import type { FetchResponse, RequestConfig } from './types';\n\nexport class ResponseErr extends Error {\n response: FetchResponse;\n request: RequestConfig;\n config: RequestConfig;\n status: number;\n statusText: string;\n\n constructor(\n message: string,\n requestInfo: RequestConfig,\n response: FetchResponse,\n ) {\n super(message);\n\n this.name = 'ResponseError';\n this.message = message;\n this.status = response.status;\n this.statusText = response.statusText;\n this.request = requestInfo;\n this.config = requestInfo;\n this.response = response;\n }\n}\n","export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\nexport const CANCELLED_ERROR = 'CanceledError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\nexport function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const sortedObj = {} as Record;\n const keys = Object.keys(obj);\n\n keys.sort();\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === 'function' ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any) => {\n let i: number, len: number, key: string;\n\n if (prefix) {\n if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n buildParams(\n prefix + '[' + (typeof obj[i] === OBJECT && obj[i] ? i : '') + ']',\n obj[i],\n );\n }\n } else if (typeof obj === OBJECT && obj !== null) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key]);\n }\n } else {\n add(prefix, obj);\n }\n } else if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n add(obj[i].name, obj[i].value);\n }\n } else {\n for (key in obj) {\n buildParams(key, obj[key]);\n }\n }\n return s;\n };\n\n const queryStringParts = buildParams('', params).join('&');\n\n // Encode special characters as per RFC 3986, https://datatracker.ietf.org/doc/html/rfc3986\n const encodedQueryString = queryStringParts.replace(/%5B%5D/g, '[]'); // Keep '[]' for arrays\n\n return appendQueryStringToUrl(url, encodedQueryString);\n}\n\n/**\n * Replaces dynamic URI parameters in a URL string with values from the provided `urlPathParams` object.\n * Parameters in the URL are denoted by `:`, where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:`.\n * @param {Object} urlPathParams - An object containing the parameter values to replace placeholders.\n * @param {string} urlPathParams.paramName - The value to replace the placeholder `:` in the URL.\n * @returns {string} - The URL string with placeholders replaced by corresponding values from `urlPathParams`.\n */\nexport function replaceUrlPathParams(\n url: string,\n urlPathParams: UrlPathParams,\n): string {\n if (!urlPathParams) {\n return url;\n }\n\n return url.replace(/:\\w+/g, (str): string => {\n const word = str.substring(1);\n\n if ((urlPathParams as DefaultUrlParams)[word]) {\n return String((urlPathParams as DefaultUrlParams)[word]);\n }\n\n return str;\n });\n}\n\n/**\n * Checks if a value is JSON serializable.\n *\n * JSON serializable values include:\n * - Primitive types: string, number, boolean, null\n * - Arrays\n * - Plain objects (i.e., objects without special methods)\n * - Values with a `toJSON` method\n *\n * @param {any} value - The value to check for JSON serializability.\n * @returns {boolean} - Returns `true` if the value is JSON serializable, otherwise `false`.\n */\nexport function isJSONSerializable(value: any): boolean {\n const t = typeof value;\n\n if (t === UNDEFINED || value === null) {\n return false;\n }\n\n if (t === STRING || t === 'number' || t === 'boolean') {\n return true;\n }\n\n if (Array.isArray(value)) {\n return true;\n }\n\n if (Buffer.isBuffer(value)) {\n return false;\n }\n\n if (value instanceof Date) {\n return false;\n }\n\n if (t === OBJECT) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` or `null` (plain object)\n if (proto === Object.prototype || proto === null) {\n return true;\n }\n\n // Check if the object has a toJSON method\n if (typeof value.toJSON === 'function') {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any): any {\n if (\n data &&\n typeof data === OBJECT &&\n typeof data.data !== UNDEFINED &&\n Object.keys(data).length === 1\n ) {\n return flattenData(data.data);\n }\n\n return data;\n}\n\n/**\n * Processes headers and returns them as a normalized object.\n *\n * Handles both `Headers` instances and plain objects. Normalizes header keys to lowercase\n * as per RFC 2616 section 4.2.\n *\n * @param headers - The headers to process. Can be an instance of `Headers`, a plain object,\n * or `null`. If `null`, an empty object is returned.\n * @returns {HeadersObject} - A normalized headers object with lowercase keys.\n */\nexport function processHeaders(\n headers?: (HeadersObject & HeadersInit) | null | Headers,\n): HeadersObject {\n if (!headers) {\n return {};\n }\n\n const headersObject: HeadersObject = {};\n\n // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (typeof headers === OBJECT && headers !== null) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * Deletes a property from an object if it exists.\n *\n * @param obj - The object from which to delete the property.\n * @param property - The property to delete from the object.\n */\nexport function deleteProperty>(\n obj: T | null,\n property: keyof T,\n): void {\n if (obj && property in obj) {\n delete obj[property];\n }\n}\n","import { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport type { RequestConfig } from './types';\nimport type { QueueItem, RequestsQueue } from './types/queue-manager';\n\n/**\n * Queue Manager is responsible for managing and controlling the flow of concurrent or sequential requests. It handles:\n * - Request Queueing and Deduplication\n * - Request Timeout Handling\n * - Abort Controller Management and Request Cancellation\n * - Concurrency Control and Locking\n * - Request Lifecycle Management\n */\nconst queue: RequestsQueue = new Map();\n\n/**\n * Adds a request to the queue if it's not already being processed within the dedupeTime interval.\n *\n * @param {RequestConfig} config - The request configuration object.\n * @param {number} timeout - Timeout in milliseconds for the request.\n * @param {number} dedupeTime - Deduplication time in milliseconds.\n * @param {boolean} isCancellable - If true, then the previous request with same configuration should be aborted.\n * @param {boolean} isTimeoutEnabled - Whether timeout is enabled.\n * @returns {Promise} - A promise that resolves to an AbortController.\n */\nexport async function addRequest(\n config: RequestConfig,\n timeout: number | undefined,\n dedupeTime: number = 0,\n isCancellable: boolean = false,\n isTimeoutEnabled: boolean = true,\n): Promise {\n const now = Date.now();\n const item = queue.get(config);\n\n if (item) {\n const isCancellable = item[3];\n const previousController = item[0];\n const timeoutId = item[1];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (!isCancellable && now - item[2] < dedupeTime) {\n return previousController;\n }\n\n // If the request is too old, remove it and proceed to add a new one\n // Abort previous request, if applicable, and continue as usual\n if (isCancellable) {\n previousController.abort(\n new DOMException('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n\n const controller = new AbortController();\n\n const timeoutId = isTimeoutEnabled\n ? setTimeout(() => {\n const error = new DOMException(\n `${config.url} aborted due to timeout`,\n TIMEOUT_ERROR,\n );\n\n removeRequest(config, error);\n }, timeout)\n : null;\n\n queue.set(config, [controller, timeoutId, now, isCancellable]);\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param config - The request configuration.\n * @param {boolean} error - Error payload so to force the request to abort.\n */\nexport async function removeRequest(\n config: RequestConfig,\n error: DOMException | null | string = null,\n): Promise {\n const item = queue.get(config);\n\n if (item) {\n const controller = item[0];\n const timeoutId = item[1];\n\n // If the request is not yet aborted, abort it with the provided error\n if (error && !controller.signal.aborted) {\n controller.abort(error);\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n}\n\n/**\n * Gets the AbortController for a request configuration.\n *\n * @param config - The request configuration.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n config: RequestConfig,\n): Promise {\n const item = queue.get(config);\n\n return item?.[0];\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n} from './constants';\nimport type { DefaultResponse, FetchResponse } from './types/request-handler';\n\n/**\n * Parses the response data based on the Content-Type header.\n *\n * @param response - The Response object to parse.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData(\n response: FetchResponse,\n): Promise {\n // Bail early when body is empty\n if (!response?.body) {\n return null;\n }\n\n const contentType = String(\n (response as Response).headers?.get(CONTENT_TYPE) || '',\n ).split(';')[0]; // Correctly handle charset\n\n let data;\n\n try {\n if (\n contentType.includes(APPLICATION_JSON) ||\n contentType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (contentType.includes('multipart/form-data')) {\n data = await response.formData(); // Parse as FormData\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream')\n ) {\n data = await response.blob(); // Parse as blob\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded')\n ) {\n data = await response.formData(); // Handle URL-encoded forms\n } else if (contentType.includes('text/')) {\n data = await response.text(); // Parse as text\n } else {\n try {\n const responseClone = response.clone();\n\n // Handle edge case of no content type being provided... We assume JSON here.\n data = await responseClone.json();\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_e) {\n // Handle streams\n data = await response.text();\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n // Parsing failed, fallback to null\n data = null;\n }\n\n return data;\n}\n","const PRIME_MULTIPLIER = 31;\n\n/**\n * Computes a hash value for a given string using the variant of djb2 hash function.\n * This hash function is non-cryptographic and designed for speed.\n * @author Daniel J. Bernstein (of djb2)\n *\n * @param str Input string to hash\n * @returns {string} Hash\n */\nexport function hash(str: string): string {\n let hash = 0;\n\n for (let i = 0, len = str.length; i < len; i++) {\n const char = str.charCodeAt(i);\n hash = (hash * PRIME_MULTIPLIER + char) | 0;\n }\n\n return String(hash);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport { fetchf } from './index';\nimport type { FetcherConfig } from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, OBJECT, UNDEFINED } from './constants';\nimport { shallowSerialize, sortObject } from './utils';\n\nconst cache = new Map>();\n\n/**\n * Generates a cache key for a given URL and fetch options, ensuring that key factors\n * like method, headers, body, and other options are included in the cache key.\n * Headers and other objects are sorted by key to ensure consistent cache keys.\n *\n * @param options - The fetch options that may affect the request. The most important are:\n * @property {string} [method=\"GET\"] - The HTTP method (GET, POST, etc.).\n * @property {HeadersInit} [headers={}] - The request headers.\n * @property {BodyInit | null} [body=\"\"] - The body of the request (only for methods like POST, PUT).\n * @property {RequestMode} [mode=\"cors\"] - The mode for the request (e.g., cors, no-cors, include).\n * @property {RequestCredentials} [credentials=\"include\"] - Whether to include credentials like cookies.\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @property {RequestRedirect} [redirect=\"follow\"] - How to handle redirects (e.g., follow, error, manual).\n * @property {string} [referrer=\"\"] - The referrer URL to send with the request.\n * @property {string} [integrity=\"\"] - Subresource integrity value (a cryptographic hash for resource validation).\n * @returns {string} - A unique cache key based on the URL and request options. Empty if cache is to be burst.\n *\n * @example\n * const cacheKey = generateCacheKey({\n * url: 'https://api.example.com/data',\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'Alice' }),\n * mode: 'cors',\n * credentials: 'include',\n * });\n * console.log(cacheKey);\n */\nexport function generateCacheKey(options: FetcherConfig): string {\n const {\n url = '',\n method = GET,\n headers = {},\n body = '',\n mode = 'cors',\n credentials = 'include',\n cache = 'default',\n redirect = 'follow',\n referrer = '',\n integrity = '',\n } = options;\n\n // Bail early if cache should be burst\n if (cache === 'reload') {\n return '';\n }\n\n // Sort headers and body + convert sorted to strings for hashing purposes\n // Native serializer is on avg. 3.5x faster than a Fast Hash or FNV-1a\n const headersString = shallowSerialize(sortObject(headers));\n\n let bodyString = '';\n\n // In majority of cases we do not cache body\n if (body !== null) {\n if (typeof body === 'string') {\n bodyString = hash(body);\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n bodyString = hash(bodyString);\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = typeof body === OBJECT ? sortObject(body) : String(body);\n bodyString = hash(JSON.stringify(o));\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n return (\n method +\n url +\n mode +\n credentials +\n cache +\n redirect +\n referrer +\n integrity +\n headersString +\n bodyString\n );\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the maximum stale time.\n *\n * @param {number} timestamp - The timestamp of the cache entry.\n * @param {number} maxStaleTime - The maximum stale time in seconds.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(timestamp: number, maxStaleTime: number): boolean {\n if (!maxStaleTime) {\n return false;\n }\n\n return Date.now() - timestamp > maxStaleTime * 1000;\n}\n\n/**\n * Retrieves a cache entry if it exists and is not expired.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} cacheTime - Maximum time to cache entry.\n * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string,\n cacheTime: number,\n): CacheEntry | null {\n const entry = cache.get(key);\n\n if (entry) {\n if (!isCacheExpired(entry.timestamp, cacheTime)) {\n return entry;\n }\n\n cache.delete(key);\n }\n\n return null;\n}\n\n/**\n * Sets a new cache entry or updates an existing one.\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {boolean} isLoading - Indicates if the data is currently being fetched.\n */\nexport function setCache(\n key: string,\n data: T,\n isLoading: boolean = false,\n): void {\n cache.set(key, {\n data,\n isLoading,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Revalidates a cache entry by fetching fresh data and updating the cache.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @returns {Promise} - A promise that resolves when the revalidation is complete.\n */\nexport async function revalidate(\n key: string,\n config: FetcherConfig,\n): Promise {\n try {\n // Fetch fresh data\n const newData = await fetchf(config.url, {\n ...config,\n cache: 'reload',\n });\n\n setCache(key, newData);\n } catch (error) {\n console.error(`Error revalidating ${config.url}:`, error);\n\n // Rethrow the error to forward it\n throw error;\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n */\nexport function deleteCache(key: string): void {\n cache.delete(key);\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @param {T} newData - The new data to be cached.\n * @param {boolean} revalidateAfter - If true, triggers revalidation after mutation.\n */\nexport function mutate(\n key: string,\n config: FetcherConfig,\n newData: T,\n revalidateAfter: boolean = false,\n): void {\n setCache(key, newData);\n\n if (revalidateAfter) {\n revalidate(key, config);\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n DefaultResponse,\n RequestHandlerConfig,\n RequestConfig,\n Method,\n RetryOptions,\n FetchResponse,\n ResponseError,\n RequestHandlerReturnType,\n CreatedCustomFetcherInstance,\n FetcherConfig,\n} from './types/request-handler';\nimport type {\n BodyPayload,\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n QueryParams,\n} from './types/api-handler';\nimport { applyInterceptor } from './interceptor-manager';\nimport { ResponseErr } from './response-error';\nimport {\n appendQueryParams,\n isJSONSerializable,\n replaceUrlPathParams,\n delayInvocation,\n flattenData,\n processHeaders,\n deleteProperty,\n isSearchParams,\n} from './utils';\nimport { addRequest, removeRequest } from './queue-manager';\nimport {\n ABORT_ERROR,\n APPLICATION_JSON,\n CANCELLED_ERROR,\n CONTENT_TYPE,\n GET,\n HEAD,\n OBJECT,\n STRING,\n UNDEFINED,\n} from './constants';\nimport { parseResponseData } from './response-parser';\nimport { generateCacheKey, getCache, setCache } from './cache-manager';\n\nconst defaultConfig: RequestHandlerConfig = {\n method: GET,\n strategy: 'reject',\n timeout: 30000,\n dedupeTime: 1000,\n defaultResponse: null,\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n [CONTENT_TYPE]: APPLICATION_JSON + ';charset=utf-8',\n },\n retry: {\n delay: 1000,\n maxDelay: 30000,\n resetTimeout: true,\n backoff: 1.5,\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n retryOn: [\n 408, // Request Timeout\n 409, // Conflict\n 425, // Too Early\n 429, // Too Many Requests\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504, // Gateway Timeout\n ],\n },\n};\n\n/**\n * Create Request Handler\n *\n * @param {RequestHandlerConfig} config - Configuration object for the request handler\n * @returns {Object} An object with methods for handling requests\n */\nexport function createRequestHandler(\n config: RequestHandlerConfig,\n): RequestHandlerReturnType {\n const handlerConfig: RequestHandlerConfig = {\n ...defaultConfig,\n ...config,\n };\n\n /**\n * Immediately create instance of custom fetcher if it is defined\n */\n const customFetcher = handlerConfig.fetcher;\n const requestInstance = customFetcher?.create(handlerConfig) || null;\n\n /**\n * Get Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Provider's instance\n */\n const getInstance = (): CreatedCustomFetcherInstance | null => {\n return requestInstance;\n };\n\n /**\n * Gets a configuration value from `reqConfig`, defaulting to `handlerConfig` if not present.\n *\n * @param {RequestConfig} reqConfig - Request configuration object.\n * @param {keyof RequestConfig} name - Key of the configuration value.\n * @returns {T} - The configuration value.\n */\n const getConfig = (\n reqConfig: RequestConfig,\n name: keyof RequestConfig,\n ): T => {\n return typeof reqConfig[name] !== UNDEFINED\n ? reqConfig[name]\n : handlerConfig[name];\n };\n\n /**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\n const logger = (...args: (string | ResponseError)[]): void => {\n if (handlerConfig.logger?.warn) {\n handlerConfig.logger.warn(...args);\n }\n };\n\n /**\n * Build request configuration\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @returns {RequestConfig} - Provider's instance\n */\n const buildConfig = (\n url: string,\n reqConfig: RequestConfig,\n ): FetcherConfig => {\n const method = getConfig(\n reqConfig,\n 'method',\n ).toUpperCase() as Method;\n const isGetAlikeMethod = method === GET || method === HEAD;\n\n const dynamicUrl = replaceUrlPathParams(\n url,\n getConfig(reqConfig, 'urlPathParams'),\n );\n\n // The explicitly passed \"params\"\n const explicitParams = getConfig(reqConfig, 'params');\n\n // The explicitly passed \"body\" or \"data\"\n const explicitBodyData: BodyPayload =\n getConfig(reqConfig, 'body') || getConfig(reqConfig, 'data');\n\n // Final body data\n let body: RequestConfig['data'];\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (!isGetAlikeMethod) {\n body = explicitBodyData;\n }\n\n // Native fetch compatible settings\n const isWithCredentials = getConfig(reqConfig, 'withCredentials');\n\n const credentials = isWithCredentials\n ? 'include'\n : getConfig(reqConfig, 'credentials');\n\n const urlPath = explicitParams\n ? appendQueryParams(dynamicUrl, explicitParams)\n : dynamicUrl;\n const isFullUrl = urlPath.includes('://');\n const baseURL = isFullUrl\n ? ''\n : getConfig(reqConfig, 'baseURL') ||\n getConfig(reqConfig, 'apiUrl');\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (\n body &&\n typeof body !== STRING &&\n !isSearchParams(body) &&\n isJSONSerializable(body)\n ) {\n body = JSON.stringify(body);\n }\n\n return {\n ...reqConfig,\n credentials,\n body,\n method,\n\n url: baseURL + urlPath,\n };\n };\n\n /**\n * Process global Request Error\n *\n * @param {ResponseError} error Error instance\n * @param {RequestConfig} requestConfig Per endpoint request config\n * @returns {Promise}\n */\n const processError = async (\n error: ResponseError,\n requestConfig: RequestConfig,\n ): Promise => {\n if (!isRequestCancelled(error)) {\n logger('API ERROR', error);\n }\n\n // Local interceptors\n await applyInterceptor(error, requestConfig?.onError);\n\n // Global interceptors\n await applyInterceptor(error, handlerConfig?.onError);\n };\n\n /**\n * Output default response in case of an error, depending on chosen strategy\n *\n * @param {ResponseError} error - Error instance\n * @param {FetchResponse | null} response - Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Per endpoint request config\n * @returns {FetchResponse} Response together with the error object\n */\n const outputErrorResponse = async (\n error: ResponseError,\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n ): Promise => {\n const _isRequestCancelled = isRequestCancelled(error);\n const errorHandlingStrategy = getConfig(requestConfig, 'strategy');\n const rejectCancelled = getConfig(\n requestConfig,\n 'rejectCancelled',\n );\n\n // By default cancelled requests aren't rejected (softFail strategy)\n if (!(_isRequestCancelled && !rejectCancelled)) {\n // Hang the promise\n if (errorHandlingStrategy === 'silent') {\n await new Promise(() => null);\n }\n // Reject the promise\n else if (errorHandlingStrategy === 'reject') {\n return Promise.reject(error);\n }\n }\n\n return outputResponse(response, requestConfig, error);\n };\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {ResponseError} error Error instance\n * @returns {boolean} True if request is aborted\n */\n const isRequestCancelled = (error: ResponseError): boolean => {\n return error.name === ABORT_ERROR || error.name === CANCELLED_ERROR;\n };\n\n /**\n * Handle Request depending on used strategy\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config\n * @throws {ResponseError}\n * @returns {Promise>} Response Data\n */\n const request = async <\n ResponseData = DefaultResponse,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n RequestBody = DefaultPayload,\n >(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n ): Promise> => {\n const _reqConfig = reqConfig || {};\n const mergedConfig = {\n ...handlerConfig,\n ..._reqConfig,\n } as RequestConfig;\n\n let response: FetchResponse | null = null;\n const fetcherConfig = buildConfig(url, mergedConfig);\n\n const {\n timeout,\n cancellable,\n dedupeTime,\n pollingInterval,\n shouldStopPolling,\n cacheTime,\n cacheKey,\n } = mergedConfig;\n\n // Prevent performance overhead of cache access\n let _cacheKey: string;\n\n if (cacheKey) {\n _cacheKey = cacheKey(fetcherConfig);\n } else {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n if (cacheTime && _cacheKey) {\n const cacheBuster = mergedConfig.cacheBuster;\n\n if (!cacheBuster || !cacheBuster(fetcherConfig)) {\n const cachedEntry = getCache>(\n _cacheKey,\n cacheTime,\n );\n\n if (cachedEntry) {\n // Serve stale data from cache\n return cachedEntry.data;\n }\n }\n }\n\n const {\n retries = 0,\n delay,\n backoff,\n retryOn,\n shouldRetry,\n maxDelay,\n resetTimeout,\n } = mergedConfig.retry as Required;\n\n let attempt = 0;\n let pollingAttempt = 0;\n let waitTime: number = delay;\n const _retries = retries > 0 ? retries : 0;\n\n while (attempt <= _retries) {\n try {\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = await addRequest(\n fetcherConfig,\n timeout,\n dedupeTime,\n cancellable,\n // Reset timeouts by default or when retries are ON\n !!(timeout && (!_retries || resetTimeout)),\n );\n\n // Shallow copy to ensure basic idempotency\n const requestConfig: RequestConfig = {\n signal: controller.signal,\n ...fetcherConfig,\n };\n\n // Local interceptors\n await applyInterceptor(requestConfig, _reqConfig?.onRequest);\n\n // Global interceptors\n await applyInterceptor(requestConfig, handlerConfig?.onRequest);\n\n if (customFetcher !== null && requestInstance !== null) {\n response = await requestInstance.request(requestConfig);\n } else {\n response = (await fetch(\n requestConfig.url as string,\n requestConfig as RequestInit,\n )) as FetchResponse;\n }\n\n // Add more information to response object\n if (response instanceof Response) {\n response.config = requestConfig;\n response.data = await parseResponseData(response);\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n if (!response.ok) {\n throw new ResponseErr(\n `${requestConfig.url} failed! Status: ${response.status || null}`,\n requestConfig,\n response,\n );\n }\n }\n\n // Local interceptors\n await applyInterceptor(response, _reqConfig?.onResponse);\n\n // Global interceptors\n await applyInterceptor(response, handlerConfig?.onResponse);\n\n removeRequest(fetcherConfig);\n\n // Polling logic\n if (\n pollingInterval &&\n (!shouldStopPolling || !shouldStopPolling(response, pollingAttempt))\n ) {\n // Restart the main retry loop\n pollingAttempt++;\n\n logger(`Polling attempt ${pollingAttempt}...`);\n\n await delayInvocation(pollingInterval);\n\n continue;\n }\n\n // If polling is not required, or polling attempts are exhausted\n const output = outputResponse(response, requestConfig);\n\n if (cacheTime && _cacheKey) {\n const skipCache = requestConfig.skipCache;\n\n if (!skipCache || !skipCache(output, requestConfig)) {\n setCache(_cacheKey, output);\n }\n }\n\n return output;\n } catch (err) {\n const error = err as ResponseErr;\n const status = error?.response?.status || error?.status || 0;\n\n if (\n attempt === retries ||\n !(!shouldRetry || (await shouldRetry(error, attempt))) ||\n !retryOn?.includes(status)\n ) {\n await processError(error, fetcherConfig);\n\n removeRequest(fetcherConfig);\n\n return outputErrorResponse(\n error,\n response,\n fetcherConfig,\n );\n }\n\n logger(`Attempt ${attempt + 1} failed. Retry in ${waitTime}ms.`);\n\n await delayInvocation(waitTime);\n\n waitTime *= backoff;\n waitTime = Math.min(waitTime, maxDelay);\n attempt++;\n }\n }\n\n return outputResponse(response, fetcherConfig);\n };\n\n /**\n * Output response\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\n const outputResponse = (\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n error: ResponseError | null = null,\n ): FetchResponse => {\n const defaultResponse = getConfig(requestConfig, 'defaultResponse');\n\n // This may happen when request is cancelled.\n if (!response) {\n return {\n ok: false,\n // Enhance the response with extra information\n error,\n data: defaultResponse,\n headers: null,\n config: requestConfig,\n } as unknown as FetchResponse;\n }\n\n // Clean up the error object\n deleteProperty(error, 'response');\n deleteProperty(error, 'request');\n deleteProperty(error, 'config');\n\n let data = response?.data;\n\n // Set the default response if the provided data is an empty object\n if (\n data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0)\n ) {\n data = defaultResponse;\n }\n\n // Return flattened response immediately\n const flattenResponse = getConfig(\n requestConfig,\n 'flattenResponse',\n );\n\n if (flattenResponse) {\n response.data = flattenData(data);\n }\n\n // If it's a custom fetcher, and it does not return any Response instance, it may have its own internal handler\n if (!(response instanceof Response)) {\n return response;\n }\n\n // Native fetch Response extended by extra information\n return {\n body: response.body,\n bodyUsed: response.bodyUsed,\n formData: response.formData,\n ok: response.ok,\n redirected: response.redirected,\n type: response.type,\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n\n blob: response.blob.bind(response),\n json: response.json.bind(response),\n text: response.text.bind(response),\n clone: response.clone.bind(response),\n arrayBuffer: response.arrayBuffer.bind(response),\n\n // Enhance the response with extra information\n error,\n data,\n headers: processHeaders(response.headers),\n config: requestConfig,\n };\n };\n\n return {\n getInstance,\n buildConfig,\n config,\n request,\n };\n}\n","import type {\n RequestConfig,\n FetchResponse,\n DefaultResponse,\n CreatedCustomFetcherInstance,\n} from './types/request-handler';\nimport type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n DefaultPayload,\n FallbackValue,\n FinalParams,\n FinalResponse,\n QueryParams,\n RequestConfigUrlRequired,\n UrlPathParams,\n} from './types/api-handler';\nimport { createRequestHandler } from './request-handler';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if it is passed as \"fetcher\".\n * @url https://github.com/MattCCC/fetchff\n *\n * @param {Object} config - Configuration object for the API fetcher.\n * @param {string} config.apiUrl - The base URL for the API.\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {number} config.timeout - You can set the timeout for particular request in milliseconds.\n * @param {number} config.cancellable - If true, the ongoing previous requests will be automatically cancelled.\n * @param {number} config.rejectCancelled - If true and request is set to cancellable, a cancelled request promise will be rejected. By default, instead of rejecting the promise, defaultResponse is returned.\n * @param {number} config.timeout - Request timeout\n * @param {number} config.dedupeTime - Time window, in milliseconds, during which identical requests are deduplicated (treated as single request).\n * @param {string} config.strategy - Error Handling Strategy\n * @param {string} config.flattenResponse - Whether to flatten response \"data\" object within \"data\". It works only if the response structure includes a single data property.\n * @param {*} config.defaultResponse - Default response when there is no data or when endpoint fails depending on the chosen strategy. It's \"null\" by default\n * @param {Object} [config.retry] - Options for retrying requests.\n * @param {number} [config.retry.retries=0] - Number of retry attempts. No retries by default.\n * @param {number} [config.retry.delay=1000] - Initial delay between retries in milliseconds.\n * @param {number} [config.retry.backoff=1.5] - Exponential backoff factor.\n * @param {number[]} [config.retry.retryOn=[502, 504, 408]] - HTTP status codes to retry on.\n * @param {RequestInterceptor|RequestInterceptor[]} [config.onRequest] - Optional request interceptor function or an array of functions.\n * These functions will be called with the request configuration object before the request is made. Can be used to modify or log the request configuration.\n * @param {ResponseInterceptor|ResponseInterceptor[]} [config.onResponse] - Optional response interceptor function or an array of functions.\n * These functions will be called with the response object after the response is received. an be used to modify or log the response data.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Object} config.fetcher - The Custom Fetcher instance to use for making requests. It should expose create() and request() functions.\n * @param {*} config.logger - Instance of custom logger. Either class or an object similar to \"console\". Console is used by default.\n * @returns API handler functions and endpoints to call\n *\n * @example\n * // Define endpoint paths\n * const endpoints = {\n * getUser: '/user',\n * createPost: '/post',\n * };\n *\n * // Create the API fetcher with configuration\n * const api = createApiFetcher({\n * endpoints,\n * apiUrl: 'https://example.com/api',\n * onError(error) {\n * console.log('Request failed', error);\n * },\n * headers: {\n * 'my-auth-key': 'example-auth-key-32rjjfa',\n * },\n * });\n *\n * // Fetch user data\n * const response = await api.getUser({ userId: 1, ratings: [1, 2] })\n */\nfunction createApiFetcher<\n EndpointsMethods extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n const requestHandler = createRequestHandler(config);\n\n /**\n * Get Custom Fetcher Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Request Handler's Custom Fetcher Instance\n */\n function getInstance(): CreatedCustomFetcherInstance | null {\n return requestHandler.getInstance();\n }\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n function handleNonImplemented(endpointName: string): Promise {\n console.error(`Add ${endpointName} to 'endpoints'.`);\n\n return Promise.resolve(null);\n }\n\n /**\n * Handle Single API Request\n * It considers settings in following order: per-request settings, global per-endpoint settings, global settings.\n *\n * @param {keyof EndpointsMethods | string} endpointName - The name of the API endpoint to call.\n * @param {EndpointConfig} [requestConfig={}] - Additional configuration for the request.\n * @returns {Promise>} - A promise that resolves with the response from the API provider.\n */\n async function request<\n ResponseData = never,\n QueryParams_ = never,\n UrlParams = never,\n RequestBody = never,\n >(\n endpointName: keyof EndpointsMethods | string,\n requestConfig: RequestConfig<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n > = {},\n ): Promise>> {\n // Use global per-endpoint settings\n const endpointConfig =\n endpoints[endpointName] ||\n ({ url: endpointName as string } as RequestConfigUrlRequired);\n\n const responseData = await requestHandler.request<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n >(endpointConfig.url, {\n ...endpointConfig,\n ...requestConfig,\n });\n\n return responseData;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\n requestHandler,\n getInstance,\n request,\n };\n\n /**\n * Maps all API requests using native Proxy\n *\n * @param {*} prop Caller\n */\n return new Proxy>(\n apiHandler as ApiHandlerMethods,\n {\n get(_target, prop: string) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"],"mappings":"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","names":["src_exports","__export","createApiFetcher","fetchf","applyInterceptor","object","interceptors","value","interceptor","ResponseErr","message","requestInfo","response","__publicField","APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","ABORT_ERROR","TIMEOUT_ERROR","CANCELLED_ERROR","GET","HEAD","isSearchParams","data","shallowSerialize","obj","result","key","sortObject","sortedObj","keys","i","len","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","isSearchParams","encodedQueryString","s","encode","add","k","v","buildParams","prefix","OBJECT","replaceUrlPathParams","urlPathParams","str","word","isJSONSerializable","value","UNDEFINED","STRING","proto","delayInvocation","ms","resolve","flattenData","data","processHeaders","headers","headersObject","deleteProperty","property","queue","addRequest","config","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","previousController","timeoutId","ABORT_ERROR","controller","error","TIMEOUT_ERROR","removeRequest","parseResponseData","response","_a","contentType","CONTENT_TYPE","data","APPLICATION_JSON","APPLICATION_CONTENT_TYPE","_e","_error","hash","str","i","len","char","cache","generateCacheKey","options","url","method","GET","headers","body","mode","credentials","redirect","referrer","integrity","headersString","shallowSerialize","sortObject","bodyString","hash","value","key","UNDEFINED","o","OBJECT","isCacheExpired","timestamp","maxStaleTime","getCache","cacheTime","entry","setCache","data","isLoading","defaultConfig","GET","APPLICATION_JSON","CONTENT_TYPE","createRequestHandler","config","handlerConfig","customFetcher","requestInstance","getInstance","getConfig","reqConfig","name","UNDEFINED","logger","args","_a","buildConfig","url","method","isGetAlikeMethod","HEAD","dynamicUrl","replaceUrlPathParams","explicitParams","explicitBodyData","body","credentials","urlPath","appendQueryParams","baseURL","STRING","isSearchParams","isJSONSerializable","processError","error","requestConfig","isRequestCancelled","applyInterceptor","outputErrorResponse","response","_isRequestCancelled","errorHandlingStrategy","rejectCancelled","outputResponse","ABORT_ERROR","CANCELLED_ERROR","request","_reqConfig","mergedConfig","fetcherConfig","timeout","cancellable","dedupeTime","pollingInterval","shouldStopPolling","cacheTime","cacheKey","_cacheKey","generateCacheKey","cacheBuster","cachedEntry","getCache","retries","delay","backoff","retryOn","shouldRetry","maxDelay","resetTimeout","attempt","pollingAttempt","waitTime","_retries","addRequest","parseResponseData","ResponseErr","removeRequest","delayInvocation","output","skipCache","setCache","err","status","defaultResponse","deleteProperty","data","OBJECT","flattenData","processHeaders","createApiFetcher","config","endpoints","requestHandler","createRequestHandler","getInstance","handleNonImplemented","endpointName","request","requestConfig","endpointConfig","apiHandler","_target","prop","fetchf","url","config","createRequestHandler"]} \ No newline at end of file +{"version":3,"sources":["../../src/index.ts","../../src/interceptor-manager.ts","../../src/response-error.ts","../../src/constants.ts","../../src/utils.ts","../../src/queue-manager.ts","../../src/response-parser.ts","../../src/hash.ts","../../src/cache-manager.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"sourcesContent":["import { createRequestHandler } from './request-handler';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestHandlerConfig,\n} from './types';\n\n/**\n * Simple wrapper for request fetching.\n * It abstracts the creation of RequestHandler, making it easy to perform API requests.\n *\n * @param {string | URL | globalThis.Request} url - Request URL.\n * @param {RequestHandlerConfig} config - Configuration object for the request handler.\n * @returns {Promise>} Response Data.\n */\nexport async function fetchf(\n url: string,\n config: RequestHandlerConfig = {},\n): Promise> {\n return createRequestHandler(config).request(url, config);\n}\n\nexport * from './types';\nexport * from './api-handler';\n","type InterceptorFunction = (object: T) => Promise;\n\n/**\n * Applies interceptors to the object. Interceptors can be a single function or an array of functions.\n *\n * @template T - Type of the object.\n * @template I - Type of interceptors.\n *\n * @param {T} object - The object to process.\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptor<\n T extends object,\n I = InterceptorFunction | InterceptorFunction[],\n>(object: T, interceptors?: I): Promise {\n if (!interceptors) {\n return;\n }\n\n if (typeof interceptors === 'function') {\n const value = await interceptors(object);\n\n if (value) {\n Object.assign(object, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(object);\n\n if (value) {\n Object.assign(object, value);\n }\n }\n }\n}\n","import type { FetchResponse, RequestConfig } from './types';\n\nexport class ResponseErr extends Error {\n response: FetchResponse;\n request: RequestConfig;\n config: RequestConfig;\n status: number;\n statusText: string;\n\n constructor(\n message: string,\n requestInfo: RequestConfig,\n response: FetchResponse,\n ) {\n super(message);\n\n this.name = 'ResponseError';\n this.message = message;\n this.status = response.status;\n this.statusText = response.statusText;\n this.request = requestInfo;\n this.config = requestInfo;\n this.response = response;\n }\n}\n","export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\nexport const CANCELLED_ERROR = 'CanceledError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\nexport function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const sortedObj = {} as Record;\n const keys = Object.keys(obj);\n\n keys.sort();\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === 'function' ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any) => {\n let i: number, len: number, key: string;\n\n if (prefix) {\n if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n buildParams(\n prefix + '[' + (typeof obj[i] === OBJECT && obj[i] ? i : '') + ']',\n obj[i],\n );\n }\n } else if (typeof obj === OBJECT && obj !== null) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key]);\n }\n } else {\n add(prefix, obj);\n }\n } else if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n add(obj[i].name, obj[i].value);\n }\n } else {\n for (key in obj) {\n buildParams(key, obj[key]);\n }\n }\n return s;\n };\n\n const queryStringParts = buildParams('', params).join('&');\n\n // Encode special characters as per RFC 3986, https://datatracker.ietf.org/doc/html/rfc3986\n const encodedQueryString = queryStringParts.replace(/%5B%5D/g, '[]'); // Keep '[]' for arrays\n\n return appendQueryStringToUrl(url, encodedQueryString);\n}\n\n/**\n * Replaces dynamic URI parameters in a URL string with values from the provided `urlPathParams` object.\n * Parameters in the URL are denoted by `:`, where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:`.\n * @param {Object} urlPathParams - An object containing the parameter values to replace placeholders.\n * @param {string} urlPathParams.paramName - The value to replace the placeholder `:` in the URL.\n * @returns {string} - The URL string with placeholders replaced by corresponding values from `urlPathParams`.\n */\nexport function replaceUrlPathParams(\n url: string,\n urlPathParams: UrlPathParams,\n): string {\n if (!urlPathParams) {\n return url;\n }\n\n return url.replace(/:\\w+/g, (str): string => {\n const word = str.substring(1);\n\n if ((urlPathParams as DefaultUrlParams)[word]) {\n return String((urlPathParams as DefaultUrlParams)[word]);\n }\n\n return str;\n });\n}\n\n/**\n * Checks if a value is JSON serializable.\n *\n * JSON serializable values include:\n * - Primitive types: string, number, boolean, null\n * - Arrays\n * - Plain objects (i.e., objects without special methods)\n * - Values with a `toJSON` method\n *\n * @param {any} value - The value to check for JSON serializability.\n * @returns {boolean} - Returns `true` if the value is JSON serializable, otherwise `false`.\n */\nexport function isJSONSerializable(value: any): boolean {\n const t = typeof value;\n\n if (t === UNDEFINED || value === null) {\n return false;\n }\n\n if (t === STRING || t === 'number' || t === 'boolean') {\n return true;\n }\n\n if (Array.isArray(value)) {\n return true;\n }\n\n if (Buffer.isBuffer(value)) {\n return false;\n }\n\n if (value instanceof Date) {\n return false;\n }\n\n if (t === OBJECT) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` or `null` (plain object)\n if (proto === Object.prototype || proto === null) {\n return true;\n }\n\n // Check if the object has a toJSON method\n if (typeof value.toJSON === 'function') {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any): any {\n if (\n data &&\n typeof data === OBJECT &&\n typeof data.data !== UNDEFINED &&\n Object.keys(data).length === 1\n ) {\n return flattenData(data.data);\n }\n\n return data;\n}\n\n/**\n * Processes headers and returns them as a normalized object.\n *\n * Handles both `Headers` instances and plain objects. Normalizes header keys to lowercase\n * as per RFC 2616 section 4.2.\n *\n * @param headers - The headers to process. Can be an instance of `Headers`, a plain object,\n * or `null`. If `null`, an empty object is returned.\n * @returns {HeadersObject} - A normalized headers object with lowercase keys.\n */\nexport function processHeaders(\n headers?: (HeadersObject & HeadersInit) | null | Headers,\n): HeadersObject {\n if (!headers) {\n return {};\n }\n\n const headersObject: HeadersObject = {};\n\n // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (typeof headers === OBJECT && headers !== null) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * Deletes a property from an object if it exists.\n *\n * @param obj - The object from which to delete the property.\n * @param property - The property to delete from the object.\n */\nexport function deleteProperty>(\n obj: T | null,\n property: keyof T,\n): void {\n if (obj && property in obj) {\n delete obj[property];\n }\n}\n","import { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport type { RequestConfig } from './types';\nimport type { QueueItem, RequestsQueue } from './types/queue-manager';\n\n/**\n * Queue Manager is responsible for managing and controlling the flow of concurrent or sequential requests. It handles:\n * - Request Queueing and Deduplication\n * - Request Timeout Handling\n * - Abort Controller Management and Request Cancellation\n * - Concurrency Control and Locking\n * - Request Lifecycle Management\n */\nconst queue: RequestsQueue = new Map();\n\n/**\n * Adds a request to the queue if it's not already being processed within the dedupeTime interval.\n *\n * @param {RequestConfig} config - The request configuration object.\n * @param {number} timeout - Timeout in milliseconds for the request.\n * @param {number} dedupeTime - Deduplication time in milliseconds.\n * @param {boolean} isCancellable - If true, then the previous request with same configuration should be aborted.\n * @param {boolean} isTimeoutEnabled - Whether timeout is enabled.\n * @returns {Promise} - A promise that resolves to an AbortController.\n */\nexport async function addRequest(\n config: RequestConfig,\n timeout: number | undefined,\n dedupeTime: number = 0,\n isCancellable: boolean = false,\n isTimeoutEnabled: boolean = true,\n): Promise {\n const now = Date.now();\n const item = queue.get(config);\n\n if (item) {\n const isCancellable = item[3];\n const previousController = item[0];\n const timeoutId = item[1];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (!isCancellable && now - item[2] < dedupeTime) {\n return previousController;\n }\n\n // If the request is too old, remove it and proceed to add a new one\n // Abort previous request, if applicable, and continue as usual\n if (isCancellable) {\n previousController.abort(\n new DOMException('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n\n const controller = new AbortController();\n\n const timeoutId = isTimeoutEnabled\n ? setTimeout(() => {\n const error = new DOMException(\n `${config.url} aborted due to timeout`,\n TIMEOUT_ERROR,\n );\n\n removeRequest(config, error);\n }, timeout)\n : null;\n\n queue.set(config, [controller, timeoutId, now, isCancellable]);\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param config - The request configuration.\n * @param {boolean} error - Error payload so to force the request to abort.\n */\nexport async function removeRequest(\n config: RequestConfig,\n error: DOMException | null | string = null,\n): Promise {\n const item = queue.get(config);\n\n if (item) {\n const controller = item[0];\n const timeoutId = item[1];\n\n // If the request is not yet aborted, abort it with the provided error\n if (error && !controller.signal.aborted) {\n controller.abort(error);\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n}\n\n/**\n * Gets the AbortController for a request configuration.\n *\n * @param config - The request configuration.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n config: RequestConfig,\n): Promise {\n const item = queue.get(config);\n\n return item?.[0];\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n} from './constants';\nimport type { DefaultResponse, FetchResponse } from './types/request-handler';\n\n/**\n * Parses the response data based on the Content-Type header.\n *\n * @param response - The Response object to parse.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData(\n response: FetchResponse,\n): Promise {\n // Bail early when body is empty\n if (!response?.body) {\n return null;\n }\n\n const contentType = String(\n (response as Response).headers?.get(CONTENT_TYPE) || '',\n ).split(';')[0]; // Correctly handle charset\n\n let data;\n\n try {\n if (\n contentType.includes(APPLICATION_JSON) ||\n contentType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (contentType.includes('multipart/form-data')) {\n data = await response.formData(); // Parse as FormData\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream')\n ) {\n data = await response.blob(); // Parse as blob\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded')\n ) {\n data = await response.formData(); // Handle URL-encoded forms\n } else if (contentType.includes('text/')) {\n data = await response.text(); // Parse as text\n } else {\n try {\n const responseClone = response.clone();\n\n // Handle edge case of no content type being provided... We assume JSON here.\n data = await responseClone.json();\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_e) {\n // Handle streams\n data = await response.text();\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n // Parsing failed, fallback to null\n data = null;\n }\n\n return data;\n}\n","const PRIME_MULTIPLIER = 31;\n\n/**\n * Computes a hash value for a given string using the variant of djb2 hash function.\n * This hash function is non-cryptographic and designed for speed.\n * @author Daniel J. Bernstein (of djb2)\n *\n * @param str Input string to hash\n * @returns {string} Hash\n */\nexport function hash(str: string): string {\n let hash = 0;\n\n for (let i = 0, len = str.length; i < len; i++) {\n const char = str.charCodeAt(i);\n hash = (hash * PRIME_MULTIPLIER + char) | 0;\n }\n\n return String(hash);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport { fetchf } from './index';\nimport type { FetcherConfig } from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, OBJECT, UNDEFINED } from './constants';\nimport { shallowSerialize, sortObject } from './utils';\n\nconst cache = new Map>();\n\n/**\n * Generates a cache key for a given URL and fetch options, ensuring that key factors\n * like method, headers, body, and other options are included in the cache key.\n * Headers and other objects are sorted by key to ensure consistent cache keys.\n *\n * @param options - The fetch options that may affect the request. The most important are:\n * @property {string} [method=\"GET\"] - The HTTP method (GET, POST, etc.).\n * @property {HeadersInit} [headers={}] - The request headers.\n * @property {BodyInit | null} [body=\"\"] - The body of the request (only for methods like POST, PUT).\n * @property {RequestMode} [mode=\"cors\"] - The mode for the request (e.g., cors, no-cors, include).\n * @property {RequestCredentials} [credentials=\"include\"] - Whether to include credentials like cookies.\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @property {RequestRedirect} [redirect=\"follow\"] - How to handle redirects (e.g., follow, error, manual).\n * @property {string} [referrer=\"\"] - The referrer URL to send with the request.\n * @property {string} [integrity=\"\"] - Subresource integrity value (a cryptographic hash for resource validation).\n * @returns {string} - A unique cache key based on the URL and request options. Empty if cache is to be burst.\n *\n * @example\n * const cacheKey = generateCacheKey({\n * url: 'https://api.example.com/data',\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'Alice' }),\n * mode: 'cors',\n * credentials: 'include',\n * });\n * console.log(cacheKey);\n */\nexport function generateCacheKey(options: FetcherConfig): string {\n const {\n url = '',\n method = GET,\n headers = {},\n body = '',\n mode = 'cors',\n credentials = 'include',\n cache = 'default',\n redirect = 'follow',\n referrer = '',\n integrity = '',\n } = options;\n\n // Bail early if cache should be burst\n if (cache === 'reload') {\n return '';\n }\n\n // Sort headers and body + convert sorted to strings for hashing purposes\n // Native serializer is on avg. 3.5x faster than a Fast Hash or FNV-1a\n const headersString = shallowSerialize(sortObject(headers));\n\n let bodyString = '';\n\n // In majority of cases we do not cache body\n if (body !== null) {\n if (typeof body === 'string') {\n bodyString = hash(body);\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n bodyString = hash(bodyString);\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = typeof body === OBJECT ? sortObject(body) : String(body);\n bodyString = hash(JSON.stringify(o));\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n return (\n method +\n url +\n mode +\n credentials +\n cache +\n redirect +\n referrer +\n integrity +\n headersString +\n bodyString\n );\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the maximum stale time.\n *\n * @param {number} timestamp - The timestamp of the cache entry.\n * @param {number} maxStaleTime - The maximum stale time in seconds.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(timestamp: number, maxStaleTime: number): boolean {\n if (!maxStaleTime) {\n return false;\n }\n\n return Date.now() - timestamp > maxStaleTime * 1000;\n}\n\n/**\n * Retrieves a cache entry if it exists and is not expired.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} cacheTime - Maximum time to cache entry.\n * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string,\n cacheTime: number,\n): CacheEntry | null {\n const entry = cache.get(key);\n\n if (entry) {\n if (!isCacheExpired(entry.timestamp, cacheTime)) {\n return entry;\n }\n\n cache.delete(key);\n }\n\n return null;\n}\n\n/**\n * Sets a new cache entry or updates an existing one.\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {boolean} isLoading - Indicates if the data is currently being fetched.\n */\nexport function setCache(\n key: string,\n data: T,\n isLoading: boolean = false,\n): void {\n cache.set(key, {\n data,\n isLoading,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Revalidates a cache entry by fetching fresh data and updating the cache.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @returns {Promise} - A promise that resolves when the revalidation is complete.\n */\nexport async function revalidate(\n key: string,\n config: FetcherConfig,\n): Promise {\n try {\n // Fetch fresh data\n const newData = await fetchf(config.url, {\n ...config,\n cache: 'reload',\n });\n\n setCache(key, newData);\n } catch (error) {\n console.error(`Error revalidating ${config.url}:`, error);\n\n // Rethrow the error to forward it\n throw error;\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n */\nexport function deleteCache(key: string): void {\n cache.delete(key);\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @param {T} newData - The new data to be cached.\n * @param {boolean} revalidateAfter - If true, triggers revalidation after mutation.\n */\nexport function mutate(\n key: string,\n config: FetcherConfig,\n newData: T,\n revalidateAfter: boolean = false,\n): void {\n setCache(key, newData);\n\n if (revalidateAfter) {\n revalidate(key, config);\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n DefaultResponse,\n RequestHandlerConfig,\n RequestConfig,\n Method,\n RetryOptions,\n FetchResponse,\n ResponseError,\n RequestHandlerReturnType,\n CreatedCustomFetcherInstance,\n FetcherConfig,\n FetcherInstance,\n Logger,\n} from './types/request-handler';\nimport type {\n BodyPayload,\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n QueryParams,\n} from './types/api-handler';\nimport { applyInterceptor } from './interceptor-manager';\nimport { ResponseErr } from './response-error';\nimport {\n appendQueryParams,\n isJSONSerializable,\n replaceUrlPathParams,\n delayInvocation,\n flattenData,\n processHeaders,\n deleteProperty,\n isSearchParams,\n} from './utils';\nimport { addRequest, removeRequest } from './queue-manager';\nimport {\n ABORT_ERROR,\n APPLICATION_JSON,\n CANCELLED_ERROR,\n CONTENT_TYPE,\n GET,\n HEAD,\n OBJECT,\n STRING,\n UNDEFINED,\n} from './constants';\nimport { parseResponseData } from './response-parser';\nimport { generateCacheKey, getCache, setCache } from './cache-manager';\n\nconst defaultConfig: RequestHandlerConfig = {\n method: GET,\n strategy: 'reject',\n timeout: 30000,\n dedupeTime: 1000,\n defaultResponse: null,\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n [CONTENT_TYPE]: APPLICATION_JSON + ';charset=utf-8',\n },\n retry: {\n delay: 1000,\n maxDelay: 30000,\n resetTimeout: true,\n backoff: 1.5,\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n retryOn: [\n 408, // Request Timeout\n 409, // Conflict\n 425, // Too Early\n 429, // Too Many Requests\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504, // Gateway Timeout\n ],\n },\n};\n\n/**\n * Create Request Handler\n *\n * @param {RequestHandlerConfig} config - Configuration object for the request handler\n * @returns {Object} An object with methods for handling requests\n */\nexport function createRequestHandler(\n config: RequestHandlerConfig,\n): RequestHandlerReturnType {\n const handlerConfig: RequestHandlerConfig = {\n ...defaultConfig,\n ...config,\n };\n\n /**\n * Merges the specified property from the base configuration and the new configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and new configurations. Must be a key of RequestHandlerConfig.\n * @param {RequestHandlerConfig} targetConfig - The configuration object that will receive the merged properties.\n * @param {RequestHandlerConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestHandlerConfig} newConfig - The new configuration object that contains user-specific settings to merge.\n */\n const mergeConfig = (\n property: K,\n targetConfig: RequestHandlerConfig,\n baseConfig: RequestHandlerConfig,\n newConfig: RequestHandlerConfig,\n ) => {\n if (newConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...newConfig[property],\n };\n }\n };\n\n mergeConfig('retry', handlerConfig, defaultConfig, config);\n mergeConfig('headers', handlerConfig, defaultConfig, config);\n\n /**\n * Gets a configuration value from `reqConfig`, defaulting to `handlerConfig` if not present.\n *\n * @param {RequestConfig} reqConfig - Request configuration object.\n * @param {keyof RequestConfig} name - Key of the configuration value.\n * @returns {T} - The configuration value.\n */\n const getConfig = (\n reqConfig: RequestConfig,\n name: keyof RequestConfig,\n ): T => {\n return typeof reqConfig[name] !== UNDEFINED\n ? reqConfig[name]\n : handlerConfig[name];\n };\n\n /**\n * Immediately create instance of custom fetcher if it is defined\n */\n const customFetcher = getConfig(config, 'fetcher');\n const requestInstance = customFetcher?.create(handlerConfig) || null;\n\n /**\n * Get Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Provider's instance\n */\n const getInstance = (): CreatedCustomFetcherInstance | null => {\n return requestInstance;\n };\n\n /**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\n const logger = (\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n ): void => {\n const logger = getConfig(reqConfig, 'logger');\n\n if (logger?.warn) {\n logger.warn(...args);\n }\n };\n\n /**\n * Build request configuration\n *\n * @param {string} url - Request url\n * @param {RequestConfig} requestConfig - Request config passed when making the request\n * @returns {RequestConfig} - Provider's instance\n */\n const buildConfig = (\n url: string,\n requestConfig: RequestConfig,\n ): FetcherConfig => {\n const method = getConfig(\n requestConfig,\n 'method',\n ).toUpperCase() as Method;\n const isGetAlikeMethod = method === GET || method === HEAD;\n\n const dynamicUrl = replaceUrlPathParams(\n url,\n getConfig(requestConfig, 'urlPathParams'),\n );\n\n // The explicitly passed \"params\"\n const explicitParams = getConfig(requestConfig, 'params');\n\n // The explicitly passed \"body\" or \"data\"\n const explicitBodyData: BodyPayload =\n getConfig(requestConfig, 'body') || getConfig(requestConfig, 'data');\n\n // Final body data\n let body: RequestConfig['data'];\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (!isGetAlikeMethod) {\n body = explicitBodyData;\n }\n\n // Native fetch compatible settings\n const isWithCredentials = getConfig(\n requestConfig,\n 'withCredentials',\n );\n\n const credentials = isWithCredentials\n ? 'include'\n : getConfig(requestConfig, 'credentials');\n\n const urlPath = explicitParams\n ? appendQueryParams(dynamicUrl, explicitParams)\n : dynamicUrl;\n const isFullUrl = urlPath.includes('://');\n const baseURL = isFullUrl\n ? ''\n : getConfig(requestConfig, 'baseURL') ||\n getConfig(requestConfig, 'apiUrl');\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (\n body &&\n typeof body !== STRING &&\n !isSearchParams(body) &&\n isJSONSerializable(body)\n ) {\n body = JSON.stringify(body);\n }\n\n return {\n ...requestConfig,\n credentials,\n body,\n method,\n\n url: baseURL + urlPath,\n };\n };\n\n /**\n * Process global Request Error\n *\n * @param {ResponseError} error Error instance\n * @param {RequestConfig} requestConfig Per endpoint request config\n * @returns {Promise}\n */\n const processError = async (\n error: ResponseError,\n requestConfig: RequestConfig,\n ): Promise => {\n if (!isRequestCancelled(error)) {\n logger(requestConfig, 'API ERROR', error);\n }\n\n // Local interceptors\n await applyInterceptor(error, requestConfig?.onError);\n\n // Global interceptors\n await applyInterceptor(error, handlerConfig?.onError);\n };\n\n /**\n * Output default response in case of an error, depending on chosen strategy\n *\n * @param {ResponseError} error - Error instance\n * @param {FetchResponse | null} response - Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Per endpoint request config\n * @returns {FetchResponse} Response together with the error object\n */\n const outputErrorResponse = async (\n error: ResponseError,\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n ): Promise => {\n const _isRequestCancelled = isRequestCancelled(error);\n const errorHandlingStrategy = getConfig(requestConfig, 'strategy');\n const rejectCancelled = getConfig(\n requestConfig,\n 'rejectCancelled',\n );\n\n // By default cancelled requests aren't rejected (softFail strategy)\n if (!(_isRequestCancelled && !rejectCancelled)) {\n // Hang the promise\n if (errorHandlingStrategy === 'silent') {\n await new Promise(() => null);\n }\n // Reject the promise\n else if (errorHandlingStrategy === 'reject') {\n return Promise.reject(error);\n }\n }\n\n return outputResponse(response, requestConfig, error);\n };\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {ResponseError} error Error instance\n * @returns {boolean} True if request is aborted\n */\n const isRequestCancelled = (error: ResponseError): boolean => {\n return error.name === ABORT_ERROR || error.name === CANCELLED_ERROR;\n };\n\n /**\n * Handle Request depending on used strategy\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config\n * @throws {ResponseError}\n * @returns {Promise>} Response Data\n */\n const request = async <\n ResponseData = DefaultResponse,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n RequestBody = DefaultPayload,\n >(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n ): Promise> => {\n const _reqConfig = reqConfig || {};\n const mergedConfig = {\n ...handlerConfig,\n ..._reqConfig,\n } as RequestConfig;\n\n mergeConfig('retry', mergedConfig, handlerConfig, _reqConfig);\n mergeConfig('headers', mergedConfig, handlerConfig, _reqConfig);\n\n let response: FetchResponse | null = null;\n const fetcherConfig = buildConfig(url, mergedConfig);\n\n const {\n timeout,\n cancellable,\n dedupeTime,\n pollingInterval,\n shouldStopPolling,\n cacheTime,\n cacheKey,\n } = mergedConfig;\n\n // Prevent performance overhead of cache access\n let _cacheKey: string;\n\n if (cacheKey) {\n _cacheKey = cacheKey(fetcherConfig);\n } else {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n if (cacheTime && _cacheKey) {\n const cacheBuster = mergedConfig.cacheBuster;\n\n if (!cacheBuster || !cacheBuster(fetcherConfig)) {\n const cachedEntry = getCache>(\n _cacheKey,\n cacheTime,\n );\n\n if (cachedEntry) {\n // Serve stale data from cache\n return cachedEntry.data;\n }\n }\n }\n\n const {\n retries = 0,\n delay,\n backoff,\n retryOn,\n shouldRetry,\n maxDelay,\n resetTimeout,\n } = mergedConfig.retry as Required;\n\n let attempt = 0;\n let pollingAttempt = 0;\n let waitTime: number = delay;\n const _retries = retries > 0 ? retries : 0;\n\n while (attempt <= _retries) {\n try {\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = await addRequest(\n fetcherConfig,\n timeout,\n dedupeTime,\n cancellable,\n // Reset timeouts by default or when retries are ON\n !!(timeout && (!_retries || resetTimeout)),\n );\n\n // Shallow copy to ensure basic idempotency\n const requestConfig: RequestConfig = {\n signal: controller.signal,\n ...fetcherConfig,\n };\n\n // Local interceptors\n await applyInterceptor(requestConfig, _reqConfig?.onRequest);\n\n // Global interceptors\n await applyInterceptor(requestConfig, handlerConfig?.onRequest);\n\n if (customFetcher !== null && requestInstance !== null) {\n response = await requestInstance.request(requestConfig);\n } else {\n response = (await fetch(\n requestConfig.url as string,\n requestConfig as RequestInit,\n )) as FetchResponse;\n }\n\n // Add more information to response object\n if (response instanceof Response) {\n response.config = requestConfig;\n response.data = await parseResponseData(response);\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n if (!response.ok) {\n throw new ResponseErr(\n `${requestConfig.url} failed! Status: ${response.status || null}`,\n requestConfig,\n response,\n );\n }\n }\n\n // Local interceptors\n await applyInterceptor(response, _reqConfig?.onResponse);\n\n // Global interceptors\n await applyInterceptor(response, handlerConfig?.onResponse);\n\n removeRequest(fetcherConfig);\n\n // Polling logic\n if (\n pollingInterval &&\n (!shouldStopPolling || !shouldStopPolling(response, pollingAttempt))\n ) {\n // Restart the main retry loop\n pollingAttempt++;\n\n logger(requestConfig, 'Polling attempt ' + pollingAttempt + '...');\n\n await delayInvocation(pollingInterval);\n\n continue;\n }\n\n // If polling is not required, or polling attempts are exhausted\n const output = outputResponse(response, requestConfig);\n\n if (cacheTime && _cacheKey) {\n const skipCache = requestConfig.skipCache;\n\n if (!skipCache || !skipCache(output, requestConfig)) {\n setCache(_cacheKey, output);\n }\n }\n\n return output;\n } catch (err) {\n const error = err as ResponseErr;\n const status = error?.response?.status || error?.status || 0;\n\n if (\n attempt === retries ||\n !(!shouldRetry || (await shouldRetry(error, attempt))) ||\n !retryOn?.includes(status)\n ) {\n await processError(error, fetcherConfig);\n\n removeRequest(fetcherConfig);\n\n return outputErrorResponse(\n error,\n response,\n fetcherConfig,\n );\n }\n\n logger(\n mergedConfig,\n `Attempt ${attempt + 1} failed. Retry in ${waitTime}ms.`,\n );\n\n await delayInvocation(waitTime);\n\n waitTime *= backoff;\n waitTime = Math.min(waitTime, maxDelay);\n attempt++;\n }\n }\n\n return outputResponse(response, fetcherConfig);\n };\n\n /**\n * Output response\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\n const outputResponse = (\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n error: ResponseError | null = null,\n ): FetchResponse => {\n const defaultResponse = getConfig(requestConfig, 'defaultResponse');\n\n // This may happen when request is cancelled.\n if (!response) {\n return {\n ok: false,\n // Enhance the response with extra information\n error,\n data: defaultResponse,\n headers: null,\n config: requestConfig,\n } as unknown as FetchResponse;\n }\n\n // Clean up the error object\n deleteProperty(error, 'response');\n deleteProperty(error, 'request');\n deleteProperty(error, 'config');\n\n let data = response?.data;\n\n // Set the default response if the provided data is an empty object\n if (\n data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0)\n ) {\n data = defaultResponse;\n }\n\n // Return flattened response immediately\n const flattenResponse = getConfig(\n requestConfig,\n 'flattenResponse',\n );\n\n if (flattenResponse) {\n response.data = flattenData(data);\n }\n\n // If it's a custom fetcher, and it does not return any Response instance, it may have its own internal handler\n if (!(response instanceof Response)) {\n return response;\n }\n\n // Native fetch Response extended by extra information\n return {\n body: response.body,\n bodyUsed: response.bodyUsed,\n formData: response.formData,\n ok: response.ok,\n redirected: response.redirected,\n type: response.type,\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n\n blob: response.blob.bind(response),\n json: response.json.bind(response),\n text: response.text.bind(response),\n clone: response.clone.bind(response),\n arrayBuffer: response.arrayBuffer.bind(response),\n\n // Enhance the response with extra information\n error,\n data,\n headers: processHeaders(response.headers),\n config: requestConfig,\n };\n };\n\n return {\n getInstance,\n buildConfig,\n config,\n request,\n };\n}\n","import type {\n RequestConfig,\n FetchResponse,\n DefaultResponse,\n CreatedCustomFetcherInstance,\n} from './types/request-handler';\nimport type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n DefaultPayload,\n FallbackValue,\n FinalParams,\n FinalResponse,\n QueryParams,\n RequestConfigUrlRequired,\n UrlPathParams,\n} from './types/api-handler';\nimport { createRequestHandler } from './request-handler';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if it is passed as \"fetcher\".\n * @url https://github.com/MattCCC/fetchff\n *\n * @param {Object} config - Configuration object for the API fetcher.\n * @param {string} config.apiUrl - The base URL for the API.\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {number} config.timeout - You can set the timeout for particular request in milliseconds.\n * @param {number} config.cancellable - If true, the ongoing previous requests will be automatically cancelled.\n * @param {number} config.rejectCancelled - If true and request is set to cancellable, a cancelled request promise will be rejected. By default, instead of rejecting the promise, defaultResponse is returned.\n * @param {number} config.timeout - Request timeout\n * @param {number} config.dedupeTime - Time window, in milliseconds, during which identical requests are deduplicated (treated as single request).\n * @param {string} config.strategy - Error Handling Strategy\n * @param {string} config.flattenResponse - Whether to flatten response \"data\" object within \"data\". It works only if the response structure includes a single data property.\n * @param {*} config.defaultResponse - Default response when there is no data or when endpoint fails depending on the chosen strategy. It's \"null\" by default\n * @param {Object} [config.retry] - Options for retrying requests.\n * @param {number} [config.retry.retries=0] - Number of retry attempts. No retries by default.\n * @param {number} [config.retry.delay=1000] - Initial delay between retries in milliseconds.\n * @param {number} [config.retry.backoff=1.5] - Exponential backoff factor.\n * @param {number[]} [config.retry.retryOn=[502, 504, 408]] - HTTP status codes to retry on.\n * @param {RequestInterceptor|RequestInterceptor[]} [config.onRequest] - Optional request interceptor function or an array of functions.\n * These functions will be called with the request configuration object before the request is made. Can be used to modify or log the request configuration.\n * @param {ResponseInterceptor|ResponseInterceptor[]} [config.onResponse] - Optional response interceptor function or an array of functions.\n * These functions will be called with the response object after the response is received. an be used to modify or log the response data.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Object} config.fetcher - The Custom Fetcher instance to use for making requests. It should expose create() and request() functions.\n * @param {*} config.logger - Instance of custom logger. Either class or an object similar to \"console\". Console is used by default.\n * @returns API handler functions and endpoints to call\n *\n * @example\n * // Define endpoint paths\n * const endpoints = {\n * getUser: '/user',\n * createPost: '/post',\n * };\n *\n * // Create the API fetcher with configuration\n * const api = createApiFetcher({\n * endpoints,\n * apiUrl: 'https://example.com/api',\n * onError(error) {\n * console.log('Request failed', error);\n * },\n * headers: {\n * 'my-auth-key': 'example-auth-key-32rjjfa',\n * },\n * });\n *\n * // Fetch user data\n * const response = await api.getUser({ userId: 1, ratings: [1, 2] })\n */\nfunction createApiFetcher<\n EndpointsMethods extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n const requestHandler = createRequestHandler(config);\n\n /**\n * Get Custom Fetcher Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Request Handler's Custom Fetcher Instance\n */\n function getInstance(): CreatedCustomFetcherInstance | null {\n return requestHandler.getInstance();\n }\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n function handleNonImplemented(endpointName: string): Promise {\n console.error(`Add ${endpointName} to 'endpoints'.`);\n\n return Promise.resolve(null);\n }\n\n /**\n * Handle Single API Request\n * It considers settings in following order: per-request settings, global per-endpoint settings, global settings.\n *\n * @param {keyof EndpointsMethods | string} endpointName - The name of the API endpoint to call.\n * @param {EndpointConfig} [requestConfig={}] - Additional configuration for the request.\n * @returns {Promise>} - A promise that resolves with the response from the API provider.\n */\n async function request<\n ResponseData = never,\n QueryParams_ = never,\n UrlParams = never,\n RequestBody = never,\n >(\n endpointName: keyof EndpointsMethods | string,\n requestConfig: RequestConfig<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n > = {},\n ): Promise>> {\n // Use global per-endpoint settings\n const endpointConfig =\n endpoints[endpointName] ||\n ({ url: endpointName as string } as RequestConfigUrlRequired);\n\n const responseData = await requestHandler.request<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n >(endpointConfig.url, {\n ...endpointConfig,\n ...requestConfig,\n });\n\n return responseData;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\n requestHandler,\n getInstance,\n request,\n };\n\n /**\n * Maps all API requests using native Proxy\n *\n * @param {*} prop Caller\n */\n return new Proxy>(\n apiHandler as ApiHandlerMethods,\n {\n get(_target, prop: string) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"],"mappings":"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","names":["src_exports","__export","createApiFetcher","fetchf","applyInterceptor","object","interceptors","value","interceptor","ResponseErr","message","requestInfo","response","__publicField","APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","ABORT_ERROR","TIMEOUT_ERROR","CANCELLED_ERROR","GET","HEAD","isSearchParams","data","shallowSerialize","obj","result","key","sortObject","sortedObj","keys","i","len","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","isSearchParams","encodedQueryString","s","encode","add","k","v","buildParams","prefix","OBJECT","replaceUrlPathParams","urlPathParams","str","word","isJSONSerializable","value","UNDEFINED","STRING","proto","delayInvocation","ms","resolve","flattenData","data","processHeaders","headers","headersObject","deleteProperty","property","queue","addRequest","config","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","previousController","timeoutId","ABORT_ERROR","controller","error","TIMEOUT_ERROR","removeRequest","parseResponseData","response","_a","contentType","CONTENT_TYPE","data","APPLICATION_JSON","APPLICATION_CONTENT_TYPE","_e","_error","hash","str","i","len","char","cache","generateCacheKey","options","url","method","GET","headers","body","mode","credentials","redirect","referrer","integrity","headersString","shallowSerialize","sortObject","bodyString","hash","value","key","UNDEFINED","o","OBJECT","isCacheExpired","timestamp","maxStaleTime","getCache","cacheTime","entry","setCache","data","isLoading","defaultConfig","GET","APPLICATION_JSON","CONTENT_TYPE","createRequestHandler","config","handlerConfig","mergeConfig","property","targetConfig","baseConfig","newConfig","getConfig","reqConfig","name","UNDEFINED","customFetcher","requestInstance","getInstance","logger","args","buildConfig","url","requestConfig","method","isGetAlikeMethod","HEAD","dynamicUrl","replaceUrlPathParams","explicitParams","explicitBodyData","body","credentials","urlPath","appendQueryParams","baseURL","STRING","isSearchParams","isJSONSerializable","processError","error","isRequestCancelled","applyInterceptor","outputErrorResponse","response","_isRequestCancelled","errorHandlingStrategy","rejectCancelled","outputResponse","ABORT_ERROR","CANCELLED_ERROR","request","_a","_reqConfig","mergedConfig","fetcherConfig","timeout","cancellable","dedupeTime","pollingInterval","shouldStopPolling","cacheTime","cacheKey","_cacheKey","generateCacheKey","cacheBuster","cachedEntry","getCache","retries","delay","backoff","retryOn","shouldRetry","maxDelay","resetTimeout","attempt","pollingAttempt","waitTime","_retries","addRequest","parseResponseData","ResponseErr","removeRequest","delayInvocation","output","skipCache","setCache","err","status","defaultResponse","deleteProperty","data","OBJECT","flattenData","processHeaders","createApiFetcher","config","endpoints","requestHandler","createRequestHandler","getInstance","handleNonImplemented","endpointName","request","requestConfig","endpointConfig","apiHandler","_target","prop","fetchf","url","config","createRequestHandler"]} \ No newline at end of file diff --git a/dist/browser/index.mjs b/dist/browser/index.mjs index ad1b42d..6fd4779 100644 --- a/dist/browser/index.mjs +++ b/dist/browser/index.mjs @@ -1,2 +1,2 @@ -var be=Object.defineProperty;var we=(e,t,n)=>t in e?be(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var w=(e,t,n)=>we(e,typeof t!="symbol"?t+"":t,n);async function T(e,t){if(t){if(typeof t=="function"){let n=await t(e);n&&Object.assign(e,n)}else if(Array.isArray(t))for(let n of t){let o=await n(e);o&&Object.assign(e,o)}}}var M=class extends Error{constructor(n,o,r){super(n);w(this,"response");w(this,"request");w(this,"config");w(this,"status");w(this,"statusText");this.name="ResponseError",this.message=n,this.status=r.status,this.statusText=r.statusText,this.request=o,this.config=o,this.response=r}};var _="application/",A=_+"json",Q="Content-Type",C="undefined",E="object",L="string",v="AbortError",oe="TimeoutError",ie="CanceledError",N="GET",le="HEAD";function V(e){return e instanceof URLSearchParams}function ce(e){let t="";for(let n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t+=n+":"+e[n]);return t}function W(e){let t={},n=Object.keys(e);n.sort();for(let o=0,r=n.length;o{a=typeof a=="function"?a():a,a=a===null||a===void 0?"":a,n[n.length]=o(f)+"="+o(a)},u=(f,a)=>{let p,g,R;if(f)if(Array.isArray(a))for(p=0,g=a.length;p{let o=n.substring(1);return t[o]?String(t[o]):n}):e}function de(e){let t=typeof e;if(t===C||e===null)return!1;if(t===L||t==="number"||t==="boolean"||Array.isArray(e))return!0;if(Buffer.isBuffer(e)||e instanceof Date)return!1;if(t===E){let n=Object.getPrototypeOf(e);if(n===Object.prototype||n===null||typeof e.toJSON=="function")return!0}return!1}async function X(e){return new Promise(t=>setTimeout(()=>t(!0),e))}function Z(e){return e&&typeof e===E&&typeof e.data!==C&&Object.keys(e).length===1?Z(e.data):e}function Re(e){if(!e)return{};let t={};if(e instanceof Headers)e.forEach((n,o)=>{t[o]=n});else if(typeof e===E&&e!==null)for(let[n,o]of Object.entries(e))t[n.toLowerCase()]=o;return t}function j(e,t){e&&t in e&&delete e[t]}var H=new Map;async function me(e,t,n=0,o=!1,r=!0){let u=Date.now(),m=H.get(e);if(m){let a=m[3],p=m[0],g=m[1];if(!a&&u-m[2]{let a=new DOMException(`${e.url} aborted due to timeout`,oe);J(e,a)},t):null;return H.set(e,[y,f,u,o]),y}async function J(e,t=null){let n=H.get(e);if(n){let o=n[0],r=n[1];t&&!o.signal.aborted&&o.abort(t),r!==null&&clearTimeout(r),H.delete(e)}}async function ye(e){var o;if(!(e!=null&&e.body))return null;let t=String(((o=e.headers)==null?void 0:o.get(Q))||"").split(";")[0],n;try{if(t.includes(A)||t.includes("+json"))n=await e.json();else if(t.includes("multipart/form-data"))n=await e.formData();else if(t.includes(_+"octet-stream"))n=await e.blob();else if(t.includes(_+"x-www-form-urlencoded"))n=await e.formData();else if(t.includes("text/"))n=await e.text();else try{n=await e.clone().json()}catch(r){n=await e.text()}}catch(r){n=null}return n}function $(e){let t=0;for(let n=0,o=e.length;n{R+=i+"="+s+"&"}),R=$(R);else if(typeof Blob!==C&&r instanceof Blob||typeof File!==C&&r instanceof File)R="BF"+r.size+r.type;else if(r instanceof ArrayBuffer||ArrayBuffer.isView(r))R="AB"+r.byteLength;else{let s=typeof r===E?W(r):String(r);R=$(JSON.stringify(s))}return n+t+u+m+y+f+a+p+g+R}function xe(e,t){return t?Date.now()-e>t*1e3:!1}function ge(e,t){let n=ee.get(e);if(n){if(!xe(n.timestamp,t))return n;ee.delete(e)}return null}function Pe(e,t,n=!1){ee.set(e,{data:t,isLoading:n,timestamp:Date.now()})}var Oe={method:N,strategy:"reject",timeout:3e4,dedupeTime:1e3,defaultResponse:null,headers:{Accept:A+", text/plain, */*","Accept-Encoding":"gzip, deflate, br",[Q]:A+";charset=utf-8"},retry:{delay:1e3,maxDelay:3e4,resetTimeout:!0,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function G(e){let t={...Oe,...e},n=t.fetcher,o=(n==null?void 0:n.create(t))||null,r=()=>o,u=(s,i)=>typeof s[i]!==C?s[i]:t[i],m=(...s)=>{var i;(i=t.logger)!=null&&i.warn&&t.logger.warn(...s)},y=(s,i)=>{let d=u(i,"method").toUpperCase(),P=d===N||d===le,l=pe(s,u(i,"urlPathParams")),h=u(i,"params"),U=u(i,"body")||u(i,"data"),D;P||(D=U);let S=u(i,"withCredentials")?"include":u(i,"credentials"),x=h?fe(l,h):l,k=x.includes("://")?"":u(i,"baseURL")||u(i,"apiUrl");return D&&typeof D!==L&&!V(D)&&de(D)&&(D=JSON.stringify(D)),{...i,credentials:S,body:D,method:d,url:k+x}},f=async(s,i)=>{p(s)||m("API ERROR",s),await T(s,i==null?void 0:i.onError),await T(s,t==null?void 0:t.onError)},a=async(s,i,d)=>{let P=p(s),l=u(d,"strategy"),h=u(d,"rejectCancelled");if(!(P&&!h)){if(l==="silent")await new Promise(()=>null);else if(l==="reject")return Promise.reject(s)}return R(i,d,s)},p=s=>s.name===v||s.name===ie,g=async(s,i=null)=>{var re;let d=i||{},P={...t,...d},l=null,h=y(s,P),{timeout:U,cancellable:D,dedupeTime:te,pollingInterval:S,shouldStopPolling:x,cacheTime:B,cacheKey:k}=P,b;if(k?b=k(h):b=he(h),B&&b){let I=P.cacheBuster;if(!I||!I(h)){let c=ge(b,B);if(c)return c.data}}let{retries:z=0,delay:De,backoff:Ee,retryOn:Y,shouldRetry:ne,maxDelay:Ce,resetTimeout:Te}=P.retry,O=0,K=0,F=De,se=z>0?z:0;for(;O<=se;)try{let c={signal:(await me(h,U,te,D,!!(U&&(!se||Te)))).signal,...h};if(await T(c,d==null?void 0:d.onRequest),await T(c,t==null?void 0:t.onRequest),n!==null&&o!==null?l=await o.request(c):l=await fetch(c.url,c),l instanceof Response&&(l.config=c,l.data=await ye(l),!l.ok))throw new M(`${c.url} failed! Status: ${l.status||null}`,c,l);if(await T(l,d==null?void 0:d.onResponse),await T(l,t==null?void 0:t.onResponse),J(h),S&&(!x||!x(l,K))){K++,m(`Polling attempt ${K}...`),await X(S);continue}let q=R(l,c);if(B&&b){let ae=c.skipCache;(!ae||!ae(q,c))&&Pe(b,q)}return q}catch(I){let c=I,q=((re=c==null?void 0:c.response)==null?void 0:re.status)||(c==null?void 0:c.status)||0;if(O===z||!(!ne||await ne(c,O))||!(Y!=null&&Y.includes(q)))return await f(c,h),J(h),a(c,l,h);m(`Attempt ${O+1} failed. Retry in ${F}ms.`),await X(F),F*=Ee,F=Math.min(F,Ce),O++}return R(l,h)},R=(s,i,d=null)=>{let P=u(i,"defaultResponse");if(!s)return{ok:!1,error:d,data:P,headers:null,config:i};j(d,"response"),j(d,"request"),j(d,"config");let l=s==null?void 0:s.data;return(l==null||typeof l===E&&Object.keys(l).length===0)&&(l=P),u(i,"flattenResponse")&&(s.data=Z(l)),s instanceof Response?{body:s.body,bodyUsed:s.bodyUsed,formData:s.formData,ok:s.ok,redirected:s.redirected,type:s.type,url:s.url,status:s.status,statusText:s.statusText,blob:s.blob.bind(s),json:s.json.bind(s),text:s.text.bind(s),clone:s.clone.bind(s),arrayBuffer:s.arrayBuffer.bind(s),error:d,data:l,headers:Re(s.headers),config:i}:s};return{getInstance:r,buildConfig:y,config:e,request:g}}function Ze(e){let t=e.endpoints,n=G(e);function o(){return n.getInstance()}function r(y){return console.error(`Add ${y} to 'endpoints'.`),Promise.resolve(null)}async function u(y,f={}){let a=t[y]||{url:y};return await n.request(a.url,{...a,...f})}let m={config:e,endpoints:t,requestHandler:n,getInstance:o,request:u};return new Proxy(m,{get(y,f){return f in m?m[f]:t[f]?m.request.bind(null,f):r.bind(null,f)}})}async function nt(e,t={}){return G(t).request(e,t)}export{Ze as createApiFetcher,nt as fetchf}; +var xe=Object.defineProperty;var Oe=(e,t,n)=>t in e?xe(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var x=(e,t,n)=>Oe(e,typeof t!="symbol"?t+"":t,n);async function b(e,t){if(t){if(typeof t=="function"){let n=await t(e);n&&Object.assign(e,n)}else if(Array.isArray(t))for(let n of t){let r=await n(e);r&&Object.assign(e,r)}}}var _=class extends Error{constructor(n,r,a){super(n);x(this,"response");x(this,"request");x(this,"config");x(this,"status");x(this,"statusText");this.name="ResponseError",this.message=n,this.status=a.status,this.statusText=a.statusText,this.request=r,this.config=r,this.response=a}};var Q="application/",H=Q+"json",L="Content-Type",C="undefined",E="object",v="string",j="AbortError",le="TimeoutError",ue="CanceledError",N="GET",ce="HEAD";function W(e){return e instanceof URLSearchParams}function pe(e){let t="";for(let n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t+=n+":"+e[n]);return t}function X(e){let t={},n=Object.keys(e);n.sort();for(let r=0,a=n.length;r{o=typeof o=="function"?o():o,o=o===null||o===void 0?"":o,n[n.length]=r(f)+"="+r(o)},d=(f,o)=>{let p,P,m;if(f)if(Array.isArray(o))for(p=0,P=o.length;p{let r=n.substring(1);return t[r]?String(t[r]):n}):e}function me(e){let t=typeof e;if(t===C||e===null)return!1;if(t===v||t==="number"||t==="boolean"||Array.isArray(e))return!0;if(Buffer.isBuffer(e)||e instanceof Date)return!1;if(t===E){let n=Object.getPrototypeOf(e);if(n===Object.prototype||n===null||typeof e.toJSON=="function")return!0}return!1}async function Z(e){return new Promise(t=>setTimeout(()=>t(!0),e))}function ee(e){return e&&typeof e===E&&typeof e.data!==C&&Object.keys(e).length===1?ee(e.data):e}function ye(e){if(!e)return{};let t={};if(e instanceof Headers)e.forEach((n,r)=>{t[r]=n});else if(typeof e===E&&e!==null)for(let[n,r]of Object.entries(e))t[n.toLowerCase()]=r;return t}function J(e,t){e&&t in e&&delete e[t]}var U=new Map;async function he(e,t,n=0,r=!1,a=!0){let d=Date.now(),g=U.get(e);if(g){let o=g[3],p=g[0],P=g[1];if(!o&&d-g[2]{let o=new DOMException(`${e.url} aborted due to timeout`,le);$(e,o)},t):null;return U.set(e,[R,f,d,r]),R}async function $(e,t=null){let n=U.get(e);if(n){let r=n[0],a=n[1];t&&!r.signal.aborted&&r.abort(t),a!==null&&clearTimeout(a),U.delete(e)}}async function ge(e){var r;if(!(e!=null&&e.body))return null;let t=String(((r=e.headers)==null?void 0:r.get(L))||"").split(";")[0],n;try{if(t.includes(H)||t.includes("+json"))n=await e.json();else if(t.includes("multipart/form-data"))n=await e.formData();else if(t.includes(Q+"octet-stream"))n=await e.blob();else if(t.includes(Q+"x-www-form-urlencoded"))n=await e.formData();else if(t.includes("text/"))n=await e.text();else try{n=await e.clone().json()}catch(a){n=await e.text()}}catch(a){n=null}return n}function G(e){let t=0;for(let n=0,r=e.length;n{m+=s+"="+T+"&"}),m=G(m);else if(typeof Blob!==C&&a instanceof Blob||typeof File!==C&&a instanceof File)m="BF"+a.size+a.type;else if(a instanceof ArrayBuffer||ArrayBuffer.isView(a))m="AB"+a.byteLength;else{let T=typeof a===E?X(a):String(a);m=G(JSON.stringify(T))}return n+t+d+g+R+f+o+p+P+m}function qe(e,t){return t?Date.now()-e>t*1e3:!1}function De(e,t){let n=te.get(e);if(n){if(!qe(n.timestamp,t))return n;te.delete(e)}return null}function Ee(e,t,n=!1){te.set(e,{data:t,isLoading:n,timestamp:Date.now()})}var ne={method:N,strategy:"reject",timeout:3e4,dedupeTime:1e3,defaultResponse:null,headers:{Accept:H+", text/plain, */*","Accept-Encoding":"gzip, deflate, br",[L]:H+";charset=utf-8"},retry:{delay:1e3,maxDelay:3e4,resetTimeout:!0,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function z(e){let t={...ne,...e},n=(s,i,l,y)=>{y[s]&&(i[s]={...l[s],...y[s]})};n("retry",t,ne,e),n("headers",t,ne,e);let r=(s,i)=>typeof s[i]!==C?s[i]:t[i],a=r(e,"fetcher"),d=(a==null?void 0:a.create(t))||null,g=()=>d,R=(s,...i)=>{let l=r(s,"logger");l!=null&&l.warn&&l.warn(...i)},f=(s,i)=>{let l=r(i,"method").toUpperCase(),y=l===N||l===ce,u=Re(s,r(i,"urlPathParams")),h=r(i,"params"),S=r(i,"body")||r(i,"data"),D;y||(D=S);let k=r(i,"withCredentials")?"include":r(i,"credentials"),O=h?de(u,h):u,M=O.includes("://")?"":r(i,"baseURL")||r(i,"apiUrl");return D&&typeof D!==v&&!W(D)&&me(D)&&(D=JSON.stringify(D)),{...i,credentials:k,body:D,method:l,url:M+O}},o=async(s,i)=>{P(s)||R(i,"API ERROR",s),await b(s,i==null?void 0:i.onError),await b(s,t==null?void 0:t.onError)},p=async(s,i,l)=>{let y=P(s),u=r(l,"strategy"),h=r(l,"rejectCancelled");if(!(y&&!h)){if(u==="silent")await new Promise(()=>null);else if(u==="reject")return Promise.reject(s)}return T(i,l,s)},P=s=>s.name===j||s.name===ue,m=async(s,i=null)=>{var oe;let l=i||{},y={...t,...l};n("retry",y,t,l),n("headers",y,t,l);let u=null,h=f(s,y),{timeout:S,cancellable:D,dedupeTime:se,pollingInterval:k,shouldStopPolling:O,cacheTime:B,cacheKey:M}=y,w;if(M?w=M(h):w=Pe(h),B&&w){let I=y.cacheBuster;if(!I||!I(h)){let c=De(w,B);if(c)return c.data}}let{retries:K=0,delay:Ce,backoff:Te,retryOn:Y,shouldRetry:re,maxDelay:be,resetTimeout:we}=y.retry,q=0,V=0,F=Ce,ae=K>0?K:0;for(;q<=ae;)try{let c={signal:(await he(h,S,se,D,!!(S&&(!ae||we)))).signal,...h};if(await b(c,l==null?void 0:l.onRequest),await b(c,t==null?void 0:t.onRequest),a!==null&&d!==null?u=await d.request(c):u=await fetch(c.url,c),u instanceof Response&&(u.config=c,u.data=await ge(u),!u.ok))throw new _(`${c.url} failed! Status: ${u.status||null}`,c,u);if(await b(u,l==null?void 0:l.onResponse),await b(u,t==null?void 0:t.onResponse),$(h),k&&(!O||!O(u,V))){V++,R(c,"Polling attempt "+V+"..."),await Z(k);continue}let A=T(u,c);if(B&&w){let ie=c.skipCache;(!ie||!ie(A,c))&&Ee(w,A)}return A}catch(I){let c=I,A=((oe=c==null?void 0:c.response)==null?void 0:oe.status)||(c==null?void 0:c.status)||0;if(q===K||!(!re||await re(c,q))||!(Y!=null&&Y.includes(A)))return await o(c,h),$(h),p(c,u,h);R(y,`Attempt ${q+1} failed. Retry in ${F}ms.`),await Z(F),F*=Te,F=Math.min(F,be),q++}return T(u,h)},T=(s,i,l=null)=>{let y=r(i,"defaultResponse");if(!s)return{ok:!1,error:l,data:y,headers:null,config:i};J(l,"response"),J(l,"request"),J(l,"config");let u=s==null?void 0:s.data;return(u==null||typeof u===E&&Object.keys(u).length===0)&&(u=y),r(i,"flattenResponse")&&(s.data=ee(u)),s instanceof Response?{body:s.body,bodyUsed:s.bodyUsed,formData:s.formData,ok:s.ok,redirected:s.redirected,type:s.type,url:s.url,status:s.status,statusText:s.statusText,blob:s.blob.bind(s),json:s.json.bind(s),text:s.text.bind(s),clone:s.clone.bind(s),arrayBuffer:s.arrayBuffer.bind(s),error:l,data:u,headers:ye(s.headers),config:i}:s};return{getInstance:g,buildConfig:f,config:e,request:m}}function et(e){let t=e.endpoints,n=z(e);function r(){return n.getInstance()}function a(R){return console.error(`Add ${R} to 'endpoints'.`),Promise.resolve(null)}async function d(R,f={}){let o=t[R]||{url:R};return await n.request(o.url,{...o,...f})}let g={config:e,endpoints:t,requestHandler:n,getInstance:r,request:d};return new Proxy(g,{get(R,f){return f in g?g[f]:t[f]?g.request.bind(null,f):a.bind(null,f)}})}async function st(e,t={}){return z(t).request(e,t)}export{et as createApiFetcher,st as fetchf}; //# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/dist/browser/index.mjs.map b/dist/browser/index.mjs.map index a84a0a0..de31749 100644 --- a/dist/browser/index.mjs.map +++ b/dist/browser/index.mjs.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/interceptor-manager.ts","../../src/response-error.ts","../../src/constants.ts","../../src/utils.ts","../../src/queue-manager.ts","../../src/response-parser.ts","../../src/hash.ts","../../src/cache-manager.ts","../../src/request-handler.ts","../../src/api-handler.ts","../../src/index.ts"],"sourcesContent":["type InterceptorFunction = (object: T) => Promise;\n\n/**\n * Applies interceptors to the object. Interceptors can be a single function or an array of functions.\n *\n * @template T - Type of the object.\n * @template I - Type of interceptors.\n *\n * @param {T} object - The object to process.\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptor<\n T extends object,\n I = InterceptorFunction | InterceptorFunction[],\n>(object: T, interceptors?: I): Promise {\n if (!interceptors) {\n return;\n }\n\n if (typeof interceptors === 'function') {\n const value = await interceptors(object);\n\n if (value) {\n Object.assign(object, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(object);\n\n if (value) {\n Object.assign(object, value);\n }\n }\n }\n}\n","import type { FetchResponse, RequestConfig } from './types';\n\nexport class ResponseErr extends Error {\n response: FetchResponse;\n request: RequestConfig;\n config: RequestConfig;\n status: number;\n statusText: string;\n\n constructor(\n message: string,\n requestInfo: RequestConfig,\n response: FetchResponse,\n ) {\n super(message);\n\n this.name = 'ResponseError';\n this.message = message;\n this.status = response.status;\n this.statusText = response.statusText;\n this.request = requestInfo;\n this.config = requestInfo;\n this.response = response;\n }\n}\n","export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\nexport const CANCELLED_ERROR = 'CanceledError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\nexport function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const sortedObj = {} as Record;\n const keys = Object.keys(obj);\n\n keys.sort();\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === 'function' ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any) => {\n let i: number, len: number, key: string;\n\n if (prefix) {\n if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n buildParams(\n prefix + '[' + (typeof obj[i] === OBJECT && obj[i] ? i : '') + ']',\n obj[i],\n );\n }\n } else if (typeof obj === OBJECT && obj !== null) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key]);\n }\n } else {\n add(prefix, obj);\n }\n } else if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n add(obj[i].name, obj[i].value);\n }\n } else {\n for (key in obj) {\n buildParams(key, obj[key]);\n }\n }\n return s;\n };\n\n const queryStringParts = buildParams('', params).join('&');\n\n // Encode special characters as per RFC 3986, https://datatracker.ietf.org/doc/html/rfc3986\n const encodedQueryString = queryStringParts.replace(/%5B%5D/g, '[]'); // Keep '[]' for arrays\n\n return appendQueryStringToUrl(url, encodedQueryString);\n}\n\n/**\n * Replaces dynamic URI parameters in a URL string with values from the provided `urlPathParams` object.\n * Parameters in the URL are denoted by `:`, where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:`.\n * @param {Object} urlPathParams - An object containing the parameter values to replace placeholders.\n * @param {string} urlPathParams.paramName - The value to replace the placeholder `:` in the URL.\n * @returns {string} - The URL string with placeholders replaced by corresponding values from `urlPathParams`.\n */\nexport function replaceUrlPathParams(\n url: string,\n urlPathParams: UrlPathParams,\n): string {\n if (!urlPathParams) {\n return url;\n }\n\n return url.replace(/:\\w+/g, (str): string => {\n const word = str.substring(1);\n\n if ((urlPathParams as DefaultUrlParams)[word]) {\n return String((urlPathParams as DefaultUrlParams)[word]);\n }\n\n return str;\n });\n}\n\n/**\n * Checks if a value is JSON serializable.\n *\n * JSON serializable values include:\n * - Primitive types: string, number, boolean, null\n * - Arrays\n * - Plain objects (i.e., objects without special methods)\n * - Values with a `toJSON` method\n *\n * @param {any} value - The value to check for JSON serializability.\n * @returns {boolean} - Returns `true` if the value is JSON serializable, otherwise `false`.\n */\nexport function isJSONSerializable(value: any): boolean {\n const t = typeof value;\n\n if (t === UNDEFINED || value === null) {\n return false;\n }\n\n if (t === STRING || t === 'number' || t === 'boolean') {\n return true;\n }\n\n if (Array.isArray(value)) {\n return true;\n }\n\n if (Buffer.isBuffer(value)) {\n return false;\n }\n\n if (value instanceof Date) {\n return false;\n }\n\n if (t === OBJECT) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` or `null` (plain object)\n if (proto === Object.prototype || proto === null) {\n return true;\n }\n\n // Check if the object has a toJSON method\n if (typeof value.toJSON === 'function') {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any): any {\n if (\n data &&\n typeof data === OBJECT &&\n typeof data.data !== UNDEFINED &&\n Object.keys(data).length === 1\n ) {\n return flattenData(data.data);\n }\n\n return data;\n}\n\n/**\n * Processes headers and returns them as a normalized object.\n *\n * Handles both `Headers` instances and plain objects. Normalizes header keys to lowercase\n * as per RFC 2616 section 4.2.\n *\n * @param headers - The headers to process. Can be an instance of `Headers`, a plain object,\n * or `null`. If `null`, an empty object is returned.\n * @returns {HeadersObject} - A normalized headers object with lowercase keys.\n */\nexport function processHeaders(\n headers?: (HeadersObject & HeadersInit) | null | Headers,\n): HeadersObject {\n if (!headers) {\n return {};\n }\n\n const headersObject: HeadersObject = {};\n\n // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (typeof headers === OBJECT && headers !== null) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * Deletes a property from an object if it exists.\n *\n * @param obj - The object from which to delete the property.\n * @param property - The property to delete from the object.\n */\nexport function deleteProperty>(\n obj: T | null,\n property: keyof T,\n): void {\n if (obj && property in obj) {\n delete obj[property];\n }\n}\n","import { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport type { RequestConfig } from './types';\nimport type { QueueItem, RequestsQueue } from './types/queue-manager';\n\n/**\n * Queue Manager is responsible for managing and controlling the flow of concurrent or sequential requests. It handles:\n * - Request Queueing and Deduplication\n * - Request Timeout Handling\n * - Abort Controller Management and Request Cancellation\n * - Concurrency Control and Locking\n * - Request Lifecycle Management\n */\nconst queue: RequestsQueue = new Map();\n\n/**\n * Adds a request to the queue if it's not already being processed within the dedupeTime interval.\n *\n * @param {RequestConfig} config - The request configuration object.\n * @param {number} timeout - Timeout in milliseconds for the request.\n * @param {number} dedupeTime - Deduplication time in milliseconds.\n * @param {boolean} isCancellable - If true, then the previous request with same configuration should be aborted.\n * @param {boolean} isTimeoutEnabled - Whether timeout is enabled.\n * @returns {Promise} - A promise that resolves to an AbortController.\n */\nexport async function addRequest(\n config: RequestConfig,\n timeout: number | undefined,\n dedupeTime: number = 0,\n isCancellable: boolean = false,\n isTimeoutEnabled: boolean = true,\n): Promise {\n const now = Date.now();\n const item = queue.get(config);\n\n if (item) {\n const isCancellable = item[3];\n const previousController = item[0];\n const timeoutId = item[1];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (!isCancellable && now - item[2] < dedupeTime) {\n return previousController;\n }\n\n // If the request is too old, remove it and proceed to add a new one\n // Abort previous request, if applicable, and continue as usual\n if (isCancellable) {\n previousController.abort(\n new DOMException('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n\n const controller = new AbortController();\n\n const timeoutId = isTimeoutEnabled\n ? setTimeout(() => {\n const error = new DOMException(\n `${config.url} aborted due to timeout`,\n TIMEOUT_ERROR,\n );\n\n removeRequest(config, error);\n }, timeout)\n : null;\n\n queue.set(config, [controller, timeoutId, now, isCancellable]);\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param config - The request configuration.\n * @param {boolean} error - Error payload so to force the request to abort.\n */\nexport async function removeRequest(\n config: RequestConfig,\n error: DOMException | null | string = null,\n): Promise {\n const item = queue.get(config);\n\n if (item) {\n const controller = item[0];\n const timeoutId = item[1];\n\n // If the request is not yet aborted, abort it with the provided error\n if (error && !controller.signal.aborted) {\n controller.abort(error);\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n}\n\n/**\n * Gets the AbortController for a request configuration.\n *\n * @param config - The request configuration.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n config: RequestConfig,\n): Promise {\n const item = queue.get(config);\n\n return item?.[0];\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n} from './constants';\nimport type { DefaultResponse, FetchResponse } from './types/request-handler';\n\n/**\n * Parses the response data based on the Content-Type header.\n *\n * @param response - The Response object to parse.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData(\n response: FetchResponse,\n): Promise {\n // Bail early when body is empty\n if (!response?.body) {\n return null;\n }\n\n const contentType = String(\n (response as Response).headers?.get(CONTENT_TYPE) || '',\n ).split(';')[0]; // Correctly handle charset\n\n let data;\n\n try {\n if (\n contentType.includes(APPLICATION_JSON) ||\n contentType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (contentType.includes('multipart/form-data')) {\n data = await response.formData(); // Parse as FormData\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream')\n ) {\n data = await response.blob(); // Parse as blob\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded')\n ) {\n data = await response.formData(); // Handle URL-encoded forms\n } else if (contentType.includes('text/')) {\n data = await response.text(); // Parse as text\n } else {\n try {\n const responseClone = response.clone();\n\n // Handle edge case of no content type being provided... We assume JSON here.\n data = await responseClone.json();\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_e) {\n // Handle streams\n data = await response.text();\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n // Parsing failed, fallback to null\n data = null;\n }\n\n return data;\n}\n","const PRIME_MULTIPLIER = 31;\n\n/**\n * Computes a hash value for a given string using the variant of djb2 hash function.\n * This hash function is non-cryptographic and designed for speed.\n * @author Daniel J. Bernstein (of djb2)\n *\n * @param str Input string to hash\n * @returns {string} Hash\n */\nexport function hash(str: string): string {\n let hash = 0;\n\n for (let i = 0, len = str.length; i < len; i++) {\n const char = str.charCodeAt(i);\n hash = (hash * PRIME_MULTIPLIER + char) | 0;\n }\n\n return String(hash);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport { fetchf } from './index';\nimport type { FetcherConfig } from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, OBJECT, UNDEFINED } from './constants';\nimport { shallowSerialize, sortObject } from './utils';\n\nconst cache = new Map>();\n\n/**\n * Generates a cache key for a given URL and fetch options, ensuring that key factors\n * like method, headers, body, and other options are included in the cache key.\n * Headers and other objects are sorted by key to ensure consistent cache keys.\n *\n * @param options - The fetch options that may affect the request. The most important are:\n * @property {string} [method=\"GET\"] - The HTTP method (GET, POST, etc.).\n * @property {HeadersInit} [headers={}] - The request headers.\n * @property {BodyInit | null} [body=\"\"] - The body of the request (only for methods like POST, PUT).\n * @property {RequestMode} [mode=\"cors\"] - The mode for the request (e.g., cors, no-cors, include).\n * @property {RequestCredentials} [credentials=\"include\"] - Whether to include credentials like cookies.\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @property {RequestRedirect} [redirect=\"follow\"] - How to handle redirects (e.g., follow, error, manual).\n * @property {string} [referrer=\"\"] - The referrer URL to send with the request.\n * @property {string} [integrity=\"\"] - Subresource integrity value (a cryptographic hash for resource validation).\n * @returns {string} - A unique cache key based on the URL and request options. Empty if cache is to be burst.\n *\n * @example\n * const cacheKey = generateCacheKey({\n * url: 'https://api.example.com/data',\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'Alice' }),\n * mode: 'cors',\n * credentials: 'include',\n * });\n * console.log(cacheKey);\n */\nexport function generateCacheKey(options: FetcherConfig): string {\n const {\n url = '',\n method = GET,\n headers = {},\n body = '',\n mode = 'cors',\n credentials = 'include',\n cache = 'default',\n redirect = 'follow',\n referrer = '',\n integrity = '',\n } = options;\n\n // Bail early if cache should be burst\n if (cache === 'reload') {\n return '';\n }\n\n // Sort headers and body + convert sorted to strings for hashing purposes\n // Native serializer is on avg. 3.5x faster than a Fast Hash or FNV-1a\n const headersString = shallowSerialize(sortObject(headers));\n\n let bodyString = '';\n\n // In majority of cases we do not cache body\n if (body !== null) {\n if (typeof body === 'string') {\n bodyString = hash(body);\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n bodyString = hash(bodyString);\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = typeof body === OBJECT ? sortObject(body) : String(body);\n bodyString = hash(JSON.stringify(o));\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n return (\n method +\n url +\n mode +\n credentials +\n cache +\n redirect +\n referrer +\n integrity +\n headersString +\n bodyString\n );\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the maximum stale time.\n *\n * @param {number} timestamp - The timestamp of the cache entry.\n * @param {number} maxStaleTime - The maximum stale time in seconds.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(timestamp: number, maxStaleTime: number): boolean {\n if (!maxStaleTime) {\n return false;\n }\n\n return Date.now() - timestamp > maxStaleTime * 1000;\n}\n\n/**\n * Retrieves a cache entry if it exists and is not expired.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} cacheTime - Maximum time to cache entry.\n * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string,\n cacheTime: number,\n): CacheEntry | null {\n const entry = cache.get(key);\n\n if (entry) {\n if (!isCacheExpired(entry.timestamp, cacheTime)) {\n return entry;\n }\n\n cache.delete(key);\n }\n\n return null;\n}\n\n/**\n * Sets a new cache entry or updates an existing one.\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {boolean} isLoading - Indicates if the data is currently being fetched.\n */\nexport function setCache(\n key: string,\n data: T,\n isLoading: boolean = false,\n): void {\n cache.set(key, {\n data,\n isLoading,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Revalidates a cache entry by fetching fresh data and updating the cache.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @returns {Promise} - A promise that resolves when the revalidation is complete.\n */\nexport async function revalidate(\n key: string,\n config: FetcherConfig,\n): Promise {\n try {\n // Fetch fresh data\n const newData = await fetchf(config.url, {\n ...config,\n cache: 'reload',\n });\n\n setCache(key, newData);\n } catch (error) {\n console.error(`Error revalidating ${config.url}:`, error);\n\n // Rethrow the error to forward it\n throw error;\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n */\nexport function deleteCache(key: string): void {\n cache.delete(key);\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @param {T} newData - The new data to be cached.\n * @param {boolean} revalidateAfter - If true, triggers revalidation after mutation.\n */\nexport function mutate(\n key: string,\n config: FetcherConfig,\n newData: T,\n revalidateAfter: boolean = false,\n): void {\n setCache(key, newData);\n\n if (revalidateAfter) {\n revalidate(key, config);\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n DefaultResponse,\n RequestHandlerConfig,\n RequestConfig,\n Method,\n RetryOptions,\n FetchResponse,\n ResponseError,\n RequestHandlerReturnType,\n CreatedCustomFetcherInstance,\n FetcherConfig,\n} from './types/request-handler';\nimport type {\n BodyPayload,\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n QueryParams,\n} from './types/api-handler';\nimport { applyInterceptor } from './interceptor-manager';\nimport { ResponseErr } from './response-error';\nimport {\n appendQueryParams,\n isJSONSerializable,\n replaceUrlPathParams,\n delayInvocation,\n flattenData,\n processHeaders,\n deleteProperty,\n isSearchParams,\n} from './utils';\nimport { addRequest, removeRequest } from './queue-manager';\nimport {\n ABORT_ERROR,\n APPLICATION_JSON,\n CANCELLED_ERROR,\n CONTENT_TYPE,\n GET,\n HEAD,\n OBJECT,\n STRING,\n UNDEFINED,\n} from './constants';\nimport { parseResponseData } from './response-parser';\nimport { generateCacheKey, getCache, setCache } from './cache-manager';\n\nconst defaultConfig: RequestHandlerConfig = {\n method: GET,\n strategy: 'reject',\n timeout: 30000,\n dedupeTime: 1000,\n defaultResponse: null,\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n [CONTENT_TYPE]: APPLICATION_JSON + ';charset=utf-8',\n },\n retry: {\n delay: 1000,\n maxDelay: 30000,\n resetTimeout: true,\n backoff: 1.5,\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n retryOn: [\n 408, // Request Timeout\n 409, // Conflict\n 425, // Too Early\n 429, // Too Many Requests\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504, // Gateway Timeout\n ],\n },\n};\n\n/**\n * Create Request Handler\n *\n * @param {RequestHandlerConfig} config - Configuration object for the request handler\n * @returns {Object} An object with methods for handling requests\n */\nexport function createRequestHandler(\n config: RequestHandlerConfig,\n): RequestHandlerReturnType {\n const handlerConfig: RequestHandlerConfig = {\n ...defaultConfig,\n ...config,\n };\n\n /**\n * Immediately create instance of custom fetcher if it is defined\n */\n const customFetcher = handlerConfig.fetcher;\n const requestInstance = customFetcher?.create(handlerConfig) || null;\n\n /**\n * Get Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Provider's instance\n */\n const getInstance = (): CreatedCustomFetcherInstance | null => {\n return requestInstance;\n };\n\n /**\n * Gets a configuration value from `reqConfig`, defaulting to `handlerConfig` if not present.\n *\n * @param {RequestConfig} reqConfig - Request configuration object.\n * @param {keyof RequestConfig} name - Key of the configuration value.\n * @returns {T} - The configuration value.\n */\n const getConfig = (\n reqConfig: RequestConfig,\n name: keyof RequestConfig,\n ): T => {\n return typeof reqConfig[name] !== UNDEFINED\n ? reqConfig[name]\n : handlerConfig[name];\n };\n\n /**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\n const logger = (...args: (string | ResponseError)[]): void => {\n if (handlerConfig.logger?.warn) {\n handlerConfig.logger.warn(...args);\n }\n };\n\n /**\n * Build request configuration\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @returns {RequestConfig} - Provider's instance\n */\n const buildConfig = (\n url: string,\n reqConfig: RequestConfig,\n ): FetcherConfig => {\n const method = getConfig(\n reqConfig,\n 'method',\n ).toUpperCase() as Method;\n const isGetAlikeMethod = method === GET || method === HEAD;\n\n const dynamicUrl = replaceUrlPathParams(\n url,\n getConfig(reqConfig, 'urlPathParams'),\n );\n\n // The explicitly passed \"params\"\n const explicitParams = getConfig(reqConfig, 'params');\n\n // The explicitly passed \"body\" or \"data\"\n const explicitBodyData: BodyPayload =\n getConfig(reqConfig, 'body') || getConfig(reqConfig, 'data');\n\n // Final body data\n let body: RequestConfig['data'];\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (!isGetAlikeMethod) {\n body = explicitBodyData;\n }\n\n // Native fetch compatible settings\n const isWithCredentials = getConfig(reqConfig, 'withCredentials');\n\n const credentials = isWithCredentials\n ? 'include'\n : getConfig(reqConfig, 'credentials');\n\n const urlPath = explicitParams\n ? appendQueryParams(dynamicUrl, explicitParams)\n : dynamicUrl;\n const isFullUrl = urlPath.includes('://');\n const baseURL = isFullUrl\n ? ''\n : getConfig(reqConfig, 'baseURL') ||\n getConfig(reqConfig, 'apiUrl');\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (\n body &&\n typeof body !== STRING &&\n !isSearchParams(body) &&\n isJSONSerializable(body)\n ) {\n body = JSON.stringify(body);\n }\n\n return {\n ...reqConfig,\n credentials,\n body,\n method,\n\n url: baseURL + urlPath,\n };\n };\n\n /**\n * Process global Request Error\n *\n * @param {ResponseError} error Error instance\n * @param {RequestConfig} requestConfig Per endpoint request config\n * @returns {Promise}\n */\n const processError = async (\n error: ResponseError,\n requestConfig: RequestConfig,\n ): Promise => {\n if (!isRequestCancelled(error)) {\n logger('API ERROR', error);\n }\n\n // Local interceptors\n await applyInterceptor(error, requestConfig?.onError);\n\n // Global interceptors\n await applyInterceptor(error, handlerConfig?.onError);\n };\n\n /**\n * Output default response in case of an error, depending on chosen strategy\n *\n * @param {ResponseError} error - Error instance\n * @param {FetchResponse | null} response - Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Per endpoint request config\n * @returns {FetchResponse} Response together with the error object\n */\n const outputErrorResponse = async (\n error: ResponseError,\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n ): Promise => {\n const _isRequestCancelled = isRequestCancelled(error);\n const errorHandlingStrategy = getConfig(requestConfig, 'strategy');\n const rejectCancelled = getConfig(\n requestConfig,\n 'rejectCancelled',\n );\n\n // By default cancelled requests aren't rejected (softFail strategy)\n if (!(_isRequestCancelled && !rejectCancelled)) {\n // Hang the promise\n if (errorHandlingStrategy === 'silent') {\n await new Promise(() => null);\n }\n // Reject the promise\n else if (errorHandlingStrategy === 'reject') {\n return Promise.reject(error);\n }\n }\n\n return outputResponse(response, requestConfig, error);\n };\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {ResponseError} error Error instance\n * @returns {boolean} True if request is aborted\n */\n const isRequestCancelled = (error: ResponseError): boolean => {\n return error.name === ABORT_ERROR || error.name === CANCELLED_ERROR;\n };\n\n /**\n * Handle Request depending on used strategy\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config\n * @throws {ResponseError}\n * @returns {Promise>} Response Data\n */\n const request = async <\n ResponseData = DefaultResponse,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n RequestBody = DefaultPayload,\n >(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n ): Promise> => {\n const _reqConfig = reqConfig || {};\n const mergedConfig = {\n ...handlerConfig,\n ..._reqConfig,\n } as RequestConfig;\n\n let response: FetchResponse | null = null;\n const fetcherConfig = buildConfig(url, mergedConfig);\n\n const {\n timeout,\n cancellable,\n dedupeTime,\n pollingInterval,\n shouldStopPolling,\n cacheTime,\n cacheKey,\n } = mergedConfig;\n\n // Prevent performance overhead of cache access\n let _cacheKey: string;\n\n if (cacheKey) {\n _cacheKey = cacheKey(fetcherConfig);\n } else {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n if (cacheTime && _cacheKey) {\n const cacheBuster = mergedConfig.cacheBuster;\n\n if (!cacheBuster || !cacheBuster(fetcherConfig)) {\n const cachedEntry = getCache>(\n _cacheKey,\n cacheTime,\n );\n\n if (cachedEntry) {\n // Serve stale data from cache\n return cachedEntry.data;\n }\n }\n }\n\n const {\n retries = 0,\n delay,\n backoff,\n retryOn,\n shouldRetry,\n maxDelay,\n resetTimeout,\n } = mergedConfig.retry as Required;\n\n let attempt = 0;\n let pollingAttempt = 0;\n let waitTime: number = delay;\n const _retries = retries > 0 ? retries : 0;\n\n while (attempt <= _retries) {\n try {\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = await addRequest(\n fetcherConfig,\n timeout,\n dedupeTime,\n cancellable,\n // Reset timeouts by default or when retries are ON\n !!(timeout && (!_retries || resetTimeout)),\n );\n\n // Shallow copy to ensure basic idempotency\n const requestConfig: RequestConfig = {\n signal: controller.signal,\n ...fetcherConfig,\n };\n\n // Local interceptors\n await applyInterceptor(requestConfig, _reqConfig?.onRequest);\n\n // Global interceptors\n await applyInterceptor(requestConfig, handlerConfig?.onRequest);\n\n if (customFetcher !== null && requestInstance !== null) {\n response = await requestInstance.request(requestConfig);\n } else {\n response = (await fetch(\n requestConfig.url as string,\n requestConfig as RequestInit,\n )) as FetchResponse;\n }\n\n // Add more information to response object\n if (response instanceof Response) {\n response.config = requestConfig;\n response.data = await parseResponseData(response);\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n if (!response.ok) {\n throw new ResponseErr(\n `${requestConfig.url} failed! Status: ${response.status || null}`,\n requestConfig,\n response,\n );\n }\n }\n\n // Local interceptors\n await applyInterceptor(response, _reqConfig?.onResponse);\n\n // Global interceptors\n await applyInterceptor(response, handlerConfig?.onResponse);\n\n removeRequest(fetcherConfig);\n\n // Polling logic\n if (\n pollingInterval &&\n (!shouldStopPolling || !shouldStopPolling(response, pollingAttempt))\n ) {\n // Restart the main retry loop\n pollingAttempt++;\n\n logger(`Polling attempt ${pollingAttempt}...`);\n\n await delayInvocation(pollingInterval);\n\n continue;\n }\n\n // If polling is not required, or polling attempts are exhausted\n const output = outputResponse(response, requestConfig);\n\n if (cacheTime && _cacheKey) {\n const skipCache = requestConfig.skipCache;\n\n if (!skipCache || !skipCache(output, requestConfig)) {\n setCache(_cacheKey, output);\n }\n }\n\n return output;\n } catch (err) {\n const error = err as ResponseErr;\n const status = error?.response?.status || error?.status || 0;\n\n if (\n attempt === retries ||\n !(!shouldRetry || (await shouldRetry(error, attempt))) ||\n !retryOn?.includes(status)\n ) {\n await processError(error, fetcherConfig);\n\n removeRequest(fetcherConfig);\n\n return outputErrorResponse(\n error,\n response,\n fetcherConfig,\n );\n }\n\n logger(`Attempt ${attempt + 1} failed. Retry in ${waitTime}ms.`);\n\n await delayInvocation(waitTime);\n\n waitTime *= backoff;\n waitTime = Math.min(waitTime, maxDelay);\n attempt++;\n }\n }\n\n return outputResponse(response, fetcherConfig);\n };\n\n /**\n * Output response\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\n const outputResponse = (\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n error: ResponseError | null = null,\n ): FetchResponse => {\n const defaultResponse = getConfig(requestConfig, 'defaultResponse');\n\n // This may happen when request is cancelled.\n if (!response) {\n return {\n ok: false,\n // Enhance the response with extra information\n error,\n data: defaultResponse,\n headers: null,\n config: requestConfig,\n } as unknown as FetchResponse;\n }\n\n // Clean up the error object\n deleteProperty(error, 'response');\n deleteProperty(error, 'request');\n deleteProperty(error, 'config');\n\n let data = response?.data;\n\n // Set the default response if the provided data is an empty object\n if (\n data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0)\n ) {\n data = defaultResponse;\n }\n\n // Return flattened response immediately\n const flattenResponse = getConfig(\n requestConfig,\n 'flattenResponse',\n );\n\n if (flattenResponse) {\n response.data = flattenData(data);\n }\n\n // If it's a custom fetcher, and it does not return any Response instance, it may have its own internal handler\n if (!(response instanceof Response)) {\n return response;\n }\n\n // Native fetch Response extended by extra information\n return {\n body: response.body,\n bodyUsed: response.bodyUsed,\n formData: response.formData,\n ok: response.ok,\n redirected: response.redirected,\n type: response.type,\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n\n blob: response.blob.bind(response),\n json: response.json.bind(response),\n text: response.text.bind(response),\n clone: response.clone.bind(response),\n arrayBuffer: response.arrayBuffer.bind(response),\n\n // Enhance the response with extra information\n error,\n data,\n headers: processHeaders(response.headers),\n config: requestConfig,\n };\n };\n\n return {\n getInstance,\n buildConfig,\n config,\n request,\n };\n}\n","import type {\n RequestConfig,\n FetchResponse,\n DefaultResponse,\n CreatedCustomFetcherInstance,\n} from './types/request-handler';\nimport type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n DefaultPayload,\n FallbackValue,\n FinalParams,\n FinalResponse,\n QueryParams,\n RequestConfigUrlRequired,\n UrlPathParams,\n} from './types/api-handler';\nimport { createRequestHandler } from './request-handler';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if it is passed as \"fetcher\".\n * @url https://github.com/MattCCC/fetchff\n *\n * @param {Object} config - Configuration object for the API fetcher.\n * @param {string} config.apiUrl - The base URL for the API.\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {number} config.timeout - You can set the timeout for particular request in milliseconds.\n * @param {number} config.cancellable - If true, the ongoing previous requests will be automatically cancelled.\n * @param {number} config.rejectCancelled - If true and request is set to cancellable, a cancelled request promise will be rejected. By default, instead of rejecting the promise, defaultResponse is returned.\n * @param {number} config.timeout - Request timeout\n * @param {number} config.dedupeTime - Time window, in milliseconds, during which identical requests are deduplicated (treated as single request).\n * @param {string} config.strategy - Error Handling Strategy\n * @param {string} config.flattenResponse - Whether to flatten response \"data\" object within \"data\". It works only if the response structure includes a single data property.\n * @param {*} config.defaultResponse - Default response when there is no data or when endpoint fails depending on the chosen strategy. It's \"null\" by default\n * @param {Object} [config.retry] - Options for retrying requests.\n * @param {number} [config.retry.retries=0] - Number of retry attempts. No retries by default.\n * @param {number} [config.retry.delay=1000] - Initial delay between retries in milliseconds.\n * @param {number} [config.retry.backoff=1.5] - Exponential backoff factor.\n * @param {number[]} [config.retry.retryOn=[502, 504, 408]] - HTTP status codes to retry on.\n * @param {RequestInterceptor|RequestInterceptor[]} [config.onRequest] - Optional request interceptor function or an array of functions.\n * These functions will be called with the request configuration object before the request is made. Can be used to modify or log the request configuration.\n * @param {ResponseInterceptor|ResponseInterceptor[]} [config.onResponse] - Optional response interceptor function or an array of functions.\n * These functions will be called with the response object after the response is received. an be used to modify or log the response data.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Object} config.fetcher - The Custom Fetcher instance to use for making requests. It should expose create() and request() functions.\n * @param {*} config.logger - Instance of custom logger. Either class or an object similar to \"console\". Console is used by default.\n * @returns API handler functions and endpoints to call\n *\n * @example\n * // Define endpoint paths\n * const endpoints = {\n * getUser: '/user',\n * createPost: '/post',\n * };\n *\n * // Create the API fetcher with configuration\n * const api = createApiFetcher({\n * endpoints,\n * apiUrl: 'https://example.com/api',\n * onError(error) {\n * console.log('Request failed', error);\n * },\n * headers: {\n * 'my-auth-key': 'example-auth-key-32rjjfa',\n * },\n * });\n *\n * // Fetch user data\n * const response = await api.getUser({ userId: 1, ratings: [1, 2] })\n */\nfunction createApiFetcher<\n EndpointsMethods extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n const requestHandler = createRequestHandler(config);\n\n /**\n * Get Custom Fetcher Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Request Handler's Custom Fetcher Instance\n */\n function getInstance(): CreatedCustomFetcherInstance | null {\n return requestHandler.getInstance();\n }\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n function handleNonImplemented(endpointName: string): Promise {\n console.error(`Add ${endpointName} to 'endpoints'.`);\n\n return Promise.resolve(null);\n }\n\n /**\n * Handle Single API Request\n * It considers settings in following order: per-request settings, global per-endpoint settings, global settings.\n *\n * @param {keyof EndpointsMethods | string} endpointName - The name of the API endpoint to call.\n * @param {EndpointConfig} [requestConfig={}] - Additional configuration for the request.\n * @returns {Promise>} - A promise that resolves with the response from the API provider.\n */\n async function request<\n ResponseData = never,\n QueryParams_ = never,\n UrlParams = never,\n RequestBody = never,\n >(\n endpointName: keyof EndpointsMethods | string,\n requestConfig: RequestConfig<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n > = {},\n ): Promise>> {\n // Use global per-endpoint settings\n const endpointConfig =\n endpoints[endpointName] ||\n ({ url: endpointName as string } as RequestConfigUrlRequired);\n\n const responseData = await requestHandler.request<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n >(endpointConfig.url, {\n ...endpointConfig,\n ...requestConfig,\n });\n\n return responseData;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\n requestHandler,\n getInstance,\n request,\n };\n\n /**\n * Maps all API requests using native Proxy\n *\n * @param {*} prop Caller\n */\n return new Proxy>(\n apiHandler as ApiHandlerMethods,\n {\n get(_target, prop: string) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n","import { createRequestHandler } from './request-handler';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestHandlerConfig,\n} from './types';\n\n/**\n * Simple wrapper for request fetching.\n * It abstracts the creation of RequestHandler, making it easy to perform API requests.\n *\n * @param {string | URL | globalThis.Request} url - Request URL.\n * @param {RequestHandlerConfig} config - Configuration object for the request handler.\n * @returns {Promise>} Response Data.\n */\nexport async function fetchf(\n url: string,\n config: RequestHandlerConfig = {},\n): Promise> {\n return createRequestHandler(config).request(url, config);\n}\n\nexport * from './types';\nexport * from './api-handler';\n"],"mappings":"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","names":["applyInterceptor","object","interceptors","value","interceptor","ResponseErr","message","requestInfo","response","__publicField","APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","ABORT_ERROR","TIMEOUT_ERROR","CANCELLED_ERROR","GET","HEAD","isSearchParams","data","shallowSerialize","obj","result","key","sortObject","sortedObj","keys","i","len","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","isSearchParams","encodedQueryString","s","encode","add","k","v","buildParams","prefix","OBJECT","replaceUrlPathParams","urlPathParams","str","word","isJSONSerializable","value","UNDEFINED","STRING","proto","delayInvocation","ms","resolve","flattenData","data","processHeaders","headers","headersObject","deleteProperty","property","queue","addRequest","config","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","previousController","timeoutId","ABORT_ERROR","controller","error","TIMEOUT_ERROR","removeRequest","parseResponseData","response","_a","contentType","CONTENT_TYPE","data","APPLICATION_JSON","APPLICATION_CONTENT_TYPE","_e","_error","hash","str","i","len","char","cache","generateCacheKey","options","url","method","GET","headers","body","mode","credentials","redirect","referrer","integrity","headersString","shallowSerialize","sortObject","bodyString","hash","value","key","UNDEFINED","o","OBJECT","isCacheExpired","timestamp","maxStaleTime","getCache","cacheTime","entry","setCache","data","isLoading","defaultConfig","GET","APPLICATION_JSON","CONTENT_TYPE","createRequestHandler","config","handlerConfig","customFetcher","requestInstance","getInstance","getConfig","reqConfig","name","UNDEFINED","logger","args","_a","buildConfig","url","method","isGetAlikeMethod","HEAD","dynamicUrl","replaceUrlPathParams","explicitParams","explicitBodyData","body","credentials","urlPath","appendQueryParams","baseURL","STRING","isSearchParams","isJSONSerializable","processError","error","requestConfig","isRequestCancelled","applyInterceptor","outputErrorResponse","response","_isRequestCancelled","errorHandlingStrategy","rejectCancelled","outputResponse","ABORT_ERROR","CANCELLED_ERROR","request","_reqConfig","mergedConfig","fetcherConfig","timeout","cancellable","dedupeTime","pollingInterval","shouldStopPolling","cacheTime","cacheKey","_cacheKey","generateCacheKey","cacheBuster","cachedEntry","getCache","retries","delay","backoff","retryOn","shouldRetry","maxDelay","resetTimeout","attempt","pollingAttempt","waitTime","_retries","addRequest","parseResponseData","ResponseErr","removeRequest","delayInvocation","output","skipCache","setCache","err","status","defaultResponse","deleteProperty","data","OBJECT","flattenData","processHeaders","createApiFetcher","config","endpoints","requestHandler","createRequestHandler","getInstance","handleNonImplemented","endpointName","request","requestConfig","endpointConfig","apiHandler","_target","prop","fetchf","url","config","createRequestHandler"]} \ No newline at end of file +{"version":3,"sources":["../../src/interceptor-manager.ts","../../src/response-error.ts","../../src/constants.ts","../../src/utils.ts","../../src/queue-manager.ts","../../src/response-parser.ts","../../src/hash.ts","../../src/cache-manager.ts","../../src/request-handler.ts","../../src/api-handler.ts","../../src/index.ts"],"sourcesContent":["type InterceptorFunction = (object: T) => Promise;\n\n/**\n * Applies interceptors to the object. Interceptors can be a single function or an array of functions.\n *\n * @template T - Type of the object.\n * @template I - Type of interceptors.\n *\n * @param {T} object - The object to process.\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptor<\n T extends object,\n I = InterceptorFunction | InterceptorFunction[],\n>(object: T, interceptors?: I): Promise {\n if (!interceptors) {\n return;\n }\n\n if (typeof interceptors === 'function') {\n const value = await interceptors(object);\n\n if (value) {\n Object.assign(object, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(object);\n\n if (value) {\n Object.assign(object, value);\n }\n }\n }\n}\n","import type { FetchResponse, RequestConfig } from './types';\n\nexport class ResponseErr extends Error {\n response: FetchResponse;\n request: RequestConfig;\n config: RequestConfig;\n status: number;\n statusText: string;\n\n constructor(\n message: string,\n requestInfo: RequestConfig,\n response: FetchResponse,\n ) {\n super(message);\n\n this.name = 'ResponseError';\n this.message = message;\n this.status = response.status;\n this.statusText = response.statusText;\n this.request = requestInfo;\n this.config = requestInfo;\n this.response = response;\n }\n}\n","export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\nexport const CANCELLED_ERROR = 'CanceledError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\nexport function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const sortedObj = {} as Record;\n const keys = Object.keys(obj);\n\n keys.sort();\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === 'function' ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any) => {\n let i: number, len: number, key: string;\n\n if (prefix) {\n if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n buildParams(\n prefix + '[' + (typeof obj[i] === OBJECT && obj[i] ? i : '') + ']',\n obj[i],\n );\n }\n } else if (typeof obj === OBJECT && obj !== null) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key]);\n }\n } else {\n add(prefix, obj);\n }\n } else if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n add(obj[i].name, obj[i].value);\n }\n } else {\n for (key in obj) {\n buildParams(key, obj[key]);\n }\n }\n return s;\n };\n\n const queryStringParts = buildParams('', params).join('&');\n\n // Encode special characters as per RFC 3986, https://datatracker.ietf.org/doc/html/rfc3986\n const encodedQueryString = queryStringParts.replace(/%5B%5D/g, '[]'); // Keep '[]' for arrays\n\n return appendQueryStringToUrl(url, encodedQueryString);\n}\n\n/**\n * Replaces dynamic URI parameters in a URL string with values from the provided `urlPathParams` object.\n * Parameters in the URL are denoted by `:`, where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:`.\n * @param {Object} urlPathParams - An object containing the parameter values to replace placeholders.\n * @param {string} urlPathParams.paramName - The value to replace the placeholder `:` in the URL.\n * @returns {string} - The URL string with placeholders replaced by corresponding values from `urlPathParams`.\n */\nexport function replaceUrlPathParams(\n url: string,\n urlPathParams: UrlPathParams,\n): string {\n if (!urlPathParams) {\n return url;\n }\n\n return url.replace(/:\\w+/g, (str): string => {\n const word = str.substring(1);\n\n if ((urlPathParams as DefaultUrlParams)[word]) {\n return String((urlPathParams as DefaultUrlParams)[word]);\n }\n\n return str;\n });\n}\n\n/**\n * Checks if a value is JSON serializable.\n *\n * JSON serializable values include:\n * - Primitive types: string, number, boolean, null\n * - Arrays\n * - Plain objects (i.e., objects without special methods)\n * - Values with a `toJSON` method\n *\n * @param {any} value - The value to check for JSON serializability.\n * @returns {boolean} - Returns `true` if the value is JSON serializable, otherwise `false`.\n */\nexport function isJSONSerializable(value: any): boolean {\n const t = typeof value;\n\n if (t === UNDEFINED || value === null) {\n return false;\n }\n\n if (t === STRING || t === 'number' || t === 'boolean') {\n return true;\n }\n\n if (Array.isArray(value)) {\n return true;\n }\n\n if (Buffer.isBuffer(value)) {\n return false;\n }\n\n if (value instanceof Date) {\n return false;\n }\n\n if (t === OBJECT) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` or `null` (plain object)\n if (proto === Object.prototype || proto === null) {\n return true;\n }\n\n // Check if the object has a toJSON method\n if (typeof value.toJSON === 'function') {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any): any {\n if (\n data &&\n typeof data === OBJECT &&\n typeof data.data !== UNDEFINED &&\n Object.keys(data).length === 1\n ) {\n return flattenData(data.data);\n }\n\n return data;\n}\n\n/**\n * Processes headers and returns them as a normalized object.\n *\n * Handles both `Headers` instances and plain objects. Normalizes header keys to lowercase\n * as per RFC 2616 section 4.2.\n *\n * @param headers - The headers to process. Can be an instance of `Headers`, a plain object,\n * or `null`. If `null`, an empty object is returned.\n * @returns {HeadersObject} - A normalized headers object with lowercase keys.\n */\nexport function processHeaders(\n headers?: (HeadersObject & HeadersInit) | null | Headers,\n): HeadersObject {\n if (!headers) {\n return {};\n }\n\n const headersObject: HeadersObject = {};\n\n // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (typeof headers === OBJECT && headers !== null) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * Deletes a property from an object if it exists.\n *\n * @param obj - The object from which to delete the property.\n * @param property - The property to delete from the object.\n */\nexport function deleteProperty>(\n obj: T | null,\n property: keyof T,\n): void {\n if (obj && property in obj) {\n delete obj[property];\n }\n}\n","import { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport type { RequestConfig } from './types';\nimport type { QueueItem, RequestsQueue } from './types/queue-manager';\n\n/**\n * Queue Manager is responsible for managing and controlling the flow of concurrent or sequential requests. It handles:\n * - Request Queueing and Deduplication\n * - Request Timeout Handling\n * - Abort Controller Management and Request Cancellation\n * - Concurrency Control and Locking\n * - Request Lifecycle Management\n */\nconst queue: RequestsQueue = new Map();\n\n/**\n * Adds a request to the queue if it's not already being processed within the dedupeTime interval.\n *\n * @param {RequestConfig} config - The request configuration object.\n * @param {number} timeout - Timeout in milliseconds for the request.\n * @param {number} dedupeTime - Deduplication time in milliseconds.\n * @param {boolean} isCancellable - If true, then the previous request with same configuration should be aborted.\n * @param {boolean} isTimeoutEnabled - Whether timeout is enabled.\n * @returns {Promise} - A promise that resolves to an AbortController.\n */\nexport async function addRequest(\n config: RequestConfig,\n timeout: number | undefined,\n dedupeTime: number = 0,\n isCancellable: boolean = false,\n isTimeoutEnabled: boolean = true,\n): Promise {\n const now = Date.now();\n const item = queue.get(config);\n\n if (item) {\n const isCancellable = item[3];\n const previousController = item[0];\n const timeoutId = item[1];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (!isCancellable && now - item[2] < dedupeTime) {\n return previousController;\n }\n\n // If the request is too old, remove it and proceed to add a new one\n // Abort previous request, if applicable, and continue as usual\n if (isCancellable) {\n previousController.abort(\n new DOMException('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n\n const controller = new AbortController();\n\n const timeoutId = isTimeoutEnabled\n ? setTimeout(() => {\n const error = new DOMException(\n `${config.url} aborted due to timeout`,\n TIMEOUT_ERROR,\n );\n\n removeRequest(config, error);\n }, timeout)\n : null;\n\n queue.set(config, [controller, timeoutId, now, isCancellable]);\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param config - The request configuration.\n * @param {boolean} error - Error payload so to force the request to abort.\n */\nexport async function removeRequest(\n config: RequestConfig,\n error: DOMException | null | string = null,\n): Promise {\n const item = queue.get(config);\n\n if (item) {\n const controller = item[0];\n const timeoutId = item[1];\n\n // If the request is not yet aborted, abort it with the provided error\n if (error && !controller.signal.aborted) {\n controller.abort(error);\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n}\n\n/**\n * Gets the AbortController for a request configuration.\n *\n * @param config - The request configuration.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n config: RequestConfig,\n): Promise {\n const item = queue.get(config);\n\n return item?.[0];\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n} from './constants';\nimport type { DefaultResponse, FetchResponse } from './types/request-handler';\n\n/**\n * Parses the response data based on the Content-Type header.\n *\n * @param response - The Response object to parse.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData(\n response: FetchResponse,\n): Promise {\n // Bail early when body is empty\n if (!response?.body) {\n return null;\n }\n\n const contentType = String(\n (response as Response).headers?.get(CONTENT_TYPE) || '',\n ).split(';')[0]; // Correctly handle charset\n\n let data;\n\n try {\n if (\n contentType.includes(APPLICATION_JSON) ||\n contentType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (contentType.includes('multipart/form-data')) {\n data = await response.formData(); // Parse as FormData\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream')\n ) {\n data = await response.blob(); // Parse as blob\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded')\n ) {\n data = await response.formData(); // Handle URL-encoded forms\n } else if (contentType.includes('text/')) {\n data = await response.text(); // Parse as text\n } else {\n try {\n const responseClone = response.clone();\n\n // Handle edge case of no content type being provided... We assume JSON here.\n data = await responseClone.json();\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_e) {\n // Handle streams\n data = await response.text();\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n // Parsing failed, fallback to null\n data = null;\n }\n\n return data;\n}\n","const PRIME_MULTIPLIER = 31;\n\n/**\n * Computes a hash value for a given string using the variant of djb2 hash function.\n * This hash function is non-cryptographic and designed for speed.\n * @author Daniel J. Bernstein (of djb2)\n *\n * @param str Input string to hash\n * @returns {string} Hash\n */\nexport function hash(str: string): string {\n let hash = 0;\n\n for (let i = 0, len = str.length; i < len; i++) {\n const char = str.charCodeAt(i);\n hash = (hash * PRIME_MULTIPLIER + char) | 0;\n }\n\n return String(hash);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport { fetchf } from './index';\nimport type { FetcherConfig } from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, OBJECT, UNDEFINED } from './constants';\nimport { shallowSerialize, sortObject } from './utils';\n\nconst cache = new Map>();\n\n/**\n * Generates a cache key for a given URL and fetch options, ensuring that key factors\n * like method, headers, body, and other options are included in the cache key.\n * Headers and other objects are sorted by key to ensure consistent cache keys.\n *\n * @param options - The fetch options that may affect the request. The most important are:\n * @property {string} [method=\"GET\"] - The HTTP method (GET, POST, etc.).\n * @property {HeadersInit} [headers={}] - The request headers.\n * @property {BodyInit | null} [body=\"\"] - The body of the request (only for methods like POST, PUT).\n * @property {RequestMode} [mode=\"cors\"] - The mode for the request (e.g., cors, no-cors, include).\n * @property {RequestCredentials} [credentials=\"include\"] - Whether to include credentials like cookies.\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @property {RequestRedirect} [redirect=\"follow\"] - How to handle redirects (e.g., follow, error, manual).\n * @property {string} [referrer=\"\"] - The referrer URL to send with the request.\n * @property {string} [integrity=\"\"] - Subresource integrity value (a cryptographic hash for resource validation).\n * @returns {string} - A unique cache key based on the URL and request options. Empty if cache is to be burst.\n *\n * @example\n * const cacheKey = generateCacheKey({\n * url: 'https://api.example.com/data',\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'Alice' }),\n * mode: 'cors',\n * credentials: 'include',\n * });\n * console.log(cacheKey);\n */\nexport function generateCacheKey(options: FetcherConfig): string {\n const {\n url = '',\n method = GET,\n headers = {},\n body = '',\n mode = 'cors',\n credentials = 'include',\n cache = 'default',\n redirect = 'follow',\n referrer = '',\n integrity = '',\n } = options;\n\n // Bail early if cache should be burst\n if (cache === 'reload') {\n return '';\n }\n\n // Sort headers and body + convert sorted to strings for hashing purposes\n // Native serializer is on avg. 3.5x faster than a Fast Hash or FNV-1a\n const headersString = shallowSerialize(sortObject(headers));\n\n let bodyString = '';\n\n // In majority of cases we do not cache body\n if (body !== null) {\n if (typeof body === 'string') {\n bodyString = hash(body);\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n bodyString = hash(bodyString);\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = typeof body === OBJECT ? sortObject(body) : String(body);\n bodyString = hash(JSON.stringify(o));\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n return (\n method +\n url +\n mode +\n credentials +\n cache +\n redirect +\n referrer +\n integrity +\n headersString +\n bodyString\n );\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the maximum stale time.\n *\n * @param {number} timestamp - The timestamp of the cache entry.\n * @param {number} maxStaleTime - The maximum stale time in seconds.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(timestamp: number, maxStaleTime: number): boolean {\n if (!maxStaleTime) {\n return false;\n }\n\n return Date.now() - timestamp > maxStaleTime * 1000;\n}\n\n/**\n * Retrieves a cache entry if it exists and is not expired.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} cacheTime - Maximum time to cache entry.\n * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string,\n cacheTime: number,\n): CacheEntry | null {\n const entry = cache.get(key);\n\n if (entry) {\n if (!isCacheExpired(entry.timestamp, cacheTime)) {\n return entry;\n }\n\n cache.delete(key);\n }\n\n return null;\n}\n\n/**\n * Sets a new cache entry or updates an existing one.\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {boolean} isLoading - Indicates if the data is currently being fetched.\n */\nexport function setCache(\n key: string,\n data: T,\n isLoading: boolean = false,\n): void {\n cache.set(key, {\n data,\n isLoading,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Revalidates a cache entry by fetching fresh data and updating the cache.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @returns {Promise} - A promise that resolves when the revalidation is complete.\n */\nexport async function revalidate(\n key: string,\n config: FetcherConfig,\n): Promise {\n try {\n // Fetch fresh data\n const newData = await fetchf(config.url, {\n ...config,\n cache: 'reload',\n });\n\n setCache(key, newData);\n } catch (error) {\n console.error(`Error revalidating ${config.url}:`, error);\n\n // Rethrow the error to forward it\n throw error;\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n */\nexport function deleteCache(key: string): void {\n cache.delete(key);\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @param {T} newData - The new data to be cached.\n * @param {boolean} revalidateAfter - If true, triggers revalidation after mutation.\n */\nexport function mutate(\n key: string,\n config: FetcherConfig,\n newData: T,\n revalidateAfter: boolean = false,\n): void {\n setCache(key, newData);\n\n if (revalidateAfter) {\n revalidate(key, config);\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n DefaultResponse,\n RequestHandlerConfig,\n RequestConfig,\n Method,\n RetryOptions,\n FetchResponse,\n ResponseError,\n RequestHandlerReturnType,\n CreatedCustomFetcherInstance,\n FetcherConfig,\n FetcherInstance,\n Logger,\n} from './types/request-handler';\nimport type {\n BodyPayload,\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n QueryParams,\n} from './types/api-handler';\nimport { applyInterceptor } from './interceptor-manager';\nimport { ResponseErr } from './response-error';\nimport {\n appendQueryParams,\n isJSONSerializable,\n replaceUrlPathParams,\n delayInvocation,\n flattenData,\n processHeaders,\n deleteProperty,\n isSearchParams,\n} from './utils';\nimport { addRequest, removeRequest } from './queue-manager';\nimport {\n ABORT_ERROR,\n APPLICATION_JSON,\n CANCELLED_ERROR,\n CONTENT_TYPE,\n GET,\n HEAD,\n OBJECT,\n STRING,\n UNDEFINED,\n} from './constants';\nimport { parseResponseData } from './response-parser';\nimport { generateCacheKey, getCache, setCache } from './cache-manager';\n\nconst defaultConfig: RequestHandlerConfig = {\n method: GET,\n strategy: 'reject',\n timeout: 30000,\n dedupeTime: 1000,\n defaultResponse: null,\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n [CONTENT_TYPE]: APPLICATION_JSON + ';charset=utf-8',\n },\n retry: {\n delay: 1000,\n maxDelay: 30000,\n resetTimeout: true,\n backoff: 1.5,\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n retryOn: [\n 408, // Request Timeout\n 409, // Conflict\n 425, // Too Early\n 429, // Too Many Requests\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504, // Gateway Timeout\n ],\n },\n};\n\n/**\n * Create Request Handler\n *\n * @param {RequestHandlerConfig} config - Configuration object for the request handler\n * @returns {Object} An object with methods for handling requests\n */\nexport function createRequestHandler(\n config: RequestHandlerConfig,\n): RequestHandlerReturnType {\n const handlerConfig: RequestHandlerConfig = {\n ...defaultConfig,\n ...config,\n };\n\n /**\n * Merges the specified property from the base configuration and the new configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and new configurations. Must be a key of RequestHandlerConfig.\n * @param {RequestHandlerConfig} targetConfig - The configuration object that will receive the merged properties.\n * @param {RequestHandlerConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestHandlerConfig} newConfig - The new configuration object that contains user-specific settings to merge.\n */\n const mergeConfig = (\n property: K,\n targetConfig: RequestHandlerConfig,\n baseConfig: RequestHandlerConfig,\n newConfig: RequestHandlerConfig,\n ) => {\n if (newConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...newConfig[property],\n };\n }\n };\n\n mergeConfig('retry', handlerConfig, defaultConfig, config);\n mergeConfig('headers', handlerConfig, defaultConfig, config);\n\n /**\n * Gets a configuration value from `reqConfig`, defaulting to `handlerConfig` if not present.\n *\n * @param {RequestConfig} reqConfig - Request configuration object.\n * @param {keyof RequestConfig} name - Key of the configuration value.\n * @returns {T} - The configuration value.\n */\n const getConfig = (\n reqConfig: RequestConfig,\n name: keyof RequestConfig,\n ): T => {\n return typeof reqConfig[name] !== UNDEFINED\n ? reqConfig[name]\n : handlerConfig[name];\n };\n\n /**\n * Immediately create instance of custom fetcher if it is defined\n */\n const customFetcher = getConfig(config, 'fetcher');\n const requestInstance = customFetcher?.create(handlerConfig) || null;\n\n /**\n * Get Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Provider's instance\n */\n const getInstance = (): CreatedCustomFetcherInstance | null => {\n return requestInstance;\n };\n\n /**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\n const logger = (\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n ): void => {\n const logger = getConfig(reqConfig, 'logger');\n\n if (logger?.warn) {\n logger.warn(...args);\n }\n };\n\n /**\n * Build request configuration\n *\n * @param {string} url - Request url\n * @param {RequestConfig} requestConfig - Request config passed when making the request\n * @returns {RequestConfig} - Provider's instance\n */\n const buildConfig = (\n url: string,\n requestConfig: RequestConfig,\n ): FetcherConfig => {\n const method = getConfig(\n requestConfig,\n 'method',\n ).toUpperCase() as Method;\n const isGetAlikeMethod = method === GET || method === HEAD;\n\n const dynamicUrl = replaceUrlPathParams(\n url,\n getConfig(requestConfig, 'urlPathParams'),\n );\n\n // The explicitly passed \"params\"\n const explicitParams = getConfig(requestConfig, 'params');\n\n // The explicitly passed \"body\" or \"data\"\n const explicitBodyData: BodyPayload =\n getConfig(requestConfig, 'body') || getConfig(requestConfig, 'data');\n\n // Final body data\n let body: RequestConfig['data'];\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (!isGetAlikeMethod) {\n body = explicitBodyData;\n }\n\n // Native fetch compatible settings\n const isWithCredentials = getConfig(\n requestConfig,\n 'withCredentials',\n );\n\n const credentials = isWithCredentials\n ? 'include'\n : getConfig(requestConfig, 'credentials');\n\n const urlPath = explicitParams\n ? appendQueryParams(dynamicUrl, explicitParams)\n : dynamicUrl;\n const isFullUrl = urlPath.includes('://');\n const baseURL = isFullUrl\n ? ''\n : getConfig(requestConfig, 'baseURL') ||\n getConfig(requestConfig, 'apiUrl');\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (\n body &&\n typeof body !== STRING &&\n !isSearchParams(body) &&\n isJSONSerializable(body)\n ) {\n body = JSON.stringify(body);\n }\n\n return {\n ...requestConfig,\n credentials,\n body,\n method,\n\n url: baseURL + urlPath,\n };\n };\n\n /**\n * Process global Request Error\n *\n * @param {ResponseError} error Error instance\n * @param {RequestConfig} requestConfig Per endpoint request config\n * @returns {Promise}\n */\n const processError = async (\n error: ResponseError,\n requestConfig: RequestConfig,\n ): Promise => {\n if (!isRequestCancelled(error)) {\n logger(requestConfig, 'API ERROR', error);\n }\n\n // Local interceptors\n await applyInterceptor(error, requestConfig?.onError);\n\n // Global interceptors\n await applyInterceptor(error, handlerConfig?.onError);\n };\n\n /**\n * Output default response in case of an error, depending on chosen strategy\n *\n * @param {ResponseError} error - Error instance\n * @param {FetchResponse | null} response - Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Per endpoint request config\n * @returns {FetchResponse} Response together with the error object\n */\n const outputErrorResponse = async (\n error: ResponseError,\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n ): Promise => {\n const _isRequestCancelled = isRequestCancelled(error);\n const errorHandlingStrategy = getConfig(requestConfig, 'strategy');\n const rejectCancelled = getConfig(\n requestConfig,\n 'rejectCancelled',\n );\n\n // By default cancelled requests aren't rejected (softFail strategy)\n if (!(_isRequestCancelled && !rejectCancelled)) {\n // Hang the promise\n if (errorHandlingStrategy === 'silent') {\n await new Promise(() => null);\n }\n // Reject the promise\n else if (errorHandlingStrategy === 'reject') {\n return Promise.reject(error);\n }\n }\n\n return outputResponse(response, requestConfig, error);\n };\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {ResponseError} error Error instance\n * @returns {boolean} True if request is aborted\n */\n const isRequestCancelled = (error: ResponseError): boolean => {\n return error.name === ABORT_ERROR || error.name === CANCELLED_ERROR;\n };\n\n /**\n * Handle Request depending on used strategy\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config\n * @throws {ResponseError}\n * @returns {Promise>} Response Data\n */\n const request = async <\n ResponseData = DefaultResponse,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n RequestBody = DefaultPayload,\n >(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n ): Promise> => {\n const _reqConfig = reqConfig || {};\n const mergedConfig = {\n ...handlerConfig,\n ..._reqConfig,\n } as RequestConfig;\n\n mergeConfig('retry', mergedConfig, handlerConfig, _reqConfig);\n mergeConfig('headers', mergedConfig, handlerConfig, _reqConfig);\n\n let response: FetchResponse | null = null;\n const fetcherConfig = buildConfig(url, mergedConfig);\n\n const {\n timeout,\n cancellable,\n dedupeTime,\n pollingInterval,\n shouldStopPolling,\n cacheTime,\n cacheKey,\n } = mergedConfig;\n\n // Prevent performance overhead of cache access\n let _cacheKey: string;\n\n if (cacheKey) {\n _cacheKey = cacheKey(fetcherConfig);\n } else {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n if (cacheTime && _cacheKey) {\n const cacheBuster = mergedConfig.cacheBuster;\n\n if (!cacheBuster || !cacheBuster(fetcherConfig)) {\n const cachedEntry = getCache>(\n _cacheKey,\n cacheTime,\n );\n\n if (cachedEntry) {\n // Serve stale data from cache\n return cachedEntry.data;\n }\n }\n }\n\n const {\n retries = 0,\n delay,\n backoff,\n retryOn,\n shouldRetry,\n maxDelay,\n resetTimeout,\n } = mergedConfig.retry as Required;\n\n let attempt = 0;\n let pollingAttempt = 0;\n let waitTime: number = delay;\n const _retries = retries > 0 ? retries : 0;\n\n while (attempt <= _retries) {\n try {\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = await addRequest(\n fetcherConfig,\n timeout,\n dedupeTime,\n cancellable,\n // Reset timeouts by default or when retries are ON\n !!(timeout && (!_retries || resetTimeout)),\n );\n\n // Shallow copy to ensure basic idempotency\n const requestConfig: RequestConfig = {\n signal: controller.signal,\n ...fetcherConfig,\n };\n\n // Local interceptors\n await applyInterceptor(requestConfig, _reqConfig?.onRequest);\n\n // Global interceptors\n await applyInterceptor(requestConfig, handlerConfig?.onRequest);\n\n if (customFetcher !== null && requestInstance !== null) {\n response = await requestInstance.request(requestConfig);\n } else {\n response = (await fetch(\n requestConfig.url as string,\n requestConfig as RequestInit,\n )) as FetchResponse;\n }\n\n // Add more information to response object\n if (response instanceof Response) {\n response.config = requestConfig;\n response.data = await parseResponseData(response);\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n if (!response.ok) {\n throw new ResponseErr(\n `${requestConfig.url} failed! Status: ${response.status || null}`,\n requestConfig,\n response,\n );\n }\n }\n\n // Local interceptors\n await applyInterceptor(response, _reqConfig?.onResponse);\n\n // Global interceptors\n await applyInterceptor(response, handlerConfig?.onResponse);\n\n removeRequest(fetcherConfig);\n\n // Polling logic\n if (\n pollingInterval &&\n (!shouldStopPolling || !shouldStopPolling(response, pollingAttempt))\n ) {\n // Restart the main retry loop\n pollingAttempt++;\n\n logger(requestConfig, 'Polling attempt ' + pollingAttempt + '...');\n\n await delayInvocation(pollingInterval);\n\n continue;\n }\n\n // If polling is not required, or polling attempts are exhausted\n const output = outputResponse(response, requestConfig);\n\n if (cacheTime && _cacheKey) {\n const skipCache = requestConfig.skipCache;\n\n if (!skipCache || !skipCache(output, requestConfig)) {\n setCache(_cacheKey, output);\n }\n }\n\n return output;\n } catch (err) {\n const error = err as ResponseErr;\n const status = error?.response?.status || error?.status || 0;\n\n if (\n attempt === retries ||\n !(!shouldRetry || (await shouldRetry(error, attempt))) ||\n !retryOn?.includes(status)\n ) {\n await processError(error, fetcherConfig);\n\n removeRequest(fetcherConfig);\n\n return outputErrorResponse(\n error,\n response,\n fetcherConfig,\n );\n }\n\n logger(\n mergedConfig,\n `Attempt ${attempt + 1} failed. Retry in ${waitTime}ms.`,\n );\n\n await delayInvocation(waitTime);\n\n waitTime *= backoff;\n waitTime = Math.min(waitTime, maxDelay);\n attempt++;\n }\n }\n\n return outputResponse(response, fetcherConfig);\n };\n\n /**\n * Output response\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\n const outputResponse = (\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n error: ResponseError | null = null,\n ): FetchResponse => {\n const defaultResponse = getConfig(requestConfig, 'defaultResponse');\n\n // This may happen when request is cancelled.\n if (!response) {\n return {\n ok: false,\n // Enhance the response with extra information\n error,\n data: defaultResponse,\n headers: null,\n config: requestConfig,\n } as unknown as FetchResponse;\n }\n\n // Clean up the error object\n deleteProperty(error, 'response');\n deleteProperty(error, 'request');\n deleteProperty(error, 'config');\n\n let data = response?.data;\n\n // Set the default response if the provided data is an empty object\n if (\n data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0)\n ) {\n data = defaultResponse;\n }\n\n // Return flattened response immediately\n const flattenResponse = getConfig(\n requestConfig,\n 'flattenResponse',\n );\n\n if (flattenResponse) {\n response.data = flattenData(data);\n }\n\n // If it's a custom fetcher, and it does not return any Response instance, it may have its own internal handler\n if (!(response instanceof Response)) {\n return response;\n }\n\n // Native fetch Response extended by extra information\n return {\n body: response.body,\n bodyUsed: response.bodyUsed,\n formData: response.formData,\n ok: response.ok,\n redirected: response.redirected,\n type: response.type,\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n\n blob: response.blob.bind(response),\n json: response.json.bind(response),\n text: response.text.bind(response),\n clone: response.clone.bind(response),\n arrayBuffer: response.arrayBuffer.bind(response),\n\n // Enhance the response with extra information\n error,\n data,\n headers: processHeaders(response.headers),\n config: requestConfig,\n };\n };\n\n return {\n getInstance,\n buildConfig,\n config,\n request,\n };\n}\n","import type {\n RequestConfig,\n FetchResponse,\n DefaultResponse,\n CreatedCustomFetcherInstance,\n} from './types/request-handler';\nimport type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n DefaultPayload,\n FallbackValue,\n FinalParams,\n FinalResponse,\n QueryParams,\n RequestConfigUrlRequired,\n UrlPathParams,\n} from './types/api-handler';\nimport { createRequestHandler } from './request-handler';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if it is passed as \"fetcher\".\n * @url https://github.com/MattCCC/fetchff\n *\n * @param {Object} config - Configuration object for the API fetcher.\n * @param {string} config.apiUrl - The base URL for the API.\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {number} config.timeout - You can set the timeout for particular request in milliseconds.\n * @param {number} config.cancellable - If true, the ongoing previous requests will be automatically cancelled.\n * @param {number} config.rejectCancelled - If true and request is set to cancellable, a cancelled request promise will be rejected. By default, instead of rejecting the promise, defaultResponse is returned.\n * @param {number} config.timeout - Request timeout\n * @param {number} config.dedupeTime - Time window, in milliseconds, during which identical requests are deduplicated (treated as single request).\n * @param {string} config.strategy - Error Handling Strategy\n * @param {string} config.flattenResponse - Whether to flatten response \"data\" object within \"data\". It works only if the response structure includes a single data property.\n * @param {*} config.defaultResponse - Default response when there is no data or when endpoint fails depending on the chosen strategy. It's \"null\" by default\n * @param {Object} [config.retry] - Options for retrying requests.\n * @param {number} [config.retry.retries=0] - Number of retry attempts. No retries by default.\n * @param {number} [config.retry.delay=1000] - Initial delay between retries in milliseconds.\n * @param {number} [config.retry.backoff=1.5] - Exponential backoff factor.\n * @param {number[]} [config.retry.retryOn=[502, 504, 408]] - HTTP status codes to retry on.\n * @param {RequestInterceptor|RequestInterceptor[]} [config.onRequest] - Optional request interceptor function or an array of functions.\n * These functions will be called with the request configuration object before the request is made. Can be used to modify or log the request configuration.\n * @param {ResponseInterceptor|ResponseInterceptor[]} [config.onResponse] - Optional response interceptor function or an array of functions.\n * These functions will be called with the response object after the response is received. an be used to modify or log the response data.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Object} config.fetcher - The Custom Fetcher instance to use for making requests. It should expose create() and request() functions.\n * @param {*} config.logger - Instance of custom logger. Either class or an object similar to \"console\". Console is used by default.\n * @returns API handler functions and endpoints to call\n *\n * @example\n * // Define endpoint paths\n * const endpoints = {\n * getUser: '/user',\n * createPost: '/post',\n * };\n *\n * // Create the API fetcher with configuration\n * const api = createApiFetcher({\n * endpoints,\n * apiUrl: 'https://example.com/api',\n * onError(error) {\n * console.log('Request failed', error);\n * },\n * headers: {\n * 'my-auth-key': 'example-auth-key-32rjjfa',\n * },\n * });\n *\n * // Fetch user data\n * const response = await api.getUser({ userId: 1, ratings: [1, 2] })\n */\nfunction createApiFetcher<\n EndpointsMethods extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n const requestHandler = createRequestHandler(config);\n\n /**\n * Get Custom Fetcher Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Request Handler's Custom Fetcher Instance\n */\n function getInstance(): CreatedCustomFetcherInstance | null {\n return requestHandler.getInstance();\n }\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n function handleNonImplemented(endpointName: string): Promise {\n console.error(`Add ${endpointName} to 'endpoints'.`);\n\n return Promise.resolve(null);\n }\n\n /**\n * Handle Single API Request\n * It considers settings in following order: per-request settings, global per-endpoint settings, global settings.\n *\n * @param {keyof EndpointsMethods | string} endpointName - The name of the API endpoint to call.\n * @param {EndpointConfig} [requestConfig={}] - Additional configuration for the request.\n * @returns {Promise>} - A promise that resolves with the response from the API provider.\n */\n async function request<\n ResponseData = never,\n QueryParams_ = never,\n UrlParams = never,\n RequestBody = never,\n >(\n endpointName: keyof EndpointsMethods | string,\n requestConfig: RequestConfig<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n > = {},\n ): Promise>> {\n // Use global per-endpoint settings\n const endpointConfig =\n endpoints[endpointName] ||\n ({ url: endpointName as string } as RequestConfigUrlRequired);\n\n const responseData = await requestHandler.request<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n >(endpointConfig.url, {\n ...endpointConfig,\n ...requestConfig,\n });\n\n return responseData;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\n requestHandler,\n getInstance,\n request,\n };\n\n /**\n * Maps all API requests using native Proxy\n *\n * @param {*} prop Caller\n */\n return new Proxy>(\n apiHandler as ApiHandlerMethods,\n {\n get(_target, prop: string) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n","import { createRequestHandler } from './request-handler';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestHandlerConfig,\n} from './types';\n\n/**\n * Simple wrapper for request fetching.\n * It abstracts the creation of RequestHandler, making it easy to perform API requests.\n *\n * @param {string | URL | globalThis.Request} url - Request URL.\n * @param {RequestHandlerConfig} config - Configuration object for the request handler.\n * @returns {Promise>} Response Data.\n */\nexport async function fetchf(\n url: string,\n config: RequestHandlerConfig = {},\n): Promise> {\n return createRequestHandler(config).request(url, config);\n}\n\nexport * from './types';\nexport * from './api-handler';\n"],"mappings":"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","names":["applyInterceptor","object","interceptors","value","interceptor","ResponseErr","message","requestInfo","response","__publicField","APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","ABORT_ERROR","TIMEOUT_ERROR","CANCELLED_ERROR","GET","HEAD","isSearchParams","data","shallowSerialize","obj","result","key","sortObject","sortedObj","keys","i","len","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","isSearchParams","encodedQueryString","s","encode","add","k","v","buildParams","prefix","OBJECT","replaceUrlPathParams","urlPathParams","str","word","isJSONSerializable","value","UNDEFINED","STRING","proto","delayInvocation","ms","resolve","flattenData","data","processHeaders","headers","headersObject","deleteProperty","property","queue","addRequest","config","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","previousController","timeoutId","ABORT_ERROR","controller","error","TIMEOUT_ERROR","removeRequest","parseResponseData","response","_a","contentType","CONTENT_TYPE","data","APPLICATION_JSON","APPLICATION_CONTENT_TYPE","_e","_error","hash","str","i","len","char","cache","generateCacheKey","options","url","method","GET","headers","body","mode","credentials","redirect","referrer","integrity","headersString","shallowSerialize","sortObject","bodyString","hash","value","key","UNDEFINED","o","OBJECT","isCacheExpired","timestamp","maxStaleTime","getCache","cacheTime","entry","setCache","data","isLoading","defaultConfig","GET","APPLICATION_JSON","CONTENT_TYPE","createRequestHandler","config","handlerConfig","mergeConfig","property","targetConfig","baseConfig","newConfig","getConfig","reqConfig","name","UNDEFINED","customFetcher","requestInstance","getInstance","logger","args","buildConfig","url","requestConfig","method","isGetAlikeMethod","HEAD","dynamicUrl","replaceUrlPathParams","explicitParams","explicitBodyData","body","credentials","urlPath","appendQueryParams","baseURL","STRING","isSearchParams","isJSONSerializable","processError","error","isRequestCancelled","applyInterceptor","outputErrorResponse","response","_isRequestCancelled","errorHandlingStrategy","rejectCancelled","outputResponse","ABORT_ERROR","CANCELLED_ERROR","request","_a","_reqConfig","mergedConfig","fetcherConfig","timeout","cancellable","dedupeTime","pollingInterval","shouldStopPolling","cacheTime","cacheKey","_cacheKey","generateCacheKey","cacheBuster","cachedEntry","getCache","retries","delay","backoff","retryOn","shouldRetry","maxDelay","resetTimeout","attempt","pollingAttempt","waitTime","_retries","addRequest","parseResponseData","ResponseErr","removeRequest","delayInvocation","output","skipCache","setCache","err","status","defaultResponse","deleteProperty","data","OBJECT","flattenData","processHeaders","createApiFetcher","config","endpoints","requestHandler","createRequestHandler","getInstance","handleNonImplemented","endpointName","request","requestConfig","endpointConfig","apiHandler","_target","prop","fetchf","url","config","createRequestHandler"]} \ No newline at end of file diff --git a/dist/node/index.js b/dist/node/index.js index 45ccec3..34bb893 100644 --- a/dist/node/index.js +++ b/dist/node/index.js @@ -1,2 +1,2 @@ -"use strict";var Y=Object.defineProperty;var Te=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var Oe=(e,t)=>{for(var n in t)Y(e,n,{get:t[n],enumerable:!0})},xe=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of be(t))!we.call(e,a)&&a!==n&&Y(e,a,{get:()=>t[a],enumerable:!(s=Te(t,a))||s.enumerable});return e};var qe=e=>xe(Y({},"__esModule",{value:!0}),e);var He={};Oe(He,{createApiFetcher:()=>Ae,fetchf:()=>Ne});module.exports=qe(He);async function T(e,t){if(t){if(typeof t=="function"){let n=await t(e);n&&Object.assign(e,n)}else if(Array.isArray(t))for(let n of t){let s=await n(e);s&&Object.assign(e,s)}}}var B=class extends Error{response;request;config;status;statusText;constructor(t,n,s){super(t),this.name="ResponseError",this.message=t,this.status=s.status,this.statusText=s.statusText,this.request=n,this.config=n,this.response=s}};var k="application/",I=k+"json",M="Content-Type",E="undefined",C="object",Q="string",L="AbortError",se="TimeoutError",oe="CanceledError",A="GET",ae="HEAD";function K(e){return e instanceof URLSearchParams}function le(e){let t="";for(let n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t+=n+":"+e[n]);return t}function V(e){let t={},n=Object.keys(e);n.sort();for(let s=0,a=n.length;s{o=typeof o=="function"?o():o,o=o===null||o===void 0?"":o,n[n.length]=s(c)+"="+s(o)},l=(c,o)=>{let f,h,d;if(c)if(Array.isArray(o))for(f=0,h=o.length;f{let s=n.substring(1);return t[s]?String(t[s]):n}):e}function fe(e){let t=typeof e;if(t===E||e===null)return!1;if(t===Q||t==="number"||t==="boolean"||Array.isArray(e))return!0;if(Buffer.isBuffer(e)||e instanceof Date)return!1;if(t===C){let n=Object.getPrototypeOf(e);if(n===Object.prototype||n===null||typeof e.toJSON=="function")return!0}return!1}async function W(e){return new Promise(t=>setTimeout(()=>t(!0),e))}function X(e){return e&&typeof e===C&&typeof e.data!==E&&Object.keys(e).length===1?X(e.data):e}function pe(e){if(!e)return{};let t={};if(e instanceof Headers)e.forEach((n,s)=>{t[s]=n});else if(typeof e===C&&e!==null)for(let[n,s]of Object.entries(e))t[n.toLowerCase()]=s;return t}function v(e,t){e&&t in e&&delete e[t]}var N=new Map;async function de(e,t,n=0,s=!1,a=!0){let l=Date.now(),R=N.get(e);if(R){let o=R[3],f=R[0],h=R[1];if(!o&&l-R[2]{let o=new DOMException(`${e.url} aborted due to timeout`,se);j(e,o)},t):null;return N.set(e,[y,c,l,s]),y}async function j(e,t=null){let n=N.get(e);if(n){let s=n[0],a=n[1];t&&!s.signal.aborted&&s.abort(t),a!==null&&clearTimeout(a),N.delete(e)}}async function Re(e){if(!e?.body)return null;let t=String(e.headers?.get(M)||"").split(";")[0],n;try{if(t.includes(I)||t.includes("+json"))n=await e.json();else if(t.includes("multipart/form-data"))n=await e.formData();else if(t.includes(k+"octet-stream"))n=await e.blob();else if(t.includes(k+"x-www-form-urlencoded"))n=await e.formData();else if(t.includes("text/"))n=await e.text();else try{n=await e.clone().json()}catch{n=await e.text()}}catch{n=null}return n}function J(e){let t=0;for(let n=0,s=e.length;n{d+=u+"="+r+"&"}),d=J(d);else if(typeof Blob!==E&&a instanceof Blob||typeof File!==E&&a instanceof File)d="BF"+a.size+a.type;else if(a instanceof ArrayBuffer||ArrayBuffer.isView(a))d="AB"+a.byteLength;else{let r=typeof a===C?V(a):String(a);d=J(JSON.stringify(r))}return n+t+l+R+y+c+o+f+h+d}function Fe(e,t){return t?Date.now()-e>t*1e3:!1}function ye(e,t){let n=Z.get(e);if(n){if(!Fe(n.timestamp,t))return n;Z.delete(e)}return null}function ge(e,t,n=!1){Z.set(e,{data:t,isLoading:n,timestamp:Date.now()})}var Ie={method:A,strategy:"reject",timeout:3e4,dedupeTime:1e3,defaultResponse:null,headers:{Accept:I+", text/plain, */*","Accept-Encoding":"gzip, deflate, br",[M]:I+";charset=utf-8"},retry:{delay:1e3,maxDelay:3e4,resetTimeout:!0,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function $(e){let t={...Ie,...e},n=t.fetcher,s=n?.create(t)||null,a=()=>s,l=(r,u)=>typeof r[u]!==E?r[u]:t[u],R=(...r)=>{t.logger?.warn&&t.logger.warn(...r)},y=(r,u)=>{let m=l(u,"method").toUpperCase(),P=m===A||m===ae,i=ce(r,l(u,"urlPathParams")),g=l(u,"params"),H=l(u,"body")||l(u,"data"),D;P||(D=H);let U=l(u,"withCredentials")?"include":l(u,"credentials"),w=g?ue(i,g):i,_=w.includes("://")?"":l(u,"baseURL")||l(u,"apiUrl");return D&&typeof D!==Q&&!K(D)&&fe(D)&&(D=JSON.stringify(D)),{...u,credentials:U,body:D,method:m,url:_+w}},c=async(r,u)=>{f(r)||R("API ERROR",r),await T(r,u?.onError),await T(r,t?.onError)},o=async(r,u,m)=>{let P=f(r),i=l(m,"strategy"),g=l(m,"rejectCancelled");if(!(P&&!g)){if(i==="silent")await new Promise(()=>null);else if(i==="reject")return Promise.reject(r)}return d(u,m,r)},f=r=>r.name===L||r.name===oe,h=async(r,u=null)=>{let m=u||{},P={...t,...m},i=null,g=y(r,P),{timeout:H,cancellable:D,dedupeTime:ee,pollingInterval:U,shouldStopPolling:w,cacheTime:S,cacheKey:_}=P,b;if(_?b=_(g):b=me(g),S&&b){let q=P.cacheBuster;if(!q||!q(g)){let p=ye(b,S);if(p)return p.data}}let{retries:G=0,delay:he,backoff:Pe,retryOn:De,shouldRetry:te,maxDelay:Ce,resetTimeout:Ee}=P.retry,O=0,z=0,x=he,ne=G>0?G:0;for(;O<=ne;)try{let p={signal:(await de(g,H,ee,D,!!(H&&(!ne||Ee)))).signal,...g};if(await T(p,m?.onRequest),await T(p,t?.onRequest),n!==null&&s!==null?i=await s.request(p):i=await fetch(p.url,p),i instanceof Response&&(i.config=p,i.data=await Re(i),!i.ok))throw new B(`${p.url} failed! Status: ${i.status||null}`,p,i);if(await T(i,m?.onResponse),await T(i,t?.onResponse),j(g),U&&(!w||!w(i,z))){z++,R(`Polling attempt ${z}...`),await W(U);continue}let F=d(i,p);if(S&&b){let re=p.skipCache;(!re||!re(F,p))&&ge(b,F)}return F}catch(q){let p=q,F=p?.response?.status||p?.status||0;if(O===G||!(!te||await te(p,O))||!De?.includes(F))return await c(p,g),j(g),o(p,i,g);R(`Attempt ${O+1} failed. Retry in ${x}ms.`),await W(x),x*=Pe,x=Math.min(x,Ce),O++}return d(i,g)},d=(r,u,m=null)=>{let P=l(u,"defaultResponse");if(!r)return{ok:!1,error:m,data:P,headers:null,config:u};v(m,"response"),v(m,"request"),v(m,"config");let i=r?.data;return(i==null||typeof i===C&&Object.keys(i).length===0)&&(i=P),l(u,"flattenResponse")&&(r.data=X(i)),r instanceof Response?{body:r.body,bodyUsed:r.bodyUsed,formData:r.formData,ok:r.ok,redirected:r.redirected,type:r.type,url:r.url,status:r.status,statusText:r.statusText,blob:r.blob.bind(r),json:r.json.bind(r),text:r.text.bind(r),clone:r.clone.bind(r),arrayBuffer:r.arrayBuffer.bind(r),error:m,data:i,headers:pe(r.headers),config:u}:r};return{getInstance:a,buildConfig:y,config:e,request:h}}function Ae(e){let t=e.endpoints,n=$(e);function s(){return n.getInstance()}function a(y){return console.error(`Add ${y} to 'endpoints'.`),Promise.resolve(null)}async function l(y,c={}){let o=t[y]||{url:y};return await n.request(o.url,{...o,...c})}let R={config:e,endpoints:t,requestHandler:n,getInstance:s,request:l};return new Proxy(R,{get(y,c){return c in R?R[c]:t[c]?R.request.bind(null,c):a.bind(null,c)}})}async function Ne(e,t={}){return $(t).request(e,t)}0&&(module.exports={createApiFetcher,fetchf}); +"use strict";var Y=Object.defineProperty;var qe=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var xe=Object.prototype.hasOwnProperty;var Oe=(e,t)=>{for(var n in t)Y(e,n,{get:t[n],enumerable:!0})},Fe=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of we(t))!xe.call(e,o)&&o!==n&&Y(e,o,{get:()=>t[o],enumerable:!(r=qe(t,o))||r.enumerable});return e};var Ie=e=>Fe(Y({},"__esModule",{value:!0}),e);var Ue={};Oe(Ue,{createApiFetcher:()=>He,fetchf:()=>Ne});module.exports=Ie(Ue);async function b(e,t){if(t){if(typeof t=="function"){let n=await t(e);n&&Object.assign(e,n)}else if(Array.isArray(t))for(let n of t){let r=await n(e);r&&Object.assign(e,r)}}}var B=class extends Error{response;request;config;status;statusText;constructor(t,n,r){super(t),this.name="ResponseError",this.message=t,this.status=r.status,this.statusText=r.statusText,this.request=n,this.config=n,this.response=r}};var M="application/",A=M+"json",Q="Content-Type",E="undefined",C="object",L="string",v="AbortError",ae="TimeoutError",ie="CanceledError",H="GET",le="HEAD";function V(e){return e instanceof URLSearchParams}function ce(e){let t="";for(let n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t+=n+":"+e[n]);return t}function W(e){let t={},n=Object.keys(e);n.sort();for(let r=0,o=n.length;r{a=typeof a=="function"?a():a,a=a===null||a===void 0?"":a,n[n.length]=r(c)+"="+r(a)},d=(c,a)=>{let p,P,m;if(c)if(Array.isArray(a))for(p=0,P=a.length;p{let r=n.substring(1);return t[r]?String(t[r]):n}):e}function de(e){let t=typeof e;if(t===E||e===null)return!1;if(t===L||t==="number"||t==="boolean"||Array.isArray(e))return!0;if(Buffer.isBuffer(e)||e instanceof Date)return!1;if(t===C){let n=Object.getPrototypeOf(e);if(n===Object.prototype||n===null||typeof e.toJSON=="function")return!0}return!1}async function X(e){return new Promise(t=>setTimeout(()=>t(!0),e))}function Z(e){return e&&typeof e===C&&typeof e.data!==E&&Object.keys(e).length===1?Z(e.data):e}function Re(e){if(!e)return{};let t={};if(e instanceof Headers)e.forEach((n,r)=>{t[r]=n});else if(typeof e===C&&e!==null)for(let[n,r]of Object.entries(e))t[n.toLowerCase()]=r;return t}function j(e,t){e&&t in e&&delete e[t]}var N=new Map;async function me(e,t,n=0,r=!1,o=!0){let d=Date.now(),h=N.get(e);if(h){let a=h[3],p=h[0],P=h[1];if(!a&&d-h[2]{let a=new DOMException(`${e.url} aborted due to timeout`,ae);J(e,a)},t):null;return N.set(e,[R,c,d,r]),R}async function J(e,t=null){let n=N.get(e);if(n){let r=n[0],o=n[1];t&&!r.signal.aborted&&r.abort(t),o!==null&&clearTimeout(o),N.delete(e)}}async function ye(e){if(!e?.body)return null;let t=String(e.headers?.get(Q)||"").split(";")[0],n;try{if(t.includes(A)||t.includes("+json"))n=await e.json();else if(t.includes("multipart/form-data"))n=await e.formData();else if(t.includes(M+"octet-stream"))n=await e.blob();else if(t.includes(M+"x-www-form-urlencoded"))n=await e.formData();else if(t.includes("text/"))n=await e.text();else try{n=await e.clone().json()}catch{n=await e.text()}}catch{n=null}return n}function $(e){let t=0;for(let n=0,r=e.length;n{m+=s+"="+T+"&"}),m=$(m);else if(typeof Blob!==E&&o instanceof Blob||typeof File!==E&&o instanceof File)m="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))m="AB"+o.byteLength;else{let T=typeof o===C?W(o):String(o);m=$(JSON.stringify(T))}return n+t+d+h+R+c+a+p+P+m}function Ae(e,t){return t?Date.now()-e>t*1e3:!1}function he(e,t){let n=ee.get(e);if(n){if(!Ae(n.timestamp,t))return n;ee.delete(e)}return null}function Pe(e,t,n=!1){ee.set(e,{data:t,isLoading:n,timestamp:Date.now()})}var te={method:H,strategy:"reject",timeout:3e4,dedupeTime:1e3,defaultResponse:null,headers:{Accept:A+", text/plain, */*","Accept-Encoding":"gzip, deflate, br",[Q]:A+";charset=utf-8"},retry:{delay:1e3,maxDelay:3e4,resetTimeout:!0,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function G(e){let t={...te,...e},n=(s,i,u,y)=>{y[s]&&(i[s]={...u[s],...y[s]})};n("retry",t,te,e),n("headers",t,te,e);let r=(s,i)=>typeof s[i]!==E?s[i]:t[i],o=r(e,"fetcher"),d=o?.create(t)||null,h=()=>d,R=(s,...i)=>{let u=r(s,"logger");u?.warn&&u.warn(...i)},c=(s,i)=>{let u=r(i,"method").toUpperCase(),y=u===H||u===le,l=pe(s,r(i,"urlPathParams")),g=r(i,"params"),U=r(i,"body")||r(i,"data"),D;y||(D=U);let S=r(i,"withCredentials")?"include":r(i,"credentials"),w=g?fe(l,g):l,k=w.includes("://")?"":r(i,"baseURL")||r(i,"apiUrl");return D&&typeof D!==L&&!V(D)&&de(D)&&(D=JSON.stringify(D)),{...i,credentials:S,body:D,method:u,url:k+w}},a=async(s,i)=>{P(s)||R(i,"API ERROR",s),await b(s,i?.onError),await b(s,t?.onError)},p=async(s,i,u)=>{let y=P(s),l=r(u,"strategy"),g=r(u,"rejectCancelled");if(!(y&&!g)){if(l==="silent")await new Promise(()=>null);else if(l==="reject")return Promise.reject(s)}return T(i,u,s)},P=s=>s.name===v||s.name===ie,m=async(s,i=null)=>{let u=i||{},y={...t,...u};n("retry",y,t,u),n("headers",y,t,u);let l=null,g=c(s,y),{timeout:U,cancellable:D,dedupeTime:ne,pollingInterval:S,shouldStopPolling:w,cacheTime:_,cacheKey:k}=y,q;if(k?q=k(g):q=ge(g),_&&q){let F=y.cacheBuster;if(!F||!F(g)){let f=he(q,_);if(f)return f.data}}let{retries:z=0,delay:De,backoff:Ce,retryOn:Ee,shouldRetry:re,maxDelay:Te,resetTimeout:be}=y.retry,x=0,K=0,O=De,se=z>0?z:0;for(;x<=se;)try{let f={signal:(await me(g,U,ne,D,!!(U&&(!se||be)))).signal,...g};if(await b(f,u?.onRequest),await b(f,t?.onRequest),o!==null&&d!==null?l=await d.request(f):l=await fetch(f.url,f),l instanceof Response&&(l.config=f,l.data=await ye(l),!l.ok))throw new B(`${f.url} failed! Status: ${l.status||null}`,f,l);if(await b(l,u?.onResponse),await b(l,t?.onResponse),J(g),S&&(!w||!w(l,K))){K++,R(f,"Polling attempt "+K+"..."),await X(S);continue}let I=T(l,f);if(_&&q){let oe=f.skipCache;(!oe||!oe(I,f))&&Pe(q,I)}return I}catch(F){let f=F,I=f?.response?.status||f?.status||0;if(x===z||!(!re||await re(f,x))||!Ee?.includes(I))return await a(f,g),J(g),p(f,l,g);R(y,`Attempt ${x+1} failed. Retry in ${O}ms.`),await X(O),O*=Ce,O=Math.min(O,Te),x++}return T(l,g)},T=(s,i,u=null)=>{let y=r(i,"defaultResponse");if(!s)return{ok:!1,error:u,data:y,headers:null,config:i};j(u,"response"),j(u,"request"),j(u,"config");let l=s?.data;return(l==null||typeof l===C&&Object.keys(l).length===0)&&(l=y),r(i,"flattenResponse")&&(s.data=Z(l)),s instanceof Response?{body:s.body,bodyUsed:s.bodyUsed,formData:s.formData,ok:s.ok,redirected:s.redirected,type:s.type,url:s.url,status:s.status,statusText:s.statusText,blob:s.blob.bind(s),json:s.json.bind(s),text:s.text.bind(s),clone:s.clone.bind(s),arrayBuffer:s.arrayBuffer.bind(s),error:u,data:l,headers:Re(s.headers),config:i}:s};return{getInstance:h,buildConfig:c,config:e,request:m}}function He(e){let t=e.endpoints,n=G(e);function r(){return n.getInstance()}function o(R){return console.error(`Add ${R} to 'endpoints'.`),Promise.resolve(null)}async function d(R,c={}){let a=t[R]||{url:R};return await n.request(a.url,{...a,...c})}let h={config:e,endpoints:t,requestHandler:n,getInstance:r,request:d};return new Proxy(h,{get(R,c){return c in h?h[c]:t[c]?h.request.bind(null,c):o.bind(null,c)}})}async function Ne(e,t={}){return G(t).request(e,t)}0&&(module.exports={createApiFetcher,fetchf}); //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/node/index.js.map b/dist/node/index.js.map index 72e205d..51399e7 100644 --- a/dist/node/index.js.map +++ b/dist/node/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/index.ts","../../src/interceptor-manager.ts","../../src/response-error.ts","../../src/constants.ts","../../src/utils.ts","../../src/queue-manager.ts","../../src/response-parser.ts","../../src/hash.ts","../../src/cache-manager.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"sourcesContent":["import { createRequestHandler } from './request-handler';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestHandlerConfig,\n} from './types';\n\n/**\n * Simple wrapper for request fetching.\n * It abstracts the creation of RequestHandler, making it easy to perform API requests.\n *\n * @param {string | URL | globalThis.Request} url - Request URL.\n * @param {RequestHandlerConfig} config - Configuration object for the request handler.\n * @returns {Promise>} Response Data.\n */\nexport async function fetchf(\n url: string,\n config: RequestHandlerConfig = {},\n): Promise> {\n return createRequestHandler(config).request(url, config);\n}\n\nexport * from './types';\nexport * from './api-handler';\n","type InterceptorFunction = (object: T) => Promise;\n\n/**\n * Applies interceptors to the object. Interceptors can be a single function or an array of functions.\n *\n * @template T - Type of the object.\n * @template I - Type of interceptors.\n *\n * @param {T} object - The object to process.\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptor<\n T extends object,\n I = InterceptorFunction | InterceptorFunction[],\n>(object: T, interceptors?: I): Promise {\n if (!interceptors) {\n return;\n }\n\n if (typeof interceptors === 'function') {\n const value = await interceptors(object);\n\n if (value) {\n Object.assign(object, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(object);\n\n if (value) {\n Object.assign(object, value);\n }\n }\n }\n}\n","import type { FetchResponse, RequestConfig } from './types';\n\nexport class ResponseErr extends Error {\n response: FetchResponse;\n request: RequestConfig;\n config: RequestConfig;\n status: number;\n statusText: string;\n\n constructor(\n message: string,\n requestInfo: RequestConfig,\n response: FetchResponse,\n ) {\n super(message);\n\n this.name = 'ResponseError';\n this.message = message;\n this.status = response.status;\n this.statusText = response.statusText;\n this.request = requestInfo;\n this.config = requestInfo;\n this.response = response;\n }\n}\n","export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\nexport const CANCELLED_ERROR = 'CanceledError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\nexport function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const sortedObj = {} as Record;\n const keys = Object.keys(obj);\n\n keys.sort();\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === 'function' ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any) => {\n let i: number, len: number, key: string;\n\n if (prefix) {\n if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n buildParams(\n prefix + '[' + (typeof obj[i] === OBJECT && obj[i] ? i : '') + ']',\n obj[i],\n );\n }\n } else if (typeof obj === OBJECT && obj !== null) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key]);\n }\n } else {\n add(prefix, obj);\n }\n } else if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n add(obj[i].name, obj[i].value);\n }\n } else {\n for (key in obj) {\n buildParams(key, obj[key]);\n }\n }\n return s;\n };\n\n const queryStringParts = buildParams('', params).join('&');\n\n // Encode special characters as per RFC 3986, https://datatracker.ietf.org/doc/html/rfc3986\n const encodedQueryString = queryStringParts.replace(/%5B%5D/g, '[]'); // Keep '[]' for arrays\n\n return appendQueryStringToUrl(url, encodedQueryString);\n}\n\n/**\n * Replaces dynamic URI parameters in a URL string with values from the provided `urlPathParams` object.\n * Parameters in the URL are denoted by `:`, where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:`.\n * @param {Object} urlPathParams - An object containing the parameter values to replace placeholders.\n * @param {string} urlPathParams.paramName - The value to replace the placeholder `:` in the URL.\n * @returns {string} - The URL string with placeholders replaced by corresponding values from `urlPathParams`.\n */\nexport function replaceUrlPathParams(\n url: string,\n urlPathParams: UrlPathParams,\n): string {\n if (!urlPathParams) {\n return url;\n }\n\n return url.replace(/:\\w+/g, (str): string => {\n const word = str.substring(1);\n\n if ((urlPathParams as DefaultUrlParams)[word]) {\n return String((urlPathParams as DefaultUrlParams)[word]);\n }\n\n return str;\n });\n}\n\n/**\n * Checks if a value is JSON serializable.\n *\n * JSON serializable values include:\n * - Primitive types: string, number, boolean, null\n * - Arrays\n * - Plain objects (i.e., objects without special methods)\n * - Values with a `toJSON` method\n *\n * @param {any} value - The value to check for JSON serializability.\n * @returns {boolean} - Returns `true` if the value is JSON serializable, otherwise `false`.\n */\nexport function isJSONSerializable(value: any): boolean {\n const t = typeof value;\n\n if (t === UNDEFINED || value === null) {\n return false;\n }\n\n if (t === STRING || t === 'number' || t === 'boolean') {\n return true;\n }\n\n if (Array.isArray(value)) {\n return true;\n }\n\n if (Buffer.isBuffer(value)) {\n return false;\n }\n\n if (value instanceof Date) {\n return false;\n }\n\n if (t === OBJECT) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` or `null` (plain object)\n if (proto === Object.prototype || proto === null) {\n return true;\n }\n\n // Check if the object has a toJSON method\n if (typeof value.toJSON === 'function') {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any): any {\n if (\n data &&\n typeof data === OBJECT &&\n typeof data.data !== UNDEFINED &&\n Object.keys(data).length === 1\n ) {\n return flattenData(data.data);\n }\n\n return data;\n}\n\n/**\n * Processes headers and returns them as a normalized object.\n *\n * Handles both `Headers` instances and plain objects. Normalizes header keys to lowercase\n * as per RFC 2616 section 4.2.\n *\n * @param headers - The headers to process. Can be an instance of `Headers`, a plain object,\n * or `null`. If `null`, an empty object is returned.\n * @returns {HeadersObject} - A normalized headers object with lowercase keys.\n */\nexport function processHeaders(\n headers?: (HeadersObject & HeadersInit) | null | Headers,\n): HeadersObject {\n if (!headers) {\n return {};\n }\n\n const headersObject: HeadersObject = {};\n\n // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (typeof headers === OBJECT && headers !== null) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * Deletes a property from an object if it exists.\n *\n * @param obj - The object from which to delete the property.\n * @param property - The property to delete from the object.\n */\nexport function deleteProperty>(\n obj: T | null,\n property: keyof T,\n): void {\n if (obj && property in obj) {\n delete obj[property];\n }\n}\n","import { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport type { RequestConfig } from './types';\nimport type { QueueItem, RequestsQueue } from './types/queue-manager';\n\n/**\n * Queue Manager is responsible for managing and controlling the flow of concurrent or sequential requests. It handles:\n * - Request Queueing and Deduplication\n * - Request Timeout Handling\n * - Abort Controller Management and Request Cancellation\n * - Concurrency Control and Locking\n * - Request Lifecycle Management\n */\nconst queue: RequestsQueue = new Map();\n\n/**\n * Adds a request to the queue if it's not already being processed within the dedupeTime interval.\n *\n * @param {RequestConfig} config - The request configuration object.\n * @param {number} timeout - Timeout in milliseconds for the request.\n * @param {number} dedupeTime - Deduplication time in milliseconds.\n * @param {boolean} isCancellable - If true, then the previous request with same configuration should be aborted.\n * @param {boolean} isTimeoutEnabled - Whether timeout is enabled.\n * @returns {Promise} - A promise that resolves to an AbortController.\n */\nexport async function addRequest(\n config: RequestConfig,\n timeout: number | undefined,\n dedupeTime: number = 0,\n isCancellable: boolean = false,\n isTimeoutEnabled: boolean = true,\n): Promise {\n const now = Date.now();\n const item = queue.get(config);\n\n if (item) {\n const isCancellable = item[3];\n const previousController = item[0];\n const timeoutId = item[1];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (!isCancellable && now - item[2] < dedupeTime) {\n return previousController;\n }\n\n // If the request is too old, remove it and proceed to add a new one\n // Abort previous request, if applicable, and continue as usual\n if (isCancellable) {\n previousController.abort(\n new DOMException('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n\n const controller = new AbortController();\n\n const timeoutId = isTimeoutEnabled\n ? setTimeout(() => {\n const error = new DOMException(\n `${config.url} aborted due to timeout`,\n TIMEOUT_ERROR,\n );\n\n removeRequest(config, error);\n }, timeout)\n : null;\n\n queue.set(config, [controller, timeoutId, now, isCancellable]);\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param config - The request configuration.\n * @param {boolean} error - Error payload so to force the request to abort.\n */\nexport async function removeRequest(\n config: RequestConfig,\n error: DOMException | null | string = null,\n): Promise {\n const item = queue.get(config);\n\n if (item) {\n const controller = item[0];\n const timeoutId = item[1];\n\n // If the request is not yet aborted, abort it with the provided error\n if (error && !controller.signal.aborted) {\n controller.abort(error);\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n}\n\n/**\n * Gets the AbortController for a request configuration.\n *\n * @param config - The request configuration.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n config: RequestConfig,\n): Promise {\n const item = queue.get(config);\n\n return item?.[0];\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n} from './constants';\nimport type { DefaultResponse, FetchResponse } from './types/request-handler';\n\n/**\n * Parses the response data based on the Content-Type header.\n *\n * @param response - The Response object to parse.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData(\n response: FetchResponse,\n): Promise {\n // Bail early when body is empty\n if (!response?.body) {\n return null;\n }\n\n const contentType = String(\n (response as Response).headers?.get(CONTENT_TYPE) || '',\n ).split(';')[0]; // Correctly handle charset\n\n let data;\n\n try {\n if (\n contentType.includes(APPLICATION_JSON) ||\n contentType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (contentType.includes('multipart/form-data')) {\n data = await response.formData(); // Parse as FormData\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream')\n ) {\n data = await response.blob(); // Parse as blob\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded')\n ) {\n data = await response.formData(); // Handle URL-encoded forms\n } else if (contentType.includes('text/')) {\n data = await response.text(); // Parse as text\n } else {\n try {\n const responseClone = response.clone();\n\n // Handle edge case of no content type being provided... We assume JSON here.\n data = await responseClone.json();\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_e) {\n // Handle streams\n data = await response.text();\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n // Parsing failed, fallback to null\n data = null;\n }\n\n return data;\n}\n","const PRIME_MULTIPLIER = 31;\n\n/**\n * Computes a hash value for a given string using the variant of djb2 hash function.\n * This hash function is non-cryptographic and designed for speed.\n * @author Daniel J. Bernstein (of djb2)\n *\n * @param str Input string to hash\n * @returns {string} Hash\n */\nexport function hash(str: string): string {\n let hash = 0;\n\n for (let i = 0, len = str.length; i < len; i++) {\n const char = str.charCodeAt(i);\n hash = (hash * PRIME_MULTIPLIER + char) | 0;\n }\n\n return String(hash);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport { fetchf } from './index';\nimport type { FetcherConfig } from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, OBJECT, UNDEFINED } from './constants';\nimport { shallowSerialize, sortObject } from './utils';\n\nconst cache = new Map>();\n\n/**\n * Generates a cache key for a given URL and fetch options, ensuring that key factors\n * like method, headers, body, and other options are included in the cache key.\n * Headers and other objects are sorted by key to ensure consistent cache keys.\n *\n * @param options - The fetch options that may affect the request. The most important are:\n * @property {string} [method=\"GET\"] - The HTTP method (GET, POST, etc.).\n * @property {HeadersInit} [headers={}] - The request headers.\n * @property {BodyInit | null} [body=\"\"] - The body of the request (only for methods like POST, PUT).\n * @property {RequestMode} [mode=\"cors\"] - The mode for the request (e.g., cors, no-cors, include).\n * @property {RequestCredentials} [credentials=\"include\"] - Whether to include credentials like cookies.\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @property {RequestRedirect} [redirect=\"follow\"] - How to handle redirects (e.g., follow, error, manual).\n * @property {string} [referrer=\"\"] - The referrer URL to send with the request.\n * @property {string} [integrity=\"\"] - Subresource integrity value (a cryptographic hash for resource validation).\n * @returns {string} - A unique cache key based on the URL and request options. Empty if cache is to be burst.\n *\n * @example\n * const cacheKey = generateCacheKey({\n * url: 'https://api.example.com/data',\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'Alice' }),\n * mode: 'cors',\n * credentials: 'include',\n * });\n * console.log(cacheKey);\n */\nexport function generateCacheKey(options: FetcherConfig): string {\n const {\n url = '',\n method = GET,\n headers = {},\n body = '',\n mode = 'cors',\n credentials = 'include',\n cache = 'default',\n redirect = 'follow',\n referrer = '',\n integrity = '',\n } = options;\n\n // Bail early if cache should be burst\n if (cache === 'reload') {\n return '';\n }\n\n // Sort headers and body + convert sorted to strings for hashing purposes\n // Native serializer is on avg. 3.5x faster than a Fast Hash or FNV-1a\n const headersString = shallowSerialize(sortObject(headers));\n\n let bodyString = '';\n\n // In majority of cases we do not cache body\n if (body !== null) {\n if (typeof body === 'string') {\n bodyString = hash(body);\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n bodyString = hash(bodyString);\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = typeof body === OBJECT ? sortObject(body) : String(body);\n bodyString = hash(JSON.stringify(o));\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n return (\n method +\n url +\n mode +\n credentials +\n cache +\n redirect +\n referrer +\n integrity +\n headersString +\n bodyString\n );\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the maximum stale time.\n *\n * @param {number} timestamp - The timestamp of the cache entry.\n * @param {number} maxStaleTime - The maximum stale time in seconds.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(timestamp: number, maxStaleTime: number): boolean {\n if (!maxStaleTime) {\n return false;\n }\n\n return Date.now() - timestamp > maxStaleTime * 1000;\n}\n\n/**\n * Retrieves a cache entry if it exists and is not expired.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} cacheTime - Maximum time to cache entry.\n * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string,\n cacheTime: number,\n): CacheEntry | null {\n const entry = cache.get(key);\n\n if (entry) {\n if (!isCacheExpired(entry.timestamp, cacheTime)) {\n return entry;\n }\n\n cache.delete(key);\n }\n\n return null;\n}\n\n/**\n * Sets a new cache entry or updates an existing one.\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {boolean} isLoading - Indicates if the data is currently being fetched.\n */\nexport function setCache(\n key: string,\n data: T,\n isLoading: boolean = false,\n): void {\n cache.set(key, {\n data,\n isLoading,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Revalidates a cache entry by fetching fresh data and updating the cache.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @returns {Promise} - A promise that resolves when the revalidation is complete.\n */\nexport async function revalidate(\n key: string,\n config: FetcherConfig,\n): Promise {\n try {\n // Fetch fresh data\n const newData = await fetchf(config.url, {\n ...config,\n cache: 'reload',\n });\n\n setCache(key, newData);\n } catch (error) {\n console.error(`Error revalidating ${config.url}:`, error);\n\n // Rethrow the error to forward it\n throw error;\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n */\nexport function deleteCache(key: string): void {\n cache.delete(key);\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @param {T} newData - The new data to be cached.\n * @param {boolean} revalidateAfter - If true, triggers revalidation after mutation.\n */\nexport function mutate(\n key: string,\n config: FetcherConfig,\n newData: T,\n revalidateAfter: boolean = false,\n): void {\n setCache(key, newData);\n\n if (revalidateAfter) {\n revalidate(key, config);\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n DefaultResponse,\n RequestHandlerConfig,\n RequestConfig,\n Method,\n RetryOptions,\n FetchResponse,\n ResponseError,\n RequestHandlerReturnType,\n CreatedCustomFetcherInstance,\n FetcherConfig,\n} from './types/request-handler';\nimport type {\n BodyPayload,\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n QueryParams,\n} from './types/api-handler';\nimport { applyInterceptor } from './interceptor-manager';\nimport { ResponseErr } from './response-error';\nimport {\n appendQueryParams,\n isJSONSerializable,\n replaceUrlPathParams,\n delayInvocation,\n flattenData,\n processHeaders,\n deleteProperty,\n isSearchParams,\n} from './utils';\nimport { addRequest, removeRequest } from './queue-manager';\nimport {\n ABORT_ERROR,\n APPLICATION_JSON,\n CANCELLED_ERROR,\n CONTENT_TYPE,\n GET,\n HEAD,\n OBJECT,\n STRING,\n UNDEFINED,\n} from './constants';\nimport { parseResponseData } from './response-parser';\nimport { generateCacheKey, getCache, setCache } from './cache-manager';\n\nconst defaultConfig: RequestHandlerConfig = {\n method: GET,\n strategy: 'reject',\n timeout: 30000,\n dedupeTime: 1000,\n defaultResponse: null,\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n [CONTENT_TYPE]: APPLICATION_JSON + ';charset=utf-8',\n },\n retry: {\n delay: 1000,\n maxDelay: 30000,\n resetTimeout: true,\n backoff: 1.5,\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n retryOn: [\n 408, // Request Timeout\n 409, // Conflict\n 425, // Too Early\n 429, // Too Many Requests\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504, // Gateway Timeout\n ],\n },\n};\n\n/**\n * Create Request Handler\n *\n * @param {RequestHandlerConfig} config - Configuration object for the request handler\n * @returns {Object} An object with methods for handling requests\n */\nexport function createRequestHandler(\n config: RequestHandlerConfig,\n): RequestHandlerReturnType {\n const handlerConfig: RequestHandlerConfig = {\n ...defaultConfig,\n ...config,\n };\n\n /**\n * Immediately create instance of custom fetcher if it is defined\n */\n const customFetcher = handlerConfig.fetcher;\n const requestInstance = customFetcher?.create(handlerConfig) || null;\n\n /**\n * Get Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Provider's instance\n */\n const getInstance = (): CreatedCustomFetcherInstance | null => {\n return requestInstance;\n };\n\n /**\n * Gets a configuration value from `reqConfig`, defaulting to `handlerConfig` if not present.\n *\n * @param {RequestConfig} reqConfig - Request configuration object.\n * @param {keyof RequestConfig} name - Key of the configuration value.\n * @returns {T} - The configuration value.\n */\n const getConfig = (\n reqConfig: RequestConfig,\n name: keyof RequestConfig,\n ): T => {\n return typeof reqConfig[name] !== UNDEFINED\n ? reqConfig[name]\n : handlerConfig[name];\n };\n\n /**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\n const logger = (...args: (string | ResponseError)[]): void => {\n if (handlerConfig.logger?.warn) {\n handlerConfig.logger.warn(...args);\n }\n };\n\n /**\n * Build request configuration\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @returns {RequestConfig} - Provider's instance\n */\n const buildConfig = (\n url: string,\n reqConfig: RequestConfig,\n ): FetcherConfig => {\n const method = getConfig(\n reqConfig,\n 'method',\n ).toUpperCase() as Method;\n const isGetAlikeMethod = method === GET || method === HEAD;\n\n const dynamicUrl = replaceUrlPathParams(\n url,\n getConfig(reqConfig, 'urlPathParams'),\n );\n\n // The explicitly passed \"params\"\n const explicitParams = getConfig(reqConfig, 'params');\n\n // The explicitly passed \"body\" or \"data\"\n const explicitBodyData: BodyPayload =\n getConfig(reqConfig, 'body') || getConfig(reqConfig, 'data');\n\n // Final body data\n let body: RequestConfig['data'];\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (!isGetAlikeMethod) {\n body = explicitBodyData;\n }\n\n // Native fetch compatible settings\n const isWithCredentials = getConfig(reqConfig, 'withCredentials');\n\n const credentials = isWithCredentials\n ? 'include'\n : getConfig(reqConfig, 'credentials');\n\n const urlPath = explicitParams\n ? appendQueryParams(dynamicUrl, explicitParams)\n : dynamicUrl;\n const isFullUrl = urlPath.includes('://');\n const baseURL = isFullUrl\n ? ''\n : getConfig(reqConfig, 'baseURL') ||\n getConfig(reqConfig, 'apiUrl');\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (\n body &&\n typeof body !== STRING &&\n !isSearchParams(body) &&\n isJSONSerializable(body)\n ) {\n body = JSON.stringify(body);\n }\n\n return {\n ...reqConfig,\n credentials,\n body,\n method,\n\n url: baseURL + urlPath,\n };\n };\n\n /**\n * Process global Request Error\n *\n * @param {ResponseError} error Error instance\n * @param {RequestConfig} requestConfig Per endpoint request config\n * @returns {Promise}\n */\n const processError = async (\n error: ResponseError,\n requestConfig: RequestConfig,\n ): Promise => {\n if (!isRequestCancelled(error)) {\n logger('API ERROR', error);\n }\n\n // Local interceptors\n await applyInterceptor(error, requestConfig?.onError);\n\n // Global interceptors\n await applyInterceptor(error, handlerConfig?.onError);\n };\n\n /**\n * Output default response in case of an error, depending on chosen strategy\n *\n * @param {ResponseError} error - Error instance\n * @param {FetchResponse | null} response - Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Per endpoint request config\n * @returns {FetchResponse} Response together with the error object\n */\n const outputErrorResponse = async (\n error: ResponseError,\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n ): Promise => {\n const _isRequestCancelled = isRequestCancelled(error);\n const errorHandlingStrategy = getConfig(requestConfig, 'strategy');\n const rejectCancelled = getConfig(\n requestConfig,\n 'rejectCancelled',\n );\n\n // By default cancelled requests aren't rejected (softFail strategy)\n if (!(_isRequestCancelled && !rejectCancelled)) {\n // Hang the promise\n if (errorHandlingStrategy === 'silent') {\n await new Promise(() => null);\n }\n // Reject the promise\n else if (errorHandlingStrategy === 'reject') {\n return Promise.reject(error);\n }\n }\n\n return outputResponse(response, requestConfig, error);\n };\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {ResponseError} error Error instance\n * @returns {boolean} True if request is aborted\n */\n const isRequestCancelled = (error: ResponseError): boolean => {\n return error.name === ABORT_ERROR || error.name === CANCELLED_ERROR;\n };\n\n /**\n * Handle Request depending on used strategy\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config\n * @throws {ResponseError}\n * @returns {Promise>} Response Data\n */\n const request = async <\n ResponseData = DefaultResponse,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n RequestBody = DefaultPayload,\n >(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n ): Promise> => {\n const _reqConfig = reqConfig || {};\n const mergedConfig = {\n ...handlerConfig,\n ..._reqConfig,\n } as RequestConfig;\n\n let response: FetchResponse | null = null;\n const fetcherConfig = buildConfig(url, mergedConfig);\n\n const {\n timeout,\n cancellable,\n dedupeTime,\n pollingInterval,\n shouldStopPolling,\n cacheTime,\n cacheKey,\n } = mergedConfig;\n\n // Prevent performance overhead of cache access\n let _cacheKey: string;\n\n if (cacheKey) {\n _cacheKey = cacheKey(fetcherConfig);\n } else {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n if (cacheTime && _cacheKey) {\n const cacheBuster = mergedConfig.cacheBuster;\n\n if (!cacheBuster || !cacheBuster(fetcherConfig)) {\n const cachedEntry = getCache>(\n _cacheKey,\n cacheTime,\n );\n\n if (cachedEntry) {\n // Serve stale data from cache\n return cachedEntry.data;\n }\n }\n }\n\n const {\n retries = 0,\n delay,\n backoff,\n retryOn,\n shouldRetry,\n maxDelay,\n resetTimeout,\n } = mergedConfig.retry as Required;\n\n let attempt = 0;\n let pollingAttempt = 0;\n let waitTime: number = delay;\n const _retries = retries > 0 ? retries : 0;\n\n while (attempt <= _retries) {\n try {\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = await addRequest(\n fetcherConfig,\n timeout,\n dedupeTime,\n cancellable,\n // Reset timeouts by default or when retries are ON\n !!(timeout && (!_retries || resetTimeout)),\n );\n\n // Shallow copy to ensure basic idempotency\n const requestConfig: RequestConfig = {\n signal: controller.signal,\n ...fetcherConfig,\n };\n\n // Local interceptors\n await applyInterceptor(requestConfig, _reqConfig?.onRequest);\n\n // Global interceptors\n await applyInterceptor(requestConfig, handlerConfig?.onRequest);\n\n if (customFetcher !== null && requestInstance !== null) {\n response = await requestInstance.request(requestConfig);\n } else {\n response = (await fetch(\n requestConfig.url as string,\n requestConfig as RequestInit,\n )) as FetchResponse;\n }\n\n // Add more information to response object\n if (response instanceof Response) {\n response.config = requestConfig;\n response.data = await parseResponseData(response);\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n if (!response.ok) {\n throw new ResponseErr(\n `${requestConfig.url} failed! Status: ${response.status || null}`,\n requestConfig,\n response,\n );\n }\n }\n\n // Local interceptors\n await applyInterceptor(response, _reqConfig?.onResponse);\n\n // Global interceptors\n await applyInterceptor(response, handlerConfig?.onResponse);\n\n removeRequest(fetcherConfig);\n\n // Polling logic\n if (\n pollingInterval &&\n (!shouldStopPolling || !shouldStopPolling(response, pollingAttempt))\n ) {\n // Restart the main retry loop\n pollingAttempt++;\n\n logger(`Polling attempt ${pollingAttempt}...`);\n\n await delayInvocation(pollingInterval);\n\n continue;\n }\n\n // If polling is not required, or polling attempts are exhausted\n const output = outputResponse(response, requestConfig);\n\n if (cacheTime && _cacheKey) {\n const skipCache = requestConfig.skipCache;\n\n if (!skipCache || !skipCache(output, requestConfig)) {\n setCache(_cacheKey, output);\n }\n }\n\n return output;\n } catch (err) {\n const error = err as ResponseErr;\n const status = error?.response?.status || error?.status || 0;\n\n if (\n attempt === retries ||\n !(!shouldRetry || (await shouldRetry(error, attempt))) ||\n !retryOn?.includes(status)\n ) {\n await processError(error, fetcherConfig);\n\n removeRequest(fetcherConfig);\n\n return outputErrorResponse(\n error,\n response,\n fetcherConfig,\n );\n }\n\n logger(`Attempt ${attempt + 1} failed. Retry in ${waitTime}ms.`);\n\n await delayInvocation(waitTime);\n\n waitTime *= backoff;\n waitTime = Math.min(waitTime, maxDelay);\n attempt++;\n }\n }\n\n return outputResponse(response, fetcherConfig);\n };\n\n /**\n * Output response\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\n const outputResponse = (\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n error: ResponseError | null = null,\n ): FetchResponse => {\n const defaultResponse = getConfig(requestConfig, 'defaultResponse');\n\n // This may happen when request is cancelled.\n if (!response) {\n return {\n ok: false,\n // Enhance the response with extra information\n error,\n data: defaultResponse,\n headers: null,\n config: requestConfig,\n } as unknown as FetchResponse;\n }\n\n // Clean up the error object\n deleteProperty(error, 'response');\n deleteProperty(error, 'request');\n deleteProperty(error, 'config');\n\n let data = response?.data;\n\n // Set the default response if the provided data is an empty object\n if (\n data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0)\n ) {\n data = defaultResponse;\n }\n\n // Return flattened response immediately\n const flattenResponse = getConfig(\n requestConfig,\n 'flattenResponse',\n );\n\n if (flattenResponse) {\n response.data = flattenData(data);\n }\n\n // If it's a custom fetcher, and it does not return any Response instance, it may have its own internal handler\n if (!(response instanceof Response)) {\n return response;\n }\n\n // Native fetch Response extended by extra information\n return {\n body: response.body,\n bodyUsed: response.bodyUsed,\n formData: response.formData,\n ok: response.ok,\n redirected: response.redirected,\n type: response.type,\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n\n blob: response.blob.bind(response),\n json: response.json.bind(response),\n text: response.text.bind(response),\n clone: response.clone.bind(response),\n arrayBuffer: response.arrayBuffer.bind(response),\n\n // Enhance the response with extra information\n error,\n data,\n headers: processHeaders(response.headers),\n config: requestConfig,\n };\n };\n\n return {\n getInstance,\n buildConfig,\n config,\n request,\n };\n}\n","import type {\n RequestConfig,\n FetchResponse,\n DefaultResponse,\n CreatedCustomFetcherInstance,\n} from './types/request-handler';\nimport type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n DefaultPayload,\n FallbackValue,\n FinalParams,\n FinalResponse,\n QueryParams,\n RequestConfigUrlRequired,\n UrlPathParams,\n} from './types/api-handler';\nimport { createRequestHandler } from './request-handler';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if it is passed as \"fetcher\".\n * @url https://github.com/MattCCC/fetchff\n *\n * @param {Object} config - Configuration object for the API fetcher.\n * @param {string} config.apiUrl - The base URL for the API.\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {number} config.timeout - You can set the timeout for particular request in milliseconds.\n * @param {number} config.cancellable - If true, the ongoing previous requests will be automatically cancelled.\n * @param {number} config.rejectCancelled - If true and request is set to cancellable, a cancelled request promise will be rejected. By default, instead of rejecting the promise, defaultResponse is returned.\n * @param {number} config.timeout - Request timeout\n * @param {number} config.dedupeTime - Time window, in milliseconds, during which identical requests are deduplicated (treated as single request).\n * @param {string} config.strategy - Error Handling Strategy\n * @param {string} config.flattenResponse - Whether to flatten response \"data\" object within \"data\". It works only if the response structure includes a single data property.\n * @param {*} config.defaultResponse - Default response when there is no data or when endpoint fails depending on the chosen strategy. It's \"null\" by default\n * @param {Object} [config.retry] - Options for retrying requests.\n * @param {number} [config.retry.retries=0] - Number of retry attempts. No retries by default.\n * @param {number} [config.retry.delay=1000] - Initial delay between retries in milliseconds.\n * @param {number} [config.retry.backoff=1.5] - Exponential backoff factor.\n * @param {number[]} [config.retry.retryOn=[502, 504, 408]] - HTTP status codes to retry on.\n * @param {RequestInterceptor|RequestInterceptor[]} [config.onRequest] - Optional request interceptor function or an array of functions.\n * These functions will be called with the request configuration object before the request is made. Can be used to modify or log the request configuration.\n * @param {ResponseInterceptor|ResponseInterceptor[]} [config.onResponse] - Optional response interceptor function or an array of functions.\n * These functions will be called with the response object after the response is received. an be used to modify or log the response data.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Object} config.fetcher - The Custom Fetcher instance to use for making requests. It should expose create() and request() functions.\n * @param {*} config.logger - Instance of custom logger. Either class or an object similar to \"console\". Console is used by default.\n * @returns API handler functions and endpoints to call\n *\n * @example\n * // Define endpoint paths\n * const endpoints = {\n * getUser: '/user',\n * createPost: '/post',\n * };\n *\n * // Create the API fetcher with configuration\n * const api = createApiFetcher({\n * endpoints,\n * apiUrl: 'https://example.com/api',\n * onError(error) {\n * console.log('Request failed', error);\n * },\n * headers: {\n * 'my-auth-key': 'example-auth-key-32rjjfa',\n * },\n * });\n *\n * // Fetch user data\n * const response = await api.getUser({ userId: 1, ratings: [1, 2] })\n */\nfunction createApiFetcher<\n EndpointsMethods extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n const requestHandler = createRequestHandler(config);\n\n /**\n * Get Custom Fetcher Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Request Handler's Custom Fetcher Instance\n */\n function getInstance(): CreatedCustomFetcherInstance | null {\n return requestHandler.getInstance();\n }\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n function handleNonImplemented(endpointName: string): Promise {\n console.error(`Add ${endpointName} to 'endpoints'.`);\n\n return Promise.resolve(null);\n }\n\n /**\n * Handle Single API Request\n * It considers settings in following order: per-request settings, global per-endpoint settings, global settings.\n *\n * @param {keyof EndpointsMethods | string} endpointName - The name of the API endpoint to call.\n * @param {EndpointConfig} [requestConfig={}] - Additional configuration for the request.\n * @returns {Promise>} - A promise that resolves with the response from the API provider.\n */\n async function request<\n ResponseData = never,\n QueryParams_ = never,\n UrlParams = never,\n RequestBody = never,\n >(\n endpointName: keyof EndpointsMethods | string,\n requestConfig: RequestConfig<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n > = {},\n ): Promise>> {\n // Use global per-endpoint settings\n const endpointConfig =\n endpoints[endpointName] ||\n ({ url: endpointName as string } as RequestConfigUrlRequired);\n\n const responseData = await requestHandler.request<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n >(endpointConfig.url, {\n ...endpointConfig,\n ...requestConfig,\n });\n\n return responseData;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\n requestHandler,\n getInstance,\n request,\n };\n\n /**\n * Maps all API requests using native Proxy\n *\n * @param {*} prop Caller\n */\n return new Proxy>(\n apiHandler as ApiHandlerMethods,\n {\n get(_target, prop: string) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"],"mappings":"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","names":["src_exports","__export","createApiFetcher","fetchf","__toCommonJS","applyInterceptor","object","interceptors","value","interceptor","ResponseErr","message","requestInfo","response","APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","ABORT_ERROR","TIMEOUT_ERROR","CANCELLED_ERROR","GET","HEAD","isSearchParams","data","shallowSerialize","obj","result","key","sortObject","sortedObj","keys","i","len","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","isSearchParams","encodedQueryString","s","encode","add","k","v","buildParams","prefix","OBJECT","replaceUrlPathParams","urlPathParams","str","word","isJSONSerializable","value","UNDEFINED","STRING","proto","delayInvocation","ms","resolve","flattenData","data","processHeaders","headers","headersObject","deleteProperty","property","queue","addRequest","config","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","previousController","timeoutId","ABORT_ERROR","controller","error","TIMEOUT_ERROR","removeRequest","parseResponseData","response","contentType","CONTENT_TYPE","data","APPLICATION_JSON","APPLICATION_CONTENT_TYPE","hash","str","i","len","char","cache","generateCacheKey","options","url","method","GET","headers","body","mode","credentials","redirect","referrer","integrity","headersString","shallowSerialize","sortObject","bodyString","hash","value","key","UNDEFINED","o","OBJECT","isCacheExpired","timestamp","maxStaleTime","getCache","cacheTime","entry","setCache","data","isLoading","defaultConfig","GET","APPLICATION_JSON","CONTENT_TYPE","createRequestHandler","config","handlerConfig","customFetcher","requestInstance","getInstance","getConfig","reqConfig","name","UNDEFINED","logger","args","buildConfig","url","method","isGetAlikeMethod","HEAD","dynamicUrl","replaceUrlPathParams","explicitParams","explicitBodyData","body","credentials","urlPath","appendQueryParams","baseURL","STRING","isSearchParams","isJSONSerializable","processError","error","requestConfig","isRequestCancelled","applyInterceptor","outputErrorResponse","response","_isRequestCancelled","errorHandlingStrategy","rejectCancelled","outputResponse","ABORT_ERROR","CANCELLED_ERROR","request","_reqConfig","mergedConfig","fetcherConfig","timeout","cancellable","dedupeTime","pollingInterval","shouldStopPolling","cacheTime","cacheKey","_cacheKey","generateCacheKey","cacheBuster","cachedEntry","getCache","retries","delay","backoff","retryOn","shouldRetry","maxDelay","resetTimeout","attempt","pollingAttempt","waitTime","_retries","addRequest","parseResponseData","ResponseErr","removeRequest","delayInvocation","output","skipCache","setCache","err","status","defaultResponse","deleteProperty","data","OBJECT","flattenData","processHeaders","createApiFetcher","config","endpoints","requestHandler","createRequestHandler","getInstance","handleNonImplemented","endpointName","request","requestConfig","endpointConfig","apiHandler","_target","prop","fetchf","url","config","createRequestHandler"]} \ No newline at end of file +{"version":3,"sources":["../../src/index.ts","../../src/interceptor-manager.ts","../../src/response-error.ts","../../src/constants.ts","../../src/utils.ts","../../src/queue-manager.ts","../../src/response-parser.ts","../../src/hash.ts","../../src/cache-manager.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"sourcesContent":["import { createRequestHandler } from './request-handler';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestHandlerConfig,\n} from './types';\n\n/**\n * Simple wrapper for request fetching.\n * It abstracts the creation of RequestHandler, making it easy to perform API requests.\n *\n * @param {string | URL | globalThis.Request} url - Request URL.\n * @param {RequestHandlerConfig} config - Configuration object for the request handler.\n * @returns {Promise>} Response Data.\n */\nexport async function fetchf(\n url: string,\n config: RequestHandlerConfig = {},\n): Promise> {\n return createRequestHandler(config).request(url, config);\n}\n\nexport * from './types';\nexport * from './api-handler';\n","type InterceptorFunction = (object: T) => Promise;\n\n/**\n * Applies interceptors to the object. Interceptors can be a single function or an array of functions.\n *\n * @template T - Type of the object.\n * @template I - Type of interceptors.\n *\n * @param {T} object - The object to process.\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptor<\n T extends object,\n I = InterceptorFunction | InterceptorFunction[],\n>(object: T, interceptors?: I): Promise {\n if (!interceptors) {\n return;\n }\n\n if (typeof interceptors === 'function') {\n const value = await interceptors(object);\n\n if (value) {\n Object.assign(object, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(object);\n\n if (value) {\n Object.assign(object, value);\n }\n }\n }\n}\n","import type { FetchResponse, RequestConfig } from './types';\n\nexport class ResponseErr extends Error {\n response: FetchResponse;\n request: RequestConfig;\n config: RequestConfig;\n status: number;\n statusText: string;\n\n constructor(\n message: string,\n requestInfo: RequestConfig,\n response: FetchResponse,\n ) {\n super(message);\n\n this.name = 'ResponseError';\n this.message = message;\n this.status = response.status;\n this.statusText = response.statusText;\n this.request = requestInfo;\n this.config = requestInfo;\n this.response = response;\n }\n}\n","export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\nexport const CANCELLED_ERROR = 'CanceledError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\nexport function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const sortedObj = {} as Record;\n const keys = Object.keys(obj);\n\n keys.sort();\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === 'function' ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any) => {\n let i: number, len: number, key: string;\n\n if (prefix) {\n if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n buildParams(\n prefix + '[' + (typeof obj[i] === OBJECT && obj[i] ? i : '') + ']',\n obj[i],\n );\n }\n } else if (typeof obj === OBJECT && obj !== null) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key]);\n }\n } else {\n add(prefix, obj);\n }\n } else if (Array.isArray(obj)) {\n for (i = 0, len = obj.length; i < len; i++) {\n add(obj[i].name, obj[i].value);\n }\n } else {\n for (key in obj) {\n buildParams(key, obj[key]);\n }\n }\n return s;\n };\n\n const queryStringParts = buildParams('', params).join('&');\n\n // Encode special characters as per RFC 3986, https://datatracker.ietf.org/doc/html/rfc3986\n const encodedQueryString = queryStringParts.replace(/%5B%5D/g, '[]'); // Keep '[]' for arrays\n\n return appendQueryStringToUrl(url, encodedQueryString);\n}\n\n/**\n * Replaces dynamic URI parameters in a URL string with values from the provided `urlPathParams` object.\n * Parameters in the URL are denoted by `:`, where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:`.\n * @param {Object} urlPathParams - An object containing the parameter values to replace placeholders.\n * @param {string} urlPathParams.paramName - The value to replace the placeholder `:` in the URL.\n * @returns {string} - The URL string with placeholders replaced by corresponding values from `urlPathParams`.\n */\nexport function replaceUrlPathParams(\n url: string,\n urlPathParams: UrlPathParams,\n): string {\n if (!urlPathParams) {\n return url;\n }\n\n return url.replace(/:\\w+/g, (str): string => {\n const word = str.substring(1);\n\n if ((urlPathParams as DefaultUrlParams)[word]) {\n return String((urlPathParams as DefaultUrlParams)[word]);\n }\n\n return str;\n });\n}\n\n/**\n * Checks if a value is JSON serializable.\n *\n * JSON serializable values include:\n * - Primitive types: string, number, boolean, null\n * - Arrays\n * - Plain objects (i.e., objects without special methods)\n * - Values with a `toJSON` method\n *\n * @param {any} value - The value to check for JSON serializability.\n * @returns {boolean} - Returns `true` if the value is JSON serializable, otherwise `false`.\n */\nexport function isJSONSerializable(value: any): boolean {\n const t = typeof value;\n\n if (t === UNDEFINED || value === null) {\n return false;\n }\n\n if (t === STRING || t === 'number' || t === 'boolean') {\n return true;\n }\n\n if (Array.isArray(value)) {\n return true;\n }\n\n if (Buffer.isBuffer(value)) {\n return false;\n }\n\n if (value instanceof Date) {\n return false;\n }\n\n if (t === OBJECT) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` or `null` (plain object)\n if (proto === Object.prototype || proto === null) {\n return true;\n }\n\n // Check if the object has a toJSON method\n if (typeof value.toJSON === 'function') {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any): any {\n if (\n data &&\n typeof data === OBJECT &&\n typeof data.data !== UNDEFINED &&\n Object.keys(data).length === 1\n ) {\n return flattenData(data.data);\n }\n\n return data;\n}\n\n/**\n * Processes headers and returns them as a normalized object.\n *\n * Handles both `Headers` instances and plain objects. Normalizes header keys to lowercase\n * as per RFC 2616 section 4.2.\n *\n * @param headers - The headers to process. Can be an instance of `Headers`, a plain object,\n * or `null`. If `null`, an empty object is returned.\n * @returns {HeadersObject} - A normalized headers object with lowercase keys.\n */\nexport function processHeaders(\n headers?: (HeadersObject & HeadersInit) | null | Headers,\n): HeadersObject {\n if (!headers) {\n return {};\n }\n\n const headersObject: HeadersObject = {};\n\n // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (typeof headers === OBJECT && headers !== null) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * Deletes a property from an object if it exists.\n *\n * @param obj - The object from which to delete the property.\n * @param property - The property to delete from the object.\n */\nexport function deleteProperty>(\n obj: T | null,\n property: keyof T,\n): void {\n if (obj && property in obj) {\n delete obj[property];\n }\n}\n","import { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport type { RequestConfig } from './types';\nimport type { QueueItem, RequestsQueue } from './types/queue-manager';\n\n/**\n * Queue Manager is responsible for managing and controlling the flow of concurrent or sequential requests. It handles:\n * - Request Queueing and Deduplication\n * - Request Timeout Handling\n * - Abort Controller Management and Request Cancellation\n * - Concurrency Control and Locking\n * - Request Lifecycle Management\n */\nconst queue: RequestsQueue = new Map();\n\n/**\n * Adds a request to the queue if it's not already being processed within the dedupeTime interval.\n *\n * @param {RequestConfig} config - The request configuration object.\n * @param {number} timeout - Timeout in milliseconds for the request.\n * @param {number} dedupeTime - Deduplication time in milliseconds.\n * @param {boolean} isCancellable - If true, then the previous request with same configuration should be aborted.\n * @param {boolean} isTimeoutEnabled - Whether timeout is enabled.\n * @returns {Promise} - A promise that resolves to an AbortController.\n */\nexport async function addRequest(\n config: RequestConfig,\n timeout: number | undefined,\n dedupeTime: number = 0,\n isCancellable: boolean = false,\n isTimeoutEnabled: boolean = true,\n): Promise {\n const now = Date.now();\n const item = queue.get(config);\n\n if (item) {\n const isCancellable = item[3];\n const previousController = item[0];\n const timeoutId = item[1];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (!isCancellable && now - item[2] < dedupeTime) {\n return previousController;\n }\n\n // If the request is too old, remove it and proceed to add a new one\n // Abort previous request, if applicable, and continue as usual\n if (isCancellable) {\n previousController.abort(\n new DOMException('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n\n const controller = new AbortController();\n\n const timeoutId = isTimeoutEnabled\n ? setTimeout(() => {\n const error = new DOMException(\n `${config.url} aborted due to timeout`,\n TIMEOUT_ERROR,\n );\n\n removeRequest(config, error);\n }, timeout)\n : null;\n\n queue.set(config, [controller, timeoutId, now, isCancellable]);\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param config - The request configuration.\n * @param {boolean} error - Error payload so to force the request to abort.\n */\nexport async function removeRequest(\n config: RequestConfig,\n error: DOMException | null | string = null,\n): Promise {\n const item = queue.get(config);\n\n if (item) {\n const controller = item[0];\n const timeoutId = item[1];\n\n // If the request is not yet aborted, abort it with the provided error\n if (error && !controller.signal.aborted) {\n controller.abort(error);\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n queue.delete(config);\n }\n}\n\n/**\n * Gets the AbortController for a request configuration.\n *\n * @param config - The request configuration.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n config: RequestConfig,\n): Promise {\n const item = queue.get(config);\n\n return item?.[0];\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n} from './constants';\nimport type { DefaultResponse, FetchResponse } from './types/request-handler';\n\n/**\n * Parses the response data based on the Content-Type header.\n *\n * @param response - The Response object to parse.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData(\n response: FetchResponse,\n): Promise {\n // Bail early when body is empty\n if (!response?.body) {\n return null;\n }\n\n const contentType = String(\n (response as Response).headers?.get(CONTENT_TYPE) || '',\n ).split(';')[0]; // Correctly handle charset\n\n let data;\n\n try {\n if (\n contentType.includes(APPLICATION_JSON) ||\n contentType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (contentType.includes('multipart/form-data')) {\n data = await response.formData(); // Parse as FormData\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream')\n ) {\n data = await response.blob(); // Parse as blob\n } else if (\n contentType.includes(APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded')\n ) {\n data = await response.formData(); // Handle URL-encoded forms\n } else if (contentType.includes('text/')) {\n data = await response.text(); // Parse as text\n } else {\n try {\n const responseClone = response.clone();\n\n // Handle edge case of no content type being provided... We assume JSON here.\n data = await responseClone.json();\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_e) {\n // Handle streams\n data = await response.text();\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n // Parsing failed, fallback to null\n data = null;\n }\n\n return data;\n}\n","const PRIME_MULTIPLIER = 31;\n\n/**\n * Computes a hash value for a given string using the variant of djb2 hash function.\n * This hash function is non-cryptographic and designed for speed.\n * @author Daniel J. Bernstein (of djb2)\n *\n * @param str Input string to hash\n * @returns {string} Hash\n */\nexport function hash(str: string): string {\n let hash = 0;\n\n for (let i = 0, len = str.length; i < len; i++) {\n const char = str.charCodeAt(i);\n hash = (hash * PRIME_MULTIPLIER + char) | 0;\n }\n\n return String(hash);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport { fetchf } from './index';\nimport type { FetcherConfig } from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, OBJECT, UNDEFINED } from './constants';\nimport { shallowSerialize, sortObject } from './utils';\n\nconst cache = new Map>();\n\n/**\n * Generates a cache key for a given URL and fetch options, ensuring that key factors\n * like method, headers, body, and other options are included in the cache key.\n * Headers and other objects are sorted by key to ensure consistent cache keys.\n *\n * @param options - The fetch options that may affect the request. The most important are:\n * @property {string} [method=\"GET\"] - The HTTP method (GET, POST, etc.).\n * @property {HeadersInit} [headers={}] - The request headers.\n * @property {BodyInit | null} [body=\"\"] - The body of the request (only for methods like POST, PUT).\n * @property {RequestMode} [mode=\"cors\"] - The mode for the request (e.g., cors, no-cors, include).\n * @property {RequestCredentials} [credentials=\"include\"] - Whether to include credentials like cookies.\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @property {RequestRedirect} [redirect=\"follow\"] - How to handle redirects (e.g., follow, error, manual).\n * @property {string} [referrer=\"\"] - The referrer URL to send with the request.\n * @property {string} [integrity=\"\"] - Subresource integrity value (a cryptographic hash for resource validation).\n * @returns {string} - A unique cache key based on the URL and request options. Empty if cache is to be burst.\n *\n * @example\n * const cacheKey = generateCacheKey({\n * url: 'https://api.example.com/data',\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'Alice' }),\n * mode: 'cors',\n * credentials: 'include',\n * });\n * console.log(cacheKey);\n */\nexport function generateCacheKey(options: FetcherConfig): string {\n const {\n url = '',\n method = GET,\n headers = {},\n body = '',\n mode = 'cors',\n credentials = 'include',\n cache = 'default',\n redirect = 'follow',\n referrer = '',\n integrity = '',\n } = options;\n\n // Bail early if cache should be burst\n if (cache === 'reload') {\n return '';\n }\n\n // Sort headers and body + convert sorted to strings for hashing purposes\n // Native serializer is on avg. 3.5x faster than a Fast Hash or FNV-1a\n const headersString = shallowSerialize(sortObject(headers));\n\n let bodyString = '';\n\n // In majority of cases we do not cache body\n if (body !== null) {\n if (typeof body === 'string') {\n bodyString = hash(body);\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n bodyString = hash(bodyString);\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = typeof body === OBJECT ? sortObject(body) : String(body);\n bodyString = hash(JSON.stringify(o));\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n return (\n method +\n url +\n mode +\n credentials +\n cache +\n redirect +\n referrer +\n integrity +\n headersString +\n bodyString\n );\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the maximum stale time.\n *\n * @param {number} timestamp - The timestamp of the cache entry.\n * @param {number} maxStaleTime - The maximum stale time in seconds.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(timestamp: number, maxStaleTime: number): boolean {\n if (!maxStaleTime) {\n return false;\n }\n\n return Date.now() - timestamp > maxStaleTime * 1000;\n}\n\n/**\n * Retrieves a cache entry if it exists and is not expired.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} cacheTime - Maximum time to cache entry.\n * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string,\n cacheTime: number,\n): CacheEntry | null {\n const entry = cache.get(key);\n\n if (entry) {\n if (!isCacheExpired(entry.timestamp, cacheTime)) {\n return entry;\n }\n\n cache.delete(key);\n }\n\n return null;\n}\n\n/**\n * Sets a new cache entry or updates an existing one.\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {boolean} isLoading - Indicates if the data is currently being fetched.\n */\nexport function setCache(\n key: string,\n data: T,\n isLoading: boolean = false,\n): void {\n cache.set(key, {\n data,\n isLoading,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Revalidates a cache entry by fetching fresh data and updating the cache.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @returns {Promise} - A promise that resolves when the revalidation is complete.\n */\nexport async function revalidate(\n key: string,\n config: FetcherConfig,\n): Promise {\n try {\n // Fetch fresh data\n const newData = await fetchf(config.url, {\n ...config,\n cache: 'reload',\n });\n\n setCache(key, newData);\n } catch (error) {\n console.error(`Error revalidating ${config.url}:`, error);\n\n // Rethrow the error to forward it\n throw error;\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n */\nexport function deleteCache(key: string): void {\n cache.delete(key);\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string} key Cache key to utilize\n * @param {FetcherConfig} config - The request configuration object.\n * @param {T} newData - The new data to be cached.\n * @param {boolean} revalidateAfter - If true, triggers revalidation after mutation.\n */\nexport function mutate(\n key: string,\n config: FetcherConfig,\n newData: T,\n revalidateAfter: boolean = false,\n): void {\n setCache(key, newData);\n\n if (revalidateAfter) {\n revalidate(key, config);\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n DefaultResponse,\n RequestHandlerConfig,\n RequestConfig,\n Method,\n RetryOptions,\n FetchResponse,\n ResponseError,\n RequestHandlerReturnType,\n CreatedCustomFetcherInstance,\n FetcherConfig,\n FetcherInstance,\n Logger,\n} from './types/request-handler';\nimport type {\n BodyPayload,\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n QueryParams,\n} from './types/api-handler';\nimport { applyInterceptor } from './interceptor-manager';\nimport { ResponseErr } from './response-error';\nimport {\n appendQueryParams,\n isJSONSerializable,\n replaceUrlPathParams,\n delayInvocation,\n flattenData,\n processHeaders,\n deleteProperty,\n isSearchParams,\n} from './utils';\nimport { addRequest, removeRequest } from './queue-manager';\nimport {\n ABORT_ERROR,\n APPLICATION_JSON,\n CANCELLED_ERROR,\n CONTENT_TYPE,\n GET,\n HEAD,\n OBJECT,\n STRING,\n UNDEFINED,\n} from './constants';\nimport { parseResponseData } from './response-parser';\nimport { generateCacheKey, getCache, setCache } from './cache-manager';\n\nconst defaultConfig: RequestHandlerConfig = {\n method: GET,\n strategy: 'reject',\n timeout: 30000,\n dedupeTime: 1000,\n defaultResponse: null,\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n [CONTENT_TYPE]: APPLICATION_JSON + ';charset=utf-8',\n },\n retry: {\n delay: 1000,\n maxDelay: 30000,\n resetTimeout: true,\n backoff: 1.5,\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n retryOn: [\n 408, // Request Timeout\n 409, // Conflict\n 425, // Too Early\n 429, // Too Many Requests\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504, // Gateway Timeout\n ],\n },\n};\n\n/**\n * Create Request Handler\n *\n * @param {RequestHandlerConfig} config - Configuration object for the request handler\n * @returns {Object} An object with methods for handling requests\n */\nexport function createRequestHandler(\n config: RequestHandlerConfig,\n): RequestHandlerReturnType {\n const handlerConfig: RequestHandlerConfig = {\n ...defaultConfig,\n ...config,\n };\n\n /**\n * Merges the specified property from the base configuration and the new configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and new configurations. Must be a key of RequestHandlerConfig.\n * @param {RequestHandlerConfig} targetConfig - The configuration object that will receive the merged properties.\n * @param {RequestHandlerConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestHandlerConfig} newConfig - The new configuration object that contains user-specific settings to merge.\n */\n const mergeConfig = (\n property: K,\n targetConfig: RequestHandlerConfig,\n baseConfig: RequestHandlerConfig,\n newConfig: RequestHandlerConfig,\n ) => {\n if (newConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...newConfig[property],\n };\n }\n };\n\n mergeConfig('retry', handlerConfig, defaultConfig, config);\n mergeConfig('headers', handlerConfig, defaultConfig, config);\n\n /**\n * Gets a configuration value from `reqConfig`, defaulting to `handlerConfig` if not present.\n *\n * @param {RequestConfig} reqConfig - Request configuration object.\n * @param {keyof RequestConfig} name - Key of the configuration value.\n * @returns {T} - The configuration value.\n */\n const getConfig = (\n reqConfig: RequestConfig,\n name: keyof RequestConfig,\n ): T => {\n return typeof reqConfig[name] !== UNDEFINED\n ? reqConfig[name]\n : handlerConfig[name];\n };\n\n /**\n * Immediately create instance of custom fetcher if it is defined\n */\n const customFetcher = getConfig(config, 'fetcher');\n const requestInstance = customFetcher?.create(handlerConfig) || null;\n\n /**\n * Get Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Provider's instance\n */\n const getInstance = (): CreatedCustomFetcherInstance | null => {\n return requestInstance;\n };\n\n /**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\n const logger = (\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n ): void => {\n const logger = getConfig(reqConfig, 'logger');\n\n if (logger?.warn) {\n logger.warn(...args);\n }\n };\n\n /**\n * Build request configuration\n *\n * @param {string} url - Request url\n * @param {RequestConfig} requestConfig - Request config passed when making the request\n * @returns {RequestConfig} - Provider's instance\n */\n const buildConfig = (\n url: string,\n requestConfig: RequestConfig,\n ): FetcherConfig => {\n const method = getConfig(\n requestConfig,\n 'method',\n ).toUpperCase() as Method;\n const isGetAlikeMethod = method === GET || method === HEAD;\n\n const dynamicUrl = replaceUrlPathParams(\n url,\n getConfig(requestConfig, 'urlPathParams'),\n );\n\n // The explicitly passed \"params\"\n const explicitParams = getConfig(requestConfig, 'params');\n\n // The explicitly passed \"body\" or \"data\"\n const explicitBodyData: BodyPayload =\n getConfig(requestConfig, 'body') || getConfig(requestConfig, 'data');\n\n // Final body data\n let body: RequestConfig['data'];\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (!isGetAlikeMethod) {\n body = explicitBodyData;\n }\n\n // Native fetch compatible settings\n const isWithCredentials = getConfig(\n requestConfig,\n 'withCredentials',\n );\n\n const credentials = isWithCredentials\n ? 'include'\n : getConfig(requestConfig, 'credentials');\n\n const urlPath = explicitParams\n ? appendQueryParams(dynamicUrl, explicitParams)\n : dynamicUrl;\n const isFullUrl = urlPath.includes('://');\n const baseURL = isFullUrl\n ? ''\n : getConfig(requestConfig, 'baseURL') ||\n getConfig(requestConfig, 'apiUrl');\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (\n body &&\n typeof body !== STRING &&\n !isSearchParams(body) &&\n isJSONSerializable(body)\n ) {\n body = JSON.stringify(body);\n }\n\n return {\n ...requestConfig,\n credentials,\n body,\n method,\n\n url: baseURL + urlPath,\n };\n };\n\n /**\n * Process global Request Error\n *\n * @param {ResponseError} error Error instance\n * @param {RequestConfig} requestConfig Per endpoint request config\n * @returns {Promise}\n */\n const processError = async (\n error: ResponseError,\n requestConfig: RequestConfig,\n ): Promise => {\n if (!isRequestCancelled(error)) {\n logger(requestConfig, 'API ERROR', error);\n }\n\n // Local interceptors\n await applyInterceptor(error, requestConfig?.onError);\n\n // Global interceptors\n await applyInterceptor(error, handlerConfig?.onError);\n };\n\n /**\n * Output default response in case of an error, depending on chosen strategy\n *\n * @param {ResponseError} error - Error instance\n * @param {FetchResponse | null} response - Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Per endpoint request config\n * @returns {FetchResponse} Response together with the error object\n */\n const outputErrorResponse = async (\n error: ResponseError,\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n ): Promise => {\n const _isRequestCancelled = isRequestCancelled(error);\n const errorHandlingStrategy = getConfig(requestConfig, 'strategy');\n const rejectCancelled = getConfig(\n requestConfig,\n 'rejectCancelled',\n );\n\n // By default cancelled requests aren't rejected (softFail strategy)\n if (!(_isRequestCancelled && !rejectCancelled)) {\n // Hang the promise\n if (errorHandlingStrategy === 'silent') {\n await new Promise(() => null);\n }\n // Reject the promise\n else if (errorHandlingStrategy === 'reject') {\n return Promise.reject(error);\n }\n }\n\n return outputResponse(response, requestConfig, error);\n };\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {ResponseError} error Error instance\n * @returns {boolean} True if request is aborted\n */\n const isRequestCancelled = (error: ResponseError): boolean => {\n return error.name === ABORT_ERROR || error.name === CANCELLED_ERROR;\n };\n\n /**\n * Handle Request depending on used strategy\n *\n * @param {string} url - Request url\n * @param {RequestConfig} reqConfig - Request config\n * @throws {ResponseError}\n * @returns {Promise>} Response Data\n */\n const request = async <\n ResponseData = DefaultResponse,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n RequestBody = DefaultPayload,\n >(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n ): Promise> => {\n const _reqConfig = reqConfig || {};\n const mergedConfig = {\n ...handlerConfig,\n ..._reqConfig,\n } as RequestConfig;\n\n mergeConfig('retry', mergedConfig, handlerConfig, _reqConfig);\n mergeConfig('headers', mergedConfig, handlerConfig, _reqConfig);\n\n let response: FetchResponse | null = null;\n const fetcherConfig = buildConfig(url, mergedConfig);\n\n const {\n timeout,\n cancellable,\n dedupeTime,\n pollingInterval,\n shouldStopPolling,\n cacheTime,\n cacheKey,\n } = mergedConfig;\n\n // Prevent performance overhead of cache access\n let _cacheKey: string;\n\n if (cacheKey) {\n _cacheKey = cacheKey(fetcherConfig);\n } else {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n if (cacheTime && _cacheKey) {\n const cacheBuster = mergedConfig.cacheBuster;\n\n if (!cacheBuster || !cacheBuster(fetcherConfig)) {\n const cachedEntry = getCache>(\n _cacheKey,\n cacheTime,\n );\n\n if (cachedEntry) {\n // Serve stale data from cache\n return cachedEntry.data;\n }\n }\n }\n\n const {\n retries = 0,\n delay,\n backoff,\n retryOn,\n shouldRetry,\n maxDelay,\n resetTimeout,\n } = mergedConfig.retry as Required;\n\n let attempt = 0;\n let pollingAttempt = 0;\n let waitTime: number = delay;\n const _retries = retries > 0 ? retries : 0;\n\n while (attempt <= _retries) {\n try {\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = await addRequest(\n fetcherConfig,\n timeout,\n dedupeTime,\n cancellable,\n // Reset timeouts by default or when retries are ON\n !!(timeout && (!_retries || resetTimeout)),\n );\n\n // Shallow copy to ensure basic idempotency\n const requestConfig: RequestConfig = {\n signal: controller.signal,\n ...fetcherConfig,\n };\n\n // Local interceptors\n await applyInterceptor(requestConfig, _reqConfig?.onRequest);\n\n // Global interceptors\n await applyInterceptor(requestConfig, handlerConfig?.onRequest);\n\n if (customFetcher !== null && requestInstance !== null) {\n response = await requestInstance.request(requestConfig);\n } else {\n response = (await fetch(\n requestConfig.url as string,\n requestConfig as RequestInit,\n )) as FetchResponse;\n }\n\n // Add more information to response object\n if (response instanceof Response) {\n response.config = requestConfig;\n response.data = await parseResponseData(response);\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n if (!response.ok) {\n throw new ResponseErr(\n `${requestConfig.url} failed! Status: ${response.status || null}`,\n requestConfig,\n response,\n );\n }\n }\n\n // Local interceptors\n await applyInterceptor(response, _reqConfig?.onResponse);\n\n // Global interceptors\n await applyInterceptor(response, handlerConfig?.onResponse);\n\n removeRequest(fetcherConfig);\n\n // Polling logic\n if (\n pollingInterval &&\n (!shouldStopPolling || !shouldStopPolling(response, pollingAttempt))\n ) {\n // Restart the main retry loop\n pollingAttempt++;\n\n logger(requestConfig, 'Polling attempt ' + pollingAttempt + '...');\n\n await delayInvocation(pollingInterval);\n\n continue;\n }\n\n // If polling is not required, or polling attempts are exhausted\n const output = outputResponse(response, requestConfig);\n\n if (cacheTime && _cacheKey) {\n const skipCache = requestConfig.skipCache;\n\n if (!skipCache || !skipCache(output, requestConfig)) {\n setCache(_cacheKey, output);\n }\n }\n\n return output;\n } catch (err) {\n const error = err as ResponseErr;\n const status = error?.response?.status || error?.status || 0;\n\n if (\n attempt === retries ||\n !(!shouldRetry || (await shouldRetry(error, attempt))) ||\n !retryOn?.includes(status)\n ) {\n await processError(error, fetcherConfig);\n\n removeRequest(fetcherConfig);\n\n return outputErrorResponse(\n error,\n response,\n fetcherConfig,\n );\n }\n\n logger(\n mergedConfig,\n `Attempt ${attempt + 1} failed. Retry in ${waitTime}ms.`,\n );\n\n await delayInvocation(waitTime);\n\n waitTime *= backoff;\n waitTime = Math.min(waitTime, maxDelay);\n attempt++;\n }\n }\n\n return outputResponse(response, fetcherConfig);\n };\n\n /**\n * Output response\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} requestConfig - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\n const outputResponse = (\n response: FetchResponse | null,\n requestConfig: RequestConfig,\n error: ResponseError | null = null,\n ): FetchResponse => {\n const defaultResponse = getConfig(requestConfig, 'defaultResponse');\n\n // This may happen when request is cancelled.\n if (!response) {\n return {\n ok: false,\n // Enhance the response with extra information\n error,\n data: defaultResponse,\n headers: null,\n config: requestConfig,\n } as unknown as FetchResponse;\n }\n\n // Clean up the error object\n deleteProperty(error, 'response');\n deleteProperty(error, 'request');\n deleteProperty(error, 'config');\n\n let data = response?.data;\n\n // Set the default response if the provided data is an empty object\n if (\n data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0)\n ) {\n data = defaultResponse;\n }\n\n // Return flattened response immediately\n const flattenResponse = getConfig(\n requestConfig,\n 'flattenResponse',\n );\n\n if (flattenResponse) {\n response.data = flattenData(data);\n }\n\n // If it's a custom fetcher, and it does not return any Response instance, it may have its own internal handler\n if (!(response instanceof Response)) {\n return response;\n }\n\n // Native fetch Response extended by extra information\n return {\n body: response.body,\n bodyUsed: response.bodyUsed,\n formData: response.formData,\n ok: response.ok,\n redirected: response.redirected,\n type: response.type,\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n\n blob: response.blob.bind(response),\n json: response.json.bind(response),\n text: response.text.bind(response),\n clone: response.clone.bind(response),\n arrayBuffer: response.arrayBuffer.bind(response),\n\n // Enhance the response with extra information\n error,\n data,\n headers: processHeaders(response.headers),\n config: requestConfig,\n };\n };\n\n return {\n getInstance,\n buildConfig,\n config,\n request,\n };\n}\n","import type {\n RequestConfig,\n FetchResponse,\n DefaultResponse,\n CreatedCustomFetcherInstance,\n} from './types/request-handler';\nimport type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n DefaultPayload,\n FallbackValue,\n FinalParams,\n FinalResponse,\n QueryParams,\n RequestConfigUrlRequired,\n UrlPathParams,\n} from './types/api-handler';\nimport { createRequestHandler } from './request-handler';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if it is passed as \"fetcher\".\n * @url https://github.com/MattCCC/fetchff\n *\n * @param {Object} config - Configuration object for the API fetcher.\n * @param {string} config.apiUrl - The base URL for the API.\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {number} config.timeout - You can set the timeout for particular request in milliseconds.\n * @param {number} config.cancellable - If true, the ongoing previous requests will be automatically cancelled.\n * @param {number} config.rejectCancelled - If true and request is set to cancellable, a cancelled request promise will be rejected. By default, instead of rejecting the promise, defaultResponse is returned.\n * @param {number} config.timeout - Request timeout\n * @param {number} config.dedupeTime - Time window, in milliseconds, during which identical requests are deduplicated (treated as single request).\n * @param {string} config.strategy - Error Handling Strategy\n * @param {string} config.flattenResponse - Whether to flatten response \"data\" object within \"data\". It works only if the response structure includes a single data property.\n * @param {*} config.defaultResponse - Default response when there is no data or when endpoint fails depending on the chosen strategy. It's \"null\" by default\n * @param {Object} [config.retry] - Options for retrying requests.\n * @param {number} [config.retry.retries=0] - Number of retry attempts. No retries by default.\n * @param {number} [config.retry.delay=1000] - Initial delay between retries in milliseconds.\n * @param {number} [config.retry.backoff=1.5] - Exponential backoff factor.\n * @param {number[]} [config.retry.retryOn=[502, 504, 408]] - HTTP status codes to retry on.\n * @param {RequestInterceptor|RequestInterceptor[]} [config.onRequest] - Optional request interceptor function or an array of functions.\n * These functions will be called with the request configuration object before the request is made. Can be used to modify or log the request configuration.\n * @param {ResponseInterceptor|ResponseInterceptor[]} [config.onResponse] - Optional response interceptor function or an array of functions.\n * These functions will be called with the response object after the response is received. an be used to modify or log the response data.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Object} config.fetcher - The Custom Fetcher instance to use for making requests. It should expose create() and request() functions.\n * @param {*} config.logger - Instance of custom logger. Either class or an object similar to \"console\". Console is used by default.\n * @returns API handler functions and endpoints to call\n *\n * @example\n * // Define endpoint paths\n * const endpoints = {\n * getUser: '/user',\n * createPost: '/post',\n * };\n *\n * // Create the API fetcher with configuration\n * const api = createApiFetcher({\n * endpoints,\n * apiUrl: 'https://example.com/api',\n * onError(error) {\n * console.log('Request failed', error);\n * },\n * headers: {\n * 'my-auth-key': 'example-auth-key-32rjjfa',\n * },\n * });\n *\n * // Fetch user data\n * const response = await api.getUser({ userId: 1, ratings: [1, 2] })\n */\nfunction createApiFetcher<\n EndpointsMethods extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n const requestHandler = createRequestHandler(config);\n\n /**\n * Get Custom Fetcher Provider Instance\n *\n * @returns {CreatedCustomFetcherInstance | null} Request Handler's Custom Fetcher Instance\n */\n function getInstance(): CreatedCustomFetcherInstance | null {\n return requestHandler.getInstance();\n }\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n function handleNonImplemented(endpointName: string): Promise {\n console.error(`Add ${endpointName} to 'endpoints'.`);\n\n return Promise.resolve(null);\n }\n\n /**\n * Handle Single API Request\n * It considers settings in following order: per-request settings, global per-endpoint settings, global settings.\n *\n * @param {keyof EndpointsMethods | string} endpointName - The name of the API endpoint to call.\n * @param {EndpointConfig} [requestConfig={}] - Additional configuration for the request.\n * @returns {Promise>} - A promise that resolves with the response from the API provider.\n */\n async function request<\n ResponseData = never,\n QueryParams_ = never,\n UrlParams = never,\n RequestBody = never,\n >(\n endpointName: keyof EndpointsMethods | string,\n requestConfig: RequestConfig<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n > = {},\n ): Promise>> {\n // Use global per-endpoint settings\n const endpointConfig =\n endpoints[endpointName] ||\n ({ url: endpointName as string } as RequestConfigUrlRequired);\n\n const responseData = await requestHandler.request<\n FinalResponse,\n FinalParams,\n FinalParams,\n FallbackValue\n >(endpointConfig.url, {\n ...endpointConfig,\n ...requestConfig,\n });\n\n return responseData;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\n requestHandler,\n getInstance,\n request,\n };\n\n /**\n * Maps all API requests using native Proxy\n *\n * @param {*} prop Caller\n */\n return new Proxy>(\n apiHandler as ApiHandlerMethods,\n {\n get(_target, prop: string) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"],"mappings":"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","names":["src_exports","__export","createApiFetcher","fetchf","__toCommonJS","applyInterceptor","object","interceptors","value","interceptor","ResponseErr","message","requestInfo","response","APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","ABORT_ERROR","TIMEOUT_ERROR","CANCELLED_ERROR","GET","HEAD","isSearchParams","data","shallowSerialize","obj","result","key","sortObject","sortedObj","keys","i","len","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","isSearchParams","encodedQueryString","s","encode","add","k","v","buildParams","prefix","OBJECT","replaceUrlPathParams","urlPathParams","str","word","isJSONSerializable","value","UNDEFINED","STRING","proto","delayInvocation","ms","resolve","flattenData","data","processHeaders","headers","headersObject","deleteProperty","property","queue","addRequest","config","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","previousController","timeoutId","ABORT_ERROR","controller","error","TIMEOUT_ERROR","removeRequest","parseResponseData","response","contentType","CONTENT_TYPE","data","APPLICATION_JSON","APPLICATION_CONTENT_TYPE","hash","str","i","len","char","cache","generateCacheKey","options","url","method","GET","headers","body","mode","credentials","redirect","referrer","integrity","headersString","shallowSerialize","sortObject","bodyString","hash","value","key","UNDEFINED","o","OBJECT","isCacheExpired","timestamp","maxStaleTime","getCache","cacheTime","entry","setCache","data","isLoading","defaultConfig","GET","APPLICATION_JSON","CONTENT_TYPE","createRequestHandler","config","handlerConfig","mergeConfig","property","targetConfig","baseConfig","newConfig","getConfig","reqConfig","name","UNDEFINED","customFetcher","requestInstance","getInstance","logger","args","buildConfig","url","requestConfig","method","isGetAlikeMethod","HEAD","dynamicUrl","replaceUrlPathParams","explicitParams","explicitBodyData","body","credentials","urlPath","appendQueryParams","baseURL","STRING","isSearchParams","isJSONSerializable","processError","error","isRequestCancelled","applyInterceptor","outputErrorResponse","response","_isRequestCancelled","errorHandlingStrategy","rejectCancelled","outputResponse","ABORT_ERROR","CANCELLED_ERROR","request","_reqConfig","mergedConfig","fetcherConfig","timeout","cancellable","dedupeTime","pollingInterval","shouldStopPolling","cacheTime","cacheKey","_cacheKey","generateCacheKey","cacheBuster","cachedEntry","getCache","retries","delay","backoff","retryOn","shouldRetry","maxDelay","resetTimeout","attempt","pollingAttempt","waitTime","_retries","addRequest","parseResponseData","ResponseErr","removeRequest","delayInvocation","output","skipCache","setCache","err","status","defaultResponse","deleteProperty","data","OBJECT","flattenData","processHeaders","createApiFetcher","config","endpoints","requestHandler","createRequestHandler","getInstance","handleNonImplemented","endpointName","request","requestConfig","endpointConfig","apiHandler","_target","prop","fetchf","url","config","createRequestHandler"]} \ No newline at end of file