diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index add3b75..6ac1330 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,18 +1,40 @@ -name: Publish to npm +name: Release +# Keep the file name: npm's trusted publisher for fetchff is bound to publish.yml on: release: types: [published] workflow_dispatch: -permissions: - contents: read - id-token: write # Required for OIDC +permissions: {} + +concurrency: + group: release + cancel-in-progress: false jobs: - publish: + release: + name: Release runs-on: ubuntu-latest + environment: + name: npm + url: https://www.npmjs.com/package/fetchff + permissions: + contents: read + id-token: write # Required for OIDC steps: + # github.triggering_actor is the user who started this run, or re-ran it + - name: Check that an admin started the release + env: + GH_TOKEN: ${{ github.token }} + ACTOR: ${{ github.triggering_actor }} + run: | + permission=$(gh api "repos/$GITHUB_REPOSITORY/collaborators/$ACTOR/permission" --jq .permission) + if [ "$permission" != "admin" ]; then + echo "::error::Only admins can publish to npm, and $ACTOR has $permission access." + exit 1 + fi + - uses: actions/checkout@v7 - uses: actions/setup-node@v7 @@ -21,9 +43,23 @@ jobs: registry-url: "https://registry.npmjs.org" package-manager-cache: false # Never publish a build made from cached dependencies + - name: Check that the release tag matches the version + if: github.event_name == 'release' + env: + TAG: ${{ github.event.release.tag_name }} + run: | + version=$(node -p "require('./package.json').version") + if [ "${TAG#v}" != "$version" ]; then + echo "::error::The release tag $TAG does not match version $version in package.json." + exit 1 + fi + - name: Install dependencies run: npm ci + - name: Test + run: npm test -- --ci --maxWorkers=2 + - name: Build run: npm run build diff --git a/README.md b/README.md index 4ffc8f9..82996db 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@
-logo +

+ logo +

-

Fast, lightweight (~5 KB gzipped) and reusable data fetching

+

Fast, lightweight (~9 KB gzipped) and reusable data fetching

"fetchff" stands for "fetch fast & flexibly" [npm-url]: https://npmjs.org/package/fetchff [npm-image]: https://img.shields.io/npm/v/fetchff.svg -[![NPM version][npm-image]][npm-url] [![Blazing Fast](https://badgen.now.sh/badge/speed/blazing%20%F0%9F%94%A5/green)](https://github.com/MattCCC/fetchff) [![Code Coverage](https://img.shields.io/badge/coverage-96.93-green)](https://github.com/MattCCC/fetchff) [![npm downloads](https://img.shields.io/npm/dm/fetchff.svg?color=lightblue)](http://npm-stat.com/charts.html?package=fetchff) [![gzip size](https://img.shields.io/bundlephobia/minzip/fetchff)](https://bundlephobia.com/result?p=fetchff) [![snyk](https://snyk.io/test/github/MattCCC/fetchff/badge.svg)](https://security.snyk.io/package/npm/fetchff) +[![NPM version][npm-image]][npm-url] [![Blazing Fast](https://badgen.now.sh/badge/speed/blazing%20%F0%9F%94%A5/green)](https://github.com/MattCCC/fetchff) [![Code Coverage](https://img.shields.io/badge/coverage-100-green)](https://github.com/MattCCC/fetchff) [![npm downloads](https://img.shields.io/npm/dm/fetchff.svg?color=lightblue)](http://npm-stat.com/charts.html?package=fetchff) [![gzip size](https://img.shields.io/bundlephobia/minzip/fetchff)](https://bundlephobia.com/result?p=fetchff) [![snyk](https://snyk.io/test/github/MattCCC/fetchff/badge.svg)](https://security.snyk.io/package/npm/fetchff)
@@ -52,7 +54,7 @@ To address these challenges, the `fetchf()` provides several enhancements: ## ✔️ Benefits -✅ **Lightweight:** Minimal code footprint of ~4KB gzipped for managing extensive APIs. +✅ **Lightweight:** Minimal code footprint of ~9 KB gzipped for managing extensive APIs. ✅ **High-Performance**: Optimized for speed and efficiency, ensuring fast and reliable API interactions. @@ -3131,52 +3133,62 @@ const { data } = useFetcher('/api/notifications', { staleTime: 600 }); ## Comparison with other libraries -_fetchff uniquely combines advanced input sanitization, prototype pollution protection, unified cache across React and direct fetches, multiple error handling strategies, and a declarative API repository pattern—all in a single lightweight package._ - -| Feature | fetchff | ofetch | wretch | axios | native fetch() | swr | -| -------------------------------------------------- | ----------- | ----------- | ------------ | ------------ | -------------- | --------------- | -| **Unified API Client** | ✅ | -- | -- | -- | -- | -- | -| **Smart Request Cache** | ✅ | -- | -- | -- | -- | ✅ | -| **Automatic Request Deduplication** | ✅ | -- | -- | -- | -- | ✅ | -| **Revalidation on Window Focus** | ✅ | -- | -- | -- | -- | ✅ | -| **Custom Fetching Adapter** | ✅ | -- | -- | -- | -- | ✅ | -| **Built-in Error Handling** | ✅ | -- | ✅ | -- | -- | -- | -| **Customizable Error Handling** | ✅ | -- | ✅ | ✅ | -- | ✅ | -| **Retries with exponential backoff** | ✅ | -- | -- | -- | -- | -- | -| **Advanced Query Params handling** | ✅ | -- | -- | -- | -- | -- | -| **Custom Response Based Retry logic** | ✅ | ✅ | ✅ | -- | -- | -- | -| **Easy Timeouts** | ✅ | ✅ | ✅ | ✅ | -- | -- | -| **Adaptive Timeouts (Connection-aware)** | ✅ | -- | -- | -- | -- | -- | -| **Conditional Polling Functionality** | ✅ | -- | -- | -- | -- | -- | -| **Easy Cancellation of stale (previous) requests** | ✅ | -- | -- | -- | -- | -- | -| **Default Responses** | ✅ | -- | -- | -- | -- | ✅ | -| **Custom adapters (fetchers)** | ✅ | -- | -- | ✅ | -- | ✅ | -| **Global Configuration** | ✅ | -- | ✅ | ✅ | -- | ✅ | -| **TypeScript Support** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| **Built-in AbortController Support** | ✅ | -- | -- | -- | -- | -- | -| **Request Interceptors** | ✅ | ✅ | ✅ | ✅ | -- | -- | -| **Safe deduping + cancellation** | ✅ | -- | -- | -- | -- | -- | -| **Response-based polling decisions** | ✅ | -- | -- | -- | -- | -- | -| **Request/Response Data Transformation** | ✅ | ✅ | ✅ | ✅ | -- | -- | -| **Works with Multiple Frameworks** | ✅ | ✅ | ✅ | ✅ | ✅ | -- | -| **Works across multiple instances or layers** | ✅ | -- | -- | -- | -- | -- (only React) | -| **Concurrent Request Deduplication** | ✅ | -- | -- | -- | -- | ✅ | -| **Flexible Error Handling Strategies** | ✅ | -- | ✅ | ✅ | -- | ✅ | -| **Dynamic URLs with Path and query separation** | ✅ | -- | ✅ | -- | -- | -- | -| **Automatic Retry on Failure** | ✅ | ✅ | -- | ✅ | -- | ✅ | -| **Automatically handle 429 Retry-After headers** | ✅ | -- | -- | -- | -- | -- | -| **Built-in Input Sanitization** | ✅ | -- | -- | -- | -- | -- | -| **Prototype Pollution Protection** | ✅ | -- | -- | -- | -- | -- | -| **RFC 7231 Safe Methods Auto-execution** | ✅ | -- | -- | -- | -- | -- | -| **First Class React Integration** | ✅ | -- | -- | -- | -- | ✅ | -| **Shared cache for React and direct fetches** | ✅ | -- | -- | -- | -- | -- | -| **Per-endpoint and per-request config merging** | ✅ | -- | -- | -- | -- | -- | -| **Declarative API repository pattern** | ✅ | -- | -- | -- | -- | -- | -| **Supports Server-Side Rendering (SSR)** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| **SWR Pattern Support** | ✅ | -- | -- | -- | -- | ✅ | -| **Revalidation on Tab Focus** | ✅ | -- | -- | -- | -- | ✅ | -| **Revalidation on Network Reconnect** | ✅ | -- | -- | -- | -- | ✅ | -| **Minimal Installation Size** | 🟢 (5.2 KB) | 🟡 (6.5 KB) | 🟢 (2.21 KB) | 🔴 (13.7 KB) | 🟢 (0 KB) | 🟡 (6.2 KB) | +_fetchff uniquely combines advanced input sanitization, prototype pollution protection, a cache shared by React and direct fetches, ETag revalidation, multiple error handling strategies, a declarative API repository pattern and endpoints typed from OpenAPI schemas—all in a single lightweight package._ + +| Feature | fetchff | TanStack Query | axios | swr | ofetch | wretch | native fetch() | +| -------------------------------------------------- | ----------- | -------------- | ------------ | --------------- | ----------- | ----------- | -------------- | +| **Unified API Client** | ✅ | -- | -- | -- | -- | -- | -- | +| **Smart Request Cache** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Automatic Request Deduplication** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Revalidation on Window Focus** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Custom Fetching Adapter** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -- | +| **Built-in Error Handling** | ✅ | -- | -- | -- | -- | ✅ | -- | +| **Customizable Error Handling** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -- | +| **Retries with exponential backoff** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Advanced Query Params handling** | ✅ | -- | -- | -- | -- | -- | -- | +| **Custom Response Based Retry logic** | ✅ | ✅ | -- | ✅ | ✅ | ✅ | -- | +| **Easy Timeouts** | ✅ | -- | ✅ | -- | ✅ | ✅ | -- | +| **Adaptive Timeouts (Connection-aware)** | ✅ | -- | -- | -- | -- | -- | -- | +| **Conditional Polling Functionality** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Easy Cancellation of stale (previous) requests** | ✅ | ✅ | -- | -- | -- | -- | -- | +| **Default Responses** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Global Configuration** | ✅ | ✅ | ✅ | ✅ | -- | ✅ | -- | +| **TypeScript Support** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **Built-in AbortController Support** | ✅ | ✅ | -- | -- | -- | -- | -- | +| **Request Interceptors** | ✅ | -- | ✅ | -- | ✅ | ✅ | -- | +| **Safe deduping + cancellation** | ✅ | ✅ | -- | -- | -- | -- | -- | +| **Response-based polling decisions** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Request/Response Data Transformation** | ✅ | ✅ | ✅ | -- | ✅ | ✅ | -- | +| **Works with Multiple Frameworks** | ✅ | ✅ | ✅ | -- | ✅ | ✅ | ✅ | +| **Works across multiple instances or layers** | ✅ | ✅ | -- | -- (only React) | -- | -- | -- | +| **Flexible Error Handling Strategies** | ✅ | ✅ | ✅ | ✅ | -- | ✅ | -- | +| **Dynamic URLs with Path and query separation** | ✅ | -- | -- | -- | -- | ✅ | -- | +| **Automatic Retry on Failure** | ✅ | ✅ | -- | ✅ | ✅ | -- | -- | +| **Automatically handle 429 Retry-After headers** | ✅ | -- | -- | -- | -- | -- | -- | +| **Built-in Input Sanitization** | ✅ | -- | -- | -- | -- | -- | -- | +| **Prototype Pollution Protection** | ✅ | -- | -- | -- | -- | -- | -- | +| **RFC 7231 Safe Methods Auto-execution** | ✅ | -- | -- | -- | -- | -- | -- | +| **First Class React Integration** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Shared cache for React and direct fetches** | ✅ | ✅ | -- | -- | -- | -- | -- | +| **Per-endpoint and per-request config merging** | ✅ | -- | -- | -- | -- | -- | -- | +| **Declarative API repository pattern** | ✅ | -- | -- | -- | -- | -- | -- | +| **Supports Server-Side Rendering (SSR)** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **SWR Pattern Support** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Revalidation on Network Reconnect** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Pause Polling in Hidden Tabs and Offline** | ✅ | ✅ | -- | ✅ | -- | -- | -- | +| **Throttled Revalidation on Focus** | ✅ | -- | -- | ✅ | -- | -- | -- | +| **Slow Request Callback** | ✅ | -- | -- | ✅ | -- | -- | -- | +| **ETag Revalidation (`304` reuses cached data)** | ✅ | -- | -- | -- | -- | -- | -- | +| **Persistent Cache (localStorage, IndexedDB, …)** | ✅ | ✅ (plugin) | -- | ✅ | -- | -- | -- | +| **Upload Progress** | ✅ | -- | ✅ | -- | -- | 🟡 ¹ | -- | +| **Download Progress** | ✅ | -- | ✅ | -- | -- | ✅ | -- | +| **Typed Endpoints from OpenAPI Schemas** | ✅ | -- | -- | -- | -- | -- | -- | +| **No Third-party Dependencies** | ✅ | ✅ | -- | -- | -- | ✅ | ✅ | +| **Bundle Size (minified + gzipped) ²** | 🟢 (8.9 KB) | 🔴 (13.6 KB) | 🔴 (19.5 KB) | 🟢 (6.5 KB) | 🟢 (4.1 KB) | 🟢 (1.8 KB) | 🟢 (0 KB) | + +¹ Only where request bodies can be streamed: in Chromium over HTTPS and in Node.js. + +² The whole library bundled with esbuild, minified and gzipped, without React: 🟢 under 10 KB, 🟡 10–13 KB, 🔴 over 13 KB. Measured with fetchff 4.3.0, @tanstack/react-query 5.104.0, axios 1.20.0, swr 2.5.1, ofetch 1.5.1 and wretch 3.0.9. fetchff with its React hook is 9.7 KB. swr and TanStack Query also need an HTTP client, e.g. native `fetch()`. ## ✏️ Examples diff --git a/dist/browser/index.global.js b/dist/browser/index.global.js index 5a252c2..10c75a5 100644 --- a/dist/browser/index.global.js +++ b/dist/browser/index.global.js @@ -1,3 +1,3 @@ -var fetchff=(function(exports){'use strict';var Pt=Object.defineProperty;var ht=(e,t,r)=>t in e?Pt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var q=(e,t,r)=>ht(e,typeof t!="symbol"?t+"":t,r);var N="application/",X=N+"json",Ne="charset=utf-8",B="Content-Type",E="undefined",Z="object",T="string",b="function",ie="AbortError",He="TimeoutError",H="GET",Me="HEAD",ue="reject",le=2147483647;var Le=10,A=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);function M(e){return e instanceof URLSearchParams}function y(e){return e!==null&&typeof e===Z}function w(e){let t=A(e,"__proto__"),r=A(e,"constructor"),a=A(e,"prototype");if(!t&&!r&&!a)return e;let n={};for(let s of Object.keys(e))s!=="__proto__"&&s!=="constructor"&&s!=="prototype"&&(n[s]=e[s]);return n}function je(e){let t=Object.create(null);return Object.keys(e).sort().forEach(r=>t[r]=e[r]),t}function Ue(e,t){return t?e+(e.includes("?")?"&":"?")+t:e}function Ke(e,t){if(!t)return e;if(M(t)){let c=t.toString();return Ue(e,c)}let r=[],a=encodeURIComponent,n=(c,u)=>{u=typeof u===b?u():u,u=u===null||u===void 0?"":u,r[r.length]=a(c)+"="+a(u);},s=(c,u,m=0)=>{if(m>=Le)return r;let l,d,h;if(c)if(Array.isArray(u))for(l=0,d=u.length;l{if(A(r,n)){let s=r[n];if(s!=null){let o=encodeURIComponent(String(s));if(o==="."||o==="..")throw new Error('Path params "." and ".." not allowed.');return o}}return a})}function ze(e){return /^[a-z][a-z\d+\-.]*:\/\//i.test(e)}var R=()=>Date.now(),U=()=>{};function V(e){let t=typeof e;return e==null?false:t===T||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==E&&typeof globalThis.Buffer!==E&&globalThis.Buffer.isBuffer(e)||e instanceof Date||M(e)?false:!!(y(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===b))}var L=e=>new Promise(t=>setTimeout(t,Math.min(e,le),true));function Ee(e,t=0){return t>=Le?e:e&&y(e)&&typeof e.data!==E?Ee(e.data,t+1):e}function x(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else for(let r in e)A(e,r)&&r!=="__proto__"&&(t[r.toLowerCase()]=e[r]);return t}function Je(){return typeof window!==E&&typeof window.addEventListener===b}function ce(e,t){if(typeof DOMException!==E)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var be=()=>{let e=typeof navigator!==E&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function O(e,t,...r){if(!e)return;let a=n=>n&&y(t)&&y(n)&&Object.assign(t,w(n));if(typeof e===b)a(await e(t,...r));else if(Array.isArray(e))for(let n of e)a(await n(t,...r));}var fe=class extends Error{constructor(r,a,n){super(r);q(this,"request",a);q(this,"response",n);q(this,"status");q(this,"statusText");q(this,"config");q(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var me=class extends fe{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ye=600,de=1e3,xe=Array(ye).fill(0).map(()=>[]),F=new Map,pe=0,Te=0,C=null,Ye=([e,t])=>{F.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(U);}catch(r){}},v=(e,t,r)=>{j(e);let a=r/de+(C&&R()!==Te?1:0);if(r=ye||r%de!==0){F.set(e,[setTimeout(Ye.bind(null,[e,t]),Math.min(r,le))]);return}let n=(pe+a)%ye;xe[n].push([e,t]),F.set(e,n),C||(Te=R(),C=setInterval(()=>{pe=(pe+1)%ye,Te=R();let s=xe[pe];for(let o=0;o{let t=F.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=xe[t];for(let a=0;a{We(e,ce(t+" aborted due to timeout",He));},r),u}async function We(e,t=null){if(e){let r=K.get(e);r&&(t&&r[0].abort(t),Re(e));}}function Re(e){j(e),K.delete(e);}function Xe(e,t){let r=K.get(e);r&&(r[4]=t);}function we(e,t){if(!e)return null;let r=K.get(e);return r&&r[4]&&!r[3]&&R()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(U);});}async function Pe(e,t=false){if(!e)return null;let r=J.get(e);if(r){r[1]=R();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function Dt(e){et(e);let t=e==="focus"?5:6;J.forEach((r,a)=>{r[t]&&Et(a);});}function Ce(e){if(z.has(e))return;let t=$e.bind(null,e,true),r=Ve.get(e);if(r){let a=r(t);z.set(e,a);return}Je()&&(window.addEventListener(e,t),z.set(e,()=>window.removeEventListener(e,t)));}function et(e){let t=z.get(e);t&&(t(),z.delete(e));}function tt(e,t,r,a,n,s,o){let i=J.get(e);i?(i[0]=t,i[1]=R(),i[2]=Ze,i[3]=a,i[4]=n,i[5]=s,i[6]=o):J.set(e,[t,R(),Ze,a,n,s,o]),s&&Ce("focus"),o&&Ce("online"),a&&v("s:"+e,Pe.bind(null,e,true),a*1e3);}function Et(e){J.delete(e),j("s:"+e);}var $=new Map;function bt(e,t){let r=$.get(e);r||$.set(e,r=new Set),r.add(t);}function Tt(e,t){let r=$.get(e);r&&(r.delete(t),r.size===0&&$.delete(e));}function Y(e,t){let r=$.get(e);if(r)if(r.size===1){let a=r.values().next().value;a(t);}else r.forEach(a=>a(t));}function xt(e,t){return e?(bt(e,t),()=>{Tt(e,t);}):U}var Ae=(be()?60:30)*1e3,S={strategy:ue,timeout:Ae,headers:{Accept:X+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:Ae/30,maxDelay:Ae,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function wt(e){let t=w(e);return G({retry:S.retry,headers:S.headers},t,S)}function Ct(){return {...S}}function qe(e,t){let r=G(S,t?w(t):{});return At(e,r)}function At(e,t){var m;let r=t.method;r=r?r.toUpperCase():H;let a;r!==H&&r!==Me&&(a=(m=t.body)!=null?m:t.data,a&&typeof a!==T&&V(a)&&(a=JSON.stringify(a))),It(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=ke(e,t.urlPathParams),o=Ke(s,t.params),c=ze(e)?"":t.baseURL||t.apiUrl||"",u=c&&o&&!c.endsWith("/")&&!/^[/?#]/.test(o)?"/":"";return t.url=c+u+o,t.method=r,t.credentials=n,t.body=a,t}function It(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==E&&t instanceof Blob||typeof File!==E&&t instanceof File||typeof ReadableStream!==E&&t instanceof ReadableStream)return;let r;if(M(t))r=N+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=N+"octet-stream";else if(V(t))r=X+";"+Ne;else return;e instanceof Headers?e.has(B)||e.set(B,r):y(e)&&!Array.isArray(e)&&!x(e)[B.toLowerCase()]&&(e[B]=r);}function G(e,t,r={}){return Object.assign(r,e,t),rt("retry",e,t,r),rt("headers",e,t,r),Ie("onRequest",e,t,r),Ie("onResponse",e,t,r),Ie("onError",e,t,r),r}function Ie(e,t,r,a){let n=t[e],s=r[e];if(!n&&!s)return;if(!n){a[e]=s;return}if(!s){a[e]=n;return}let o=Array.isArray(n)?n:[n],i=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?i.concat(o):o.concat(i);}function rt(e,t,r,a){let n=t[e],s=r[e];if(s)if(e==="headers"){let o=n instanceof Headers||s instanceof Headers,i=o?x(n):{...n},c=o?x(s):w(s);for(let u of Object.keys(c)){let m=u.toLowerCase();for(let l in i)l.toLowerCase()===m&&delete i[l];i[u]=c[u];}a[e]=i;}else a[e]={...n,...w(s)};else s===void 0&&y(n)&&!(n instanceof Headers)&&(a[e]={...n});}var he=new Map,I="|",Be=64,qt=/[^\w\-_|/:@.?=&~%#]/g,Bt=/[^\w\-_|/:@.?=&~%#]/,Ot=new Set(["accept","accept-language","accept-encoding","authorization","content-type","referer","origin","user-agent","cookie","x-api-key","x-requested-with","x-client-id","x-tenant-id","x-user-id","x-app-version","x-feature-flag","x-device-id","x-platform","x-session-id","x-locale"]);function te(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===T?r:r(e);let{url:a="",method:n=H,headers:s=null,body:o=null,credentials:i="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=x(s):l=s;let d=Object.keys(l),h=d.length;h>1&&d.sort();let f="";for(let D=0;D{u+=d+"="+(typeof l===T?l:"F"+st(l))+"&";}),u.length>Be&&(u=k(u));else if(y(o)&&!V(o))u="B"+st(o);else {let l=y(o)?JSON.stringify(je(o)):String(o);u=l.length>Be?k(l):l;}let m=n+I+a+I+i+I+c+I+u;return nt(m)}var at=new WeakMap,Ft=0;function st(e){let t=at.get(e);return t||at.set(e,t=++Ft),t}function nt(e){return Bt.test(e)?e.replace(qt,"")+I+k(e):e}function ot(e){return e.expiry?R()>e.expiry:false}function re(e){return he.get(e)}function ge(e,t,r,a){if(r===0){ee(e);return}let n=R(),s=r?r*1e3:0,o=a?a*1e3:0;he.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&v("c:"+e,()=>{ee(e,true);},s);}function ee(e,t=false){if(t){let r=re(e);if(!r||!ot(r))return}he.delete(e);}async function Oe(e,t,r){if(!e)return null;let a=re(e);if(!a)return null;let n=y(t)?w(t):t,s={...a.data,data:n},o={...a,data:s};return he.set(e,o),Y(e,s),r&&r.refetch?await Pe(e):null}function ae(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||S.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=re(e);if(!n)return null;if(ot(n))return ee(e),null;let o=n.data;return o&&o.isFetching?null:o}function Fe(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;if(n&&(!r||t.cacheErrors)&&!(s&&s(e,t)))ge(a,e,n,t.staleTime);else {let i=re(a);i&&i.data&&i.data.isFetching&&ee(a);}Y(a,e),Re(a);let o=t._prevKey;o&&Re(o);}}async function it(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(B);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(X)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(N+"x-www-form-urlencoded"))&&typeof e.formData===b)a=await e.formData();else if(/^(image|video|audio)\/|octet-stream|pdf|zip/.test(r))a=await e.arrayBuffer();else if(a=await e.text(),typeof a===T){let s=a.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{a=JSON.parse(s);}catch(o){}}}catch(s){a=null;}return a}var ve=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Oe.bind(null,n);if(!e)return {ok:false,error:r,data:a!=null?a:null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===b&&e instanceof Response,i=e.data;a!==void 0&&(i==null||typeof i===Z&&Object.keys(i).length===0)&&(e.data=i=a),t.flattenResponse&&(e.data=i=Ee(i)),t.select&&(e.data=i=t.select(i));let c=x(e.headers);if(o){let u={body:e.body,bodyUsed:e.bodyUsed,ok:e.ok,redirected:e.redirected,type:e.type,url:e.url,status:e.status,statusText:e.statusText,blob:()=>Promise.resolve(i instanceof ArrayBuffer?new Blob([i]):new Blob),json:()=>Promise.resolve(i),text:()=>Promise.resolve(i),clone:()=>({...u}),arrayBuffer:()=>Promise.resolve(i instanceof ArrayBuffer?i:new ArrayBuffer(0)),formData:()=>Promise.resolve(i instanceof FormData?i:new FormData),bytes:()=>Promise.resolve(new Uint8Array(i instanceof ArrayBuffer?i:new ArrayBuffer(0))),error:r,data:i,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r};return u}return y(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e};function ut(e){let t=Date.parse(e)-R();return isNaN(t)?null:Math.max(0,Math.floor(t))}function vt(e){if(!e)return null;let t=e.headers||{},r=t["retry-after"];if(r){let o=Number(r);if(!isNaN(o)&&o>=0)return o*1e3;let i=ut(r);if(i!==null)return i}let a="ratelimit-reset",n=t[a+"-after"]||t["x-"+a+"-after"];if(n){let o=Number(n);if(!isNaN(o))return o*1e3}let s=t[a+"-at"]||t["x-"+a+"-at"];return s?ut(s):null}async function lt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:i}=t,c=0,u=a,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await O(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=te(f,false)));}l=await e(c>0,c);let d=l.error;if(!d){if(i&&c0&&await L(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await L(t);return o}async function ft(e,t,r){var i,c;let a=await t(e),n=a.error;if(!n)return Fe(a,r),a;r.onError&&await O(r.onError,n);let s=n.isCancelled;if(!s&&((i=r.logger)!=null&&i.warn)&&r.logger.warn("FETCH ERROR",_t(n)),r.strategy==="defaultResponse"&&(a.data=(c=r.defaultResponse)!=null?c:null),Fe(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ue)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}var Qt=["authorization","proxy-authorization","cookie","x-api-key"];function _t(e){let t={...e.config,body:void 0,data:void 0,cacheKey:void 0,_prevKey:void 0,headers:x(e.config.headers)};for(let a of Qt)t.headers[a]&&(t.headers[a]="[REDACTED]");let r=Object.assign(new Error(e.message),e,{config:t,request:t,response:e.response&&{...e.response,config:t}});return r.name=e.name,r.stack=e.stack,r}function mt(e,t,r){e.status=e.status||(t==null?void 0:t.status)||0,e.statusText=e.statusText||(t==null?void 0:t.statusText)||"",e.config=e.request=r,e.response=t,e.isCancelled=e.name===ie;}var Se=Object.freeze({isFetching:true});async function De(e,t=null){if(t&&typeof t.cacheKey=="string"){let P=ae(t.cacheKey,t.cacheTime,t);if(P)return P}let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:i,staleTime:c,refetchOnFocus:u,refetchOnReconnect:m,pollingInterval:l=0}=r,d=i!==void 0||c!==void 0,h=!!(s||a||o||d||n||u||m),f=null;if(h&&(f=te(r)),f&&d){let P=ae(f,i,r);if(P)return P}if(f&&o){let P=we(f,o);if(P)return P}let D=r.retry||{},{retries:dt=0,resetTimeout:pt}=D,Qe=async(P,ne=0)=>{ne||(f&&!P&&(c?ae(f,i,r)||(ge(f,Se,i,c),Y(f,Se)):Y(f,Se)),r.cacheKey=f);let Q=r.url,Rt=Ge(f,Q,a,o||0,!!n,!!(a&&(!ne||pt))),g=r;g.signal=Rt.signal;let oe,p=null;try{r.onRequest&&(f&&o&&!ne&&await null,await O(r.onRequest,g));let _=r.fetcher;if(p=_?await _(Q,g):await fetch(Q,g),y(p)&&(typeof Response===b&&p instanceof Response?p.data=g.parser?await g.parser(p):await it(p):_&&("data"in p&&"body"in p||(p={data:p})),p.config=g,p.ok!==void 0&&!p.ok))throw new me(g.method+" to "+Q+" failed! Status: "+(p.status||null),g,p);oe=ve(p,g);let W=r.onResponse;W&&await O(W,oe);}catch(_){let W=_;mt(W,p,g),oe=ve(p,g,W);}return oe},yt=dt>0?P=>lt((ne,Q)=>Qe(P,Q),D):Qe,se=(P=false)=>ft(P,yt,r),_e=l?ct(se,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):se();return f&&(o&&Xe(f,_e),(c||u||m)&&tt(f,se,void 0,c,se,!!u,!!m)),_e}function Nt(e){let t=e.endpoints;function r(n){return console.error("Add "+n+" to 'endpoints'."),Promise.resolve(null)}let a={config:e,endpoints:t,async request(n,s={}){let o=A(t,n)?t[n]:void 0,i=o||{url:String(n)},c=i.url,u=c.replace(/[\t\n\r]/g,"").replace(/^[\x00-\x20]+/,"");if(/^[/\\]{2}/.test(u))throw new Error("Protocol-relative URLs not allowed.");let m=/^[a-z][a-z\d+\-.]*:/i.test(u)?(o==null?void 0:o.url)===c?G(i,s):s:G(G(e,i),s);return De(c,m)}};return new Proxy(a,{get(n,s){if(s in a)return a[s];if(!(typeof s=="symbol"||s==="then"))return A(t,s)?a.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=We;exports.addTimeout=v;exports.buildConfig=qe;exports.createAbortError=ce;exports.createApiFetcher=Nt;exports.deleteCache=ee;exports.fetchf=De;exports.fetchff=De;exports.generateCacheKey=te;exports.getCache=re;exports.getCachedResponse=ae;exports.getDefaultConfig=Ct;exports.getInFlightPromise=we;exports.isSlowConnection=be;exports.mutate=Oe;exports.removeRevalidators=Dt;exports.revalidate=Pe;exports.revalidateAll=$e;exports.setCache=ge;exports.setDefaultConfig=wt;exports.setEventProvider=gt;exports.subscribe=xt;return exports;})({});//# sourceMappingURL=index.global.js.map +var fetchff=(function(exports){'use strict';var z="application/",te=z+"json",et="charset=utf-8",_="Content-Type",D="undefined",Ie="object",x="string",b="function",k="AbortError",tt="TimeoutError",O="GET",re="HEAD",pe="reject",ye=2147483647;var st=10,S=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);function J(e){return e instanceof URLSearchParams}function g(e){return e!==null&&typeof e===Ie}function B(e){let t=S(e,"__proto__"),r=S(e,"constructor"),s=S(e,"prototype");if(!t&&!r&&!s)return e;let n={};for(let a of Object.keys(e))a!=="__proto__"&&a!=="constructor"&&a!=="prototype"&&(n[a]=e[a]);return n}function at(e){let t=Object.create(null);return Object.keys(e).sort().forEach(r=>t[r]=e[r]),t}function rt(e,t){return t?e+(e.includes("?")?"&":"?")+t:e}function nt(e,t){if(!t)return e;if(J(t)){let u=t.toString();return rt(e,u)}let r=[],s=encodeURIComponent,n=(u,c)=>{c=typeof c===b?c():c,c=c==null?"":c,r[r.length]=s(u)+"="+s(c);},a=(u,c,f=0)=>{if(f>=st)return r;let l,p,m;if(u)if(Array.isArray(c))for(l=0,p=c.length;l{let o=n||a;if(S(r,o)){let i=r[o];if(i!=null){let u=encodeURIComponent(String(i));if(u==="."||u==="..")throw new Error('Path params "." and ".." not allowed.');return u}}return s})}function it(e){return /^[a-z][a-z\d+\-.]*:\/\//i.test(e)}var h=()=>Date.now(),C=()=>{};function se(e){let t=typeof e;return e==null?false:t===x||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==D&&typeof globalThis.Buffer!==D&&globalThis.Buffer.isBuffer(e)||e instanceof Date||J(e)?false:!!(g(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===b))}var ae=(e,t)=>new Promise(r=>{let s=()=>{clearTimeout(n),t&&t.removeEventListener("abort",s),r(true);},n=setTimeout(s,Math.min(e,ye));t&&(t.aborted?s():t.addEventListener("abort",s));});function ve(e,t=0){return t>=st?e:e&&g(e)&&typeof e.data!==D?ve(e.data,t+1):e}function E(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,s)=>{t[s.toLowerCase()]=r;});else for(let r in e)S(e,r)&&r!=="__proto__"&&(t[r.toLowerCase()]=e[r]);return t}function ut(){return typeof window!==D&&typeof window.addEventListener===b}function W(e,t){if(typeof DOMException!==D)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Se=()=>{let e=typeof navigator!==D&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)},ct=()=>typeof document!==D&&document.visibilityState==="hidden",lt=()=>typeof navigator!==D&&navigator.onLine===false;async function F(e,t,...r){if(!e)return;let s=n=>n&&g(t)&&g(n)&&Object.assign(t,B(n));if(typeof e===b)s(await e(t,...r));else if(Array.isArray(e))for(let n of e)s(await n(t,...r));}var Re=class extends Error{constructor(t,r,s){super(t),this.request=r,this.response=s,this.status=s?s.status:0,this.statusText=s?s.statusText:"",this.config=r,this.isCancelled=false,this.name="FetchError";}};var he=class extends Re{constructor(t,r,s){super(t,r,s),this.name="ResponseError";}};var be=600,Pe=1e3,Qe=Array(be).fill(0).map(()=>[]),U=new Map,ge=0,Fe=0,A=null,ft=([e,t])=>{U.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(C);}catch(r){}},M=(e,t,r)=>{Y(e);let s=r/Pe+(A&&h()!==Fe?1:0);if(r=be||r%Pe!==0){U.set(e,[setTimeout(ft.bind(null,[e,t]),Math.min(r,ye))]);return}let n=(ge+s)%be;Qe[n].push([e,t]),U.set(e,n),A||(Fe=h(),A=setInterval(()=>{ge=(ge+1)%be,Fe=h();let a=Qe[ge];for(let o=0;o{let t=U.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Qe[t];for(let s=0;s{mt(e,W(t+" aborted due to timeout",tt));},r),c}async function mt(e,t=null){if(e){let r=G.get(e);r&&(t&&r[0].abort(t),De(e));}}function De(e){Y(e),G.delete(e);}function pt(e,t){let r=G.get(e);r&&(r[4]=t);}function He(e,t){if(!e)return null;let r=G.get(e);return r&&r[4]&&!r[3]&&h()-r[2]{if(!a[s]||r&&n-a[1]{r[t]&&Kt(s);});}function Ne(e){if(V.has(e))return;let t=Rt.bind(null,e,true,e==="focus"),r=yt.get(e);if(r){let s=r(t);V.set(e,s);return}ut()&&(window.addEventListener(e,t),V.set(e,()=>window.removeEventListener(e,t)));}function ht(e){let t=V.get(e);t&&(t(),V.delete(e));}function Pt(e,t,r,s,n,a,o,i){let u=Z.get(e)||[];u[0]=t,u[1]=h(),u[2]=Mt,u[3]=s,u[4]=n,u[5]=a,u[6]=o,u[7]=i,Z.set(e,u),a&&Ne("focus"),o&&Ne("online"),s&&M("s:"+e,Ee.bind(null,e,true),s*1e3);}function Kt(e){Z.delete(e),Y("s:"+e);}var ne=new Map;function zt(e,t){let r=ne.get(e);r||ne.set(e,r=new Set),r.add(t);}function kt(e,t){let r=ne.get(e);r&&(r.delete(t),r.size===0&&ne.delete(e));}function L(e,t){let r=ne.get(e);if(r)if(r.size===1){let s=r.values().next().value;s(t);}else r.forEach(s=>s(t));}function Jt(e,t){return e?(zt(e,t),()=>{kt(e,t);}):C}var Te=(Se()?60:30)*1e3,j={strategy:pe,timeout:Te,loadingTimeout:Te/10,focusThrottleInterval:5e3,headers:{Accept:te+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:Te/30,maxDelay:Te,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504],methods:[O,re,"PUT","DELETE","OPTIONS","TRACE"]}};function Wt(e){let t=B(e);return $({retry:j.retry,headers:j.headers},t,j)}function Yt(){return {...j}}function _e(e,t){let r=$(j,t?B(t):{});return Gt(e,r)}function Gt(e,t){var f;let r=t.method;r=r?r.toUpperCase():O;let s;r!==O&&r!==re&&(s=(f=t.body)!=null?f:t.data,s&&typeof s!==x&&se(s)&&(s=JSON.stringify(s))),Xt(t.headers,s);let n=t.withCredentials?"include":t.credentials,a=ot(e,t.urlPathParams),o=nt(a,t.params),u=it(e)?"":t.baseURL||t.apiUrl||"",c=u&&o&&!u.endsWith("/")&&!/^[/?#]/.test(o)?"/":"";return t.url=u+c+o,t.method=r,t.credentials=n,t.body=s,t}function Xt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==D&&t instanceof Blob||typeof ReadableStream!==D&&t instanceof ReadableStream)return;let r;if(J(t))r=z+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=z+"octet-stream";else if(se(t))r=te+";"+et;else return;e instanceof Headers?e.has(_)||e.set(_,r):g(e)&&!Array.isArray(e)&&!E(e)[_.toLowerCase()]&&(e[_]=r);}var Vt=["onRequest","onResponse","onError","onLoadingSlow"];function $(e,t,r={}){Object.assign(r,e,t),gt("retry",e,t,r),gt("headers",e,t,r);for(let s of Vt)Zt(s,e,t,r);return r}function Zt(e,t,r,s){let n=t[e],a=r[e];n&&a?s[e]=e==="onResponse"?[].concat(a,n):[].concat(n,a):(n||a)&&(s[e]=n||a);}function gt(e,t,r,s){let n=t[e],a=r[e];if(a)if(e==="headers"){let o=n instanceof Headers||a instanceof Headers,i=o?E(n):{...n},u=o?E(a):B(a);for(let c of Object.keys(u)){let f=c.toLowerCase();for(let l in i)l.toLowerCase()===f&&delete i[l];i[c]=u[c];}s[e]=i;}else s[e]={...n,...B(a)};else a===void 0&&g(n)&&!(n instanceof Headers)&&(s[e]={...n});}var Q=new Map,ie=new Map,oe="|",Ue=64,$t=/[^\w\-_|/:@.?=&~%#]/g,er=/[^\w\-_|/:@.?=&~%#]/,tr=/^(accept(-language|-encoding)?|authorization|content-type|referer|origin|user-agent|cookie|x-(api-key|requested-with|client-id|tenant-id|user-id|app-version|feature-flag|device-id|platform|session-id|locale))$/i;function ue(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===x?r:r(e);let{url:s="",method:n=O,headers:a=null,body:o=null,credentials:i="same-origin"}=e,u="";if(a){let l;a instanceof Headers?l=E(a):l=a;let p=Object.keys(l),m=p.length;m>1&&p.sort();let q="";for(let T=0;T{f+=p+"="+(typeof l===x?l:"F"+Dt(l))+"&";}),f.length>Ue&&(f=X(f));else if(g(o)&&!se(o))f="B"+Dt(o);else {let l=g(o)?JSON.stringify(at(o)):String(o);f=l.length>Ue?X(l):l;}return Et(c+oe+f)}var bt=new WeakMap,rr=0;function Dt(e){let t=bt.get(e);return t||bt.set(e,t=++rr),t}function Et(e){return er.test(e)?e.replace($t,"")+oe+X(e):e}function Me(e){return e.expiry?h()>e.expiry:false}function Le(e){if(!e)return null;let t=Q.get(e);return t?t.data:null}function ce(e){return Q.get(e)}function we(e,t,r,s){if(r===0){le(e);return}let n=h(),a=r?r*1e3:0,o=s?s*1e3:0;Q.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+a}),a>0&&Tt(e,a);}function Tt(e,t){M("c:"+e,()=>le(e,true),t);}function le(e,t=false){if(t){let s=ce(e);if(!s||!Me(s))return}Q.delete(e);let r=ie.get(e);r&&(ie.delete(e),je(()=>r.delete(e)));}function je(e){try{Promise.resolve(e()).catch(C);}catch(t){}}function wt(e,t){let r=Q.get(e);if(t&&r){let{data:s,status:n,statusText:a,headers:o}=r.data;ie.set(e,t),je(()=>t.set(e,{...r,data:{data:s,status:n,statusText:a,headers:o}}));}}async function xt(e,t){let r=t.cacheStore;if(!r||xe(t))return null;let s;try{s=await r.get(e);}catch(n){return null}return !s||Q.has(e)?null:Me(s)?(je(()=>r.delete(e)),null):s}function Ct(e,t,r){return Q.set(e,t),ie.set(e,r),t.expiry&&Tt(e,t.expiry-h()),L(e,t.data),!t.stale||h(){let s=t.defaultResponse,n=t.cacheKey,a=Ke.bind(null,n);if(!e)return {ok:false,error:r,data:s!=null?s:null,headers:null,config:t,mutate:a,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===b&&e instanceof Response,i=e.data;s!==void 0&&(i==null||/^\[object (Object|Array)\]$/.test(Object.prototype.toString.call(i))&&Object.keys(i).length===0)&&(e.data=i=s),t.flattenResponse&&(e.data=i=ve(i)),t.select&&(e.data=i=t.select(i));let u=E(e.headers);if(o){let c={body:e.body,bodyUsed:e.bodyUsed,ok:e.ok,redirected:e.redirected,type:e.type,url:e.url,status:e.status,statusText:e.statusText,blob:async()=>i instanceof ArrayBuffer?new Blob([i]):new Blob,json:async()=>i,text:async()=>i,clone:()=>({...c}),arrayBuffer:async()=>i instanceof ArrayBuffer?i:new ArrayBuffer(0),formData:async()=>i instanceof FormData?i:new FormData,bytes:async()=>new Uint8Array(i instanceof ArrayBuffer?i:new ArrayBuffer(0)),error:r,data:i,headers:u,config:t,mutate:a,isFetching:false,isSuccess:e.ok&&!r,isError:!!r};return c}return g(e)&&(e.error=r,e.headers=u,e.isFetching=false,e.mutate=a,e.isSuccess=e.ok&&!r,e.isError=!!r),e};function Ot(e){let t=Date.parse(e)-h();return isNaN(t)?null:Math.max(0,Math.floor(t))}function sr(e){if(!e)return null;let t=e.headers||{},r=t["retry-after"];if(r){let o=Number(r);if(!isNaN(o)&&o>=0)return o*1e3;let i=Ot(r);if(i!==null)return i}let s="ratelimit-reset",n=t[s+"-after"]||t["x-"+s+"-after"];if(n){let o=Number(n);if(!isNaN(o))return o*1e3}let a=t[s+"-at"]||t["x-"+s+"-at"];return a?Ot(a):null}async function Bt(e,t){let{retries:r=0,delay:s=0,backoff:n=1,maxDelay:a,retryOn:o=[],shouldRetry:i,jitter:u,methods:c}=t,f=0,l=s,p=r>0?r:0,m;for(;f<=p;){if(f>0&&m){let d=m.config,H=d.onRetry;H&&(await F(H,m,f),d._isAutoKey&&(d._prevKey=d.cacheKey,d.cacheKey=ue(d,false)));}m=await e(f>0,f);let q=m.error;if(q?await ar(m,f,p,i,o,c):!(i&&fc.toUpperCase()===e.config.method)))}function nr(e,t){return typeof t===b?t(e):t?Math.random()*e:e}async function At(e,t,r,s=0,n=0,a=false,o=false,i){if(!t)return e();let u=0,c;for(;(s===0||u0&&await ae(n,i),c=await e(),u++,!(s>0&&u>=s||!t||r&&r(c,u)));)do if(await ae(t,i),i&&i.aborted)return c;while(!a&&ct()||!o&<());return c}var or=[204,205,304],ir=/^(accept-charset|accept-encoding|connection|content-length|cookie2?|date|dnt|expect|host|keep-alive|origin|referer|set-cookie|te|trailer|transfer-encoding|upgrade|via)$|^(proxy-|sec-|access-control-request-)/,It=e=>typeof ReadableStream!==D&&e instanceof ReadableStream,qe=(e,t)=>({loaded:e,total:t,progress:t?e/t:void 0});function vt(e,t){let r=t.body;return typeof XMLHttpRequest!==D&&!It(r)?ur(e,t,r):cr(e,t,r)}function ur(e,t,r){return new Promise((s,n)=>{let a=new XMLHttpRequest,o=t.signal,i=()=>a.abort(),u=f=>{o.removeEventListener("abort",i);try{f();}catch(l){n(l);}};a.open(t.method,e),a.responseType="blob",a.withCredentials=t.credentials==="include",new Headers(t.headers).forEach((f,l)=>ir.test(l)||a.setRequestHeader(l,f)),a.upload.onprogress=f=>t.onUploadProgress(qe(f.loaded,f.lengthComputable?f.total:void 0)),a.onload=()=>u(()=>{let f=new Headers;for(let p of a.getAllResponseHeaders().split(/\r?\n/)){let m=p.indexOf(":");m>0&&f.append(p.slice(0,m),p.slice(m+1).trim());}let l=new Response(or.includes(a.status)?null:a.response,{status:a.status,statusText:a.statusText,headers:f});Object.defineProperty(l,"url",{value:a.responseURL}),s(l);}),a.onerror=()=>u(()=>n(new TypeError("Network request failed")));let c=()=>u(()=>n(o.reason||W("The request was aborted",k)));if(a.onabort=c,o.aborted)return c();o.addEventListener("abort",i),a.send(r);})}async function cr(e,t,r){let s=new Headers(t.headers),n=r,a;if(!It(r)){let i=r instanceof Blob?r:await new Response(r).blob();a=i.size,n=i.stream(),i.type&&!s.has("content-type")&&s.set("content-type",i.type);}let o=0;return fetch(e,{...t,headers:s,body:n.pipeThrough(new TransformStream({transform(i,u){o+=i.byteLength,t.onUploadProgress(qe(o,a)),u.enqueue(i);}})),duplex:"half"})}function St(e,t){if(!t||typeof Response!==b||!(e instanceof Response)||!e.body)return e;let r=e.headers,s=r.has("content-encoding")?void 0:Number(r.get("content-length"))||void 0,n=0,a=new Response(e.body.pipeThrough(new TransformStream({transform(o,i){n+=o.byteLength,t(qe(n,s&&Math.max(s,n))),i.enqueue(o);}})),e);for(let o of ["url","redirected","type"])Object.defineProperty(a,o,{value:e[o]});return a}async function Ft(e,t,r){var u;let s=await t(e),n=s.error;if(!n)return ze(s,r),s;r.onError&&await F(r.onError,n);let a=n.isCancelled,o=r.logger;if(!a&&o&&o.warn&&o.warn("FETCH ERROR",fr(n)),r.strategy==="defaultResponse"&&(s.data=(u=r.defaultResponse)!=null?u:null),ze(s,r,true),!a||r.rejectCancelled){let c=r.strategy;if(c===pe)throw n;c==="silent"&&await new Promise(()=>null);}return s}var lr=["authorization","proxy-authorization","cookie","x-api-key"];function fr(e){let t={...e.config,body:void 0,data:void 0,cacheKey:void 0,_prevKey:void 0,headers:E(e.config.headers)};for(let s of lr)t.headers[s]&&(t.headers[s]="[REDACTED]");let r=Object.assign(new Error(e.message),e,{config:t,request:t,response:e.response&&{...e.response,config:t}});return r.name=e.name,r.stack=e.stack,r}function Qt(e,t,r){e.status=e.status||t&&t.status||0,e.statusText=e.statusText||t&&t.statusText||"",e.config=e.request=r,e.response=t,e.isCancelled=e.name===k;}var ke=Object.freeze({isFetching:true});async function Oe(e,t=null){var Ve;if(t&&typeof t.cacheKey=="string"){let R=fe(t.cacheKey,t.cacheTime,t);if(R)return R}let r=_e(e,t),{timeout:s,cancellable:n,cacheKey:a,dedupeTime:o,cacheTime:i,staleTime:u,refetchOnFocus:c,refetchOnReconnect:f,pollingInterval:l=0}=r,p=i!==void 0||u!==void 0,m=r.method,q=p&&(m===O||m===re)&&((Ve=r.etag)!=null?Ve:!r.fetcher),T=!!(a||s||o||p||n||c||f),d=null;T&&(d=ue(r));let H=null;if(d&&p){let R=fe(d,i,r);if(R)return R;if(r.cacheStore){let w=await xt(d,r),I=w&&Ht(w.data,d,r);if(I&&Ct(d,{...w,data:I},r.cacheStore))return I}r.initialData!==void 0&&!Le(d)&&!xe(r)&&(H=Ht({data:r.initialData,status:200,statusText:"",headers:{}},d,r));}if(d&&o){let R=He(d,o);if(R)return R}let Je=r.retry||{},{retries:Nt=0,resetTimeout:_t}=Je,N=r.signal,We=async(R,w=0)=>{let I=q&&Le(d);if(!w){if(H){let v=H;return H=null,v}d&&!R&&(u?fe(d,i,r)||(we(d,ke,i,u),L(d,ke)):L(d,ke)),r.cacheKey=d;}let ee=r.url,Ze=dt(d,ee,s,o||0,!!n,!!(s&&(!w||_t))),P=r;P.signal=Ze.signal;let Ae=()=>Ze.abort(N.reason);N&&(N.aborted?Ae():N.addEventListener("abort",Ae));let me,y=null;try{r.onRequest&&(d&&o&&!w&&await null,await F(r.onRequest,P));let v=r.fetcher,K=dr(P,I);if(y=v?await v(ee,K):await(P.onUploadProgress&&P.body?vt(ee,P):fetch(ee,K)),y=St(y,P.onDownloadProgress),g(y)){if(K!==P&&y.status===304)return I;if(typeof Response===b&&y instanceof Response?y.data=P.parser?await P.parser(y):await qt(y,P.responseType):v&&("data"in y&&"body"in y||(y={data:y})),y.config=P,y.ok!==void 0&&!y.ok)throw new he(P.method+" to "+ee+" failed! Status: "+(y.status||null),P,y)}me=Ce(y,P);let $e=r.onResponse;$e&&await F($e,me);}catch(v){let K=v;Qt(K,y,P),me=Ce(y,P,K);}finally{N&&N.removeEventListener("abort",Ae);}return me},Be=Nt>0?R=>Bt((w,I)=>We(R,I),Je):We,{onLoadingSlow:Ye,loadingTimeout:Ge}=r,Ut=Ye&&Ge?async R=>{if(R)return Be(R);let w=setTimeout(()=>F(Ye,r).catch(C),Ge);try{return await Be(R)}finally{clearTimeout(w);}}:Be,de=(R=false)=>Ft(R,Ut,r),Xe=l?At(de,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay,r.refreshWhenHidden,r.refreshWhenOffline,N):de();return d&&(o&&pt(d,Xe),(u||c||f)&&Pt(d,de,void 0,u,de,!!c,!!f,r.focusThrottleInterval)),Xe}function Ht(e,t,r){try{let s=typeof Response===b?new Response(null,e):{ok:!0,status:e.status,statusText:e.statusText,headers:e.headers};s.data=e.data,r.cacheKey=t;let n=Ce(s,{...r,select:void 0,flattenResponse:!1,defaultResponse:void 0});return n.config=r,n}catch(s){return null}}function dr(e,t){let r=t&&!t.error&&t.headers&&t.headers.etag,s=r&&E(e.headers);return s&&!s["if-none-match"]?{...e,headers:{...s,"if-none-match":r}}:e}function mr(e){let t=e.endpoints;async function r(n){return console.error("Add "+n+" to 'endpoints'."),null}let s={config:e,endpoints:t,async request(n,a={}){let o=S(t,n)?t[n]:void 0,i=o||{url:String(n)},u=i.url,c=u.replace(/[\t\n\r]/g,"").replace(/^[\x00-\x20]+/,"");if(/^[/\\]{2}/.test(c))throw new Error("Protocol-relative URLs not allowed.");let f=/^[a-z][a-z\d+\-.]*:/i.test(c)?o&&o.url===u?$(i,a):a:$($(e,i),a);return Oe(u,f)}};return new Proxy(s,{get(n,a){if(a in s)return s[a];if(!(typeof a=="symbol"||a==="then"))return S(t,a)?s.request.bind(null,a):r.bind(null,a)}})} +exports.abortRequest=mt;exports.addTimeout=M;exports.buildConfig=_e;exports.createAbortError=W;exports.createApiFetcher=mr;exports.deleteCache=le;exports.fetchf=Oe;exports.fetchff=Oe;exports.generateCacheKey=ue;exports.getCache=ce;exports.getCachedResponse=fe;exports.getDefaultConfig=Yt;exports.getInFlightPromise=He;exports.isSlowConnection=Se;exports.mutate=Ke;exports.removeRevalidators=jt;exports.revalidate=Ee;exports.revalidateAll=Rt;exports.setCache=we;exports.setDefaultConfig=Wt;exports.setEventProvider=Lt;exports.subscribe=Jt;return exports;})({});//# sourceMappingURL=index.global.js.map //# 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 76dfe87..8a34cdb 100644 --- a/dist/browser/index.global.js.map +++ b/dist/browser/index.global.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/constants.ts","../../src/utils.ts","../../src/interceptor-manager.ts","../../src/errors/fetch-error.ts","../../src/errors/response-error.ts","../../src/timeout-wheel.ts","../../src/inflight-manager.ts","../../src/hash.ts","../../src/revalidator-manager.ts","../../src/pubsub-manager.ts","../../src/config-handler.ts","../../src/cache-manager.ts","../../src/response-parser.ts","../../src/retry-handler.ts","../../src/polling-handler.ts","../../src/error-handler.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"names":["APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CHARSET_UTF_8","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","FUNCTION","ABORT_ERROR","TIMEOUT_ERROR","GET","HEAD","REJECT","MAX_DELAY_MS","MAX_DEPTH","hasOwn","o","k","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","key","sortObject","sortedObj","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","v","buildParams","prefix","depth","i","len","replaceUrlPathParams","urlPathParams","match","encoded","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","merge","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","wheel","keyMap","position","lastTick","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","customEventProviders","setEventProvider","type","provider","removeEventHandler","addEventHandler","revalidateAll","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeRevalidator","event","handler","customProvider","cleanup","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","existing","listeners","addListener","fn","set","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","merged","buildFetcherConfig","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","separator","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","isInstance","overrides","lowerKey","existingKey","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","keys","cacheStr","sanitizeCacheKey","bodyString","getObjectId","objectIds","lastObjectId","id","isCacheExpired","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","handleResponseCache","output","isError","skipCache","prevCacheKey","parseResponseData","contentType","mimeType","trimmed","_error","prepareResponse","defaultResponse","mutatator","isNativeResponse","getMsFromHttpDate","dateString","getRetryAfterMs","extendedResponse","retryAfter","RATELIMIT_RESET","rateLimitResetAfter","rateLimitResetAt","withRetry","requestFn","retries","delay","backoff","maxDelay","retryOn","shouldRetry","attempt","waitTime","maxRetries","cfg","onRetry","getShouldStopRetrying","retryAfterMs","_b","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","redactError","strategy","SENSITIVE_HEADERS","copy","enhanceError","inFlightResponse","fetchf","cached","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","resolvedUrl","mergedConfig","_target","prop"],"mappings":"4CAAO,IAAA,EAAA,CAAA,MAAA,CAAA,cAAA,CAAA,IAAA,EAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CAAA,IAAA,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,UAAA,CAAA,IAAA,CAAA,YAAA,CAAA,IAAA,CAAA,QAAA,CAAA,IAAA,CAAA,KAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,IAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,CAAA,CAAA,CAAA,OAAA,CAAA,EAAA,QAAA,CAAA,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,IAAMA,CAAAA,CAA2B,cAAA,CAE3BC,CAAAA,CAAmBD,CAAAA,CAA2B,MAAA,CAC9CE,EAAAA,CAAgB,eAAA,CAChBC,CAAAA,CAAe,cAAA,CAEfC,CAAAA,CAAY,WAAA,CACZC,CAAAA,CAAS,SACTC,CAAAA,CAAS,QAAA,CACTC,CAAAA,CAAW,UAAA,CAEXC,EAAAA,CAAc,YAAA,CACdC,EAAAA,CAAgB,cAAA,CAEhBC,CAAAA,CAAM,KAAA,CACNC,EAAAA,CAAO,MAAA,CAEPC,EAAAA,CAAS,QAAA,CAGTC,EAAAA,CAAe,UAAA,CCV5B,IAAMC,EAAAA,CAAY,EAAA,CAELC,CAAAA,CAAS,CAACC,CAAAA,CAAQC,CAAAA,GAC7B,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAKD,CAAAA,CAAGC,CAAC,CAAA,CAEpC,SAASC,CAAAA,CAAeC,CAAAA,CAAwB,CACrD,OAAOA,CAAAA,YAAgB,eACzB,CAQO,SAASC,CAAAA,CAASC,CAAAA,CAA0C,CACjE,OAAOA,CAAAA,GAAU,IAAA,EAAQ,OAAOA,CAAAA,GAAUhB,CAC5C,CA+BO,SAASiB,EAA8CC,CAAAA,CAAW,CACvE,IAAMC,CAAAA,CAAWT,CAAAA,CAAOQ,CAAAA,CAAK,WAAW,CAAA,CAClCE,CAAAA,CAAUV,CAAAA,CAAOQ,CAAAA,CAAK,aAAa,CAAA,CACnCG,CAAAA,CAAeX,CAAAA,CAAOQ,CAAAA,CAAK,WAAW,CAAA,CAE5C,GAAI,CAACC,CAAAA,EAAY,CAACC,CAAAA,EAAW,CAACC,CAAAA,CAC5B,OAAOH,CAAAA,CAIT,IAAMI,CAAAA,CAAU,EAAC,CAEjB,IAAA,IAAWC,CAAAA,IAAO,OAAO,IAAA,CAAKL,CAAG,CAAA,CAC3BK,CAAAA,GAAQ,WAAA,EAAeA,CAAAA,GAAQ,aAAA,EAAiBA,CAAAA,GAAQ,WAAA,GAC1DD,CAAAA,CAAQC,CAAG,CAAA,CAAIL,CAAAA,CAAIK,CAAG,CAAA,CAAA,CAI1B,OAAOD,CACT,CAWO,SAASE,EAAAA,CAAWN,CAAAA,CAAkC,CAE3D,IAAMO,CAAAA,CAAY,MAAA,CAAO,OAAO,IAAI,CAAA,CAEpC,OAAA,MAAA,CAAO,IAAA,CAAKP,CAAG,CAAA,CACZ,IAAA,EAAK,CACL,QAASN,CAAAA,EAAOa,CAAAA,CAAUb,CAAC,CAAA,CAAIM,CAAAA,CAAIN,CAAC,CAAE,CAAA,CAElCa,CACT,CASA,SAASC,EAAAA,CAAuBC,CAAAA,CAAiBC,CAAAA,CAA6B,CAC5E,OAAKA,EAIED,CAAAA,EAAWA,CAAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,CAAI,GAAA,CAAM,GAAA,CAAA,CAAOC,CAAAA,CAH9CD,CAIX,CASO,SAASE,EAAAA,CAAkBC,CAAAA,CAAaC,CAAAA,CAA6B,CAC1E,GAAI,CAACA,CAAAA,CACH,OAAOD,CAAAA,CAIT,GAAIjB,CAAAA,CAAekB,CAAM,CAAA,CAAG,CAC1B,IAAMC,CAAAA,CAAqBD,CAAAA,CAAO,QAAA,EAAS,CAE3C,OAAOL,EAAAA,CAAuBI,CAAAA,CAAKE,CAAkB,CACvD,CAGA,IAAMC,CAAAA,CAAc,EAAC,CACfC,CAAAA,CAAS,kBAAA,CACTC,CAAAA,CAAM,CAACvB,CAAAA,CAAWwB,CAAAA,GAAW,CACjCA,CAAAA,CAAI,OAAOA,CAAAA,GAAMlC,EAAWkC,CAAAA,EAAE,CAAIA,CAAAA,CAClCA,CAAAA,CAAIA,CAAAA,GAAM,IAAA,EAAYA,CAAAA,GAAM,MAAA,CAAX,EAAA,CAA4BA,CAAAA,CAC7CH,CAAAA,CAAEA,CAAAA,CAAE,MAAM,CAAA,CAAIC,CAAAA,CAAOtB,CAAC,EAAI,GAAA,CAAMsB,CAAAA,CAAOE,CAAC,EAC1C,CAAA,CAEMC,CAAAA,CAAc,CAACC,CAAAA,CAAgBpB,CAAAA,CAAUqB,CAAAA,CAAQ,CAAA,GAAM,CAE3D,GAAIA,CAAAA,EAAS9B,EAAAA,CACX,OAAOwB,EAGT,IAAIO,CAAAA,CAAWC,CAAAA,CAAalB,CAAAA,CAE5B,GAAIe,CAAAA,CACF,GAAI,KAAA,CAAM,OAAA,CAAQpB,CAAG,CAAA,CACnB,IAAKsB,CAAAA,CAAI,CAAA,CAAGC,CAAAA,CAAMvB,CAAAA,CAAI,OAAQsB,CAAAA,CAAIC,CAAAA,CAAKD,CAAAA,EAAAA,CACrCH,CAAAA,CACEC,CAAAA,CAAS,GAAA,EAAO,OAAOpB,CAAAA,CAAIsB,CAAC,CAAA,GAAMxC,CAAAA,EAAUkB,CAAAA,CAAIsB,CAAC,CAAA,CAAIA,CAAAA,CAAI,EAAA,CAAA,CAAM,GAAA,CAC/DtB,EAAIsB,CAAC,CAAA,CACLD,CAAAA,CAAQ,CACV,CAAA,CAAA,KAAA,GAEOxB,CAAAA,CAASG,CAAG,CAAA,CACrB,IAAKK,CAAAA,IAAOL,CAAAA,CACVmB,CAAAA,CAAYC,CAAAA,CAAS,GAAA,CAAMf,CAAAA,CAAM,GAAA,CAAKL,EAAIK,CAAG,CAAA,CAAGgB,CAAAA,CAAQ,CAAC,CAAA,CAAA,KAG3DJ,CAAAA,CAAIG,CAAAA,CAAQpB,CAAG,CAAA,CAAA,KAAA,GAER,KAAA,CAAM,OAAA,CAAQA,CAAG,CAAA,CAC1B,IAAKsB,CAAAA,CAAI,CAAA,CAAGC,EAAMvB,CAAAA,CAAI,MAAA,CAAQsB,CAAAA,CAAIC,CAAAA,CAAKD,CAAAA,EAAAA,CACrCL,CAAAA,CAAIjB,CAAAA,CAAIsB,CAAC,CAAA,CAAE,IAAA,CAAMtB,CAAAA,CAAIsB,CAAC,CAAA,CAAE,KAAK,CAAA,CAAA,KAG/B,IAAKjB,KAAOL,CAAAA,CACVmB,CAAAA,CAAYd,CAAAA,CAAKL,CAAAA,CAAIK,CAAG,CAAA,CAAGgB,CAAAA,CAAQ,CAAC,CAAA,CAGxC,OAAON,CACT,CAAA,CAMMD,CAAAA,CAJmBK,CAAAA,CAAY,EAAA,CAAIN,CAAM,EAAE,IAAA,CAAK,GAAG,CAAA,CAIb,OAAA,CAAQ,SAAA,CAAW,IAAI,CAAA,CAEnE,OAAOL,EAAAA,CAAuBI,CAAAA,CAAKE,CAAkB,CACvD,CAWO,SAASU,EAAAA,CACdZ,CAAAA,CACAa,EACQ,CACR,GAAI,CAACA,CAAAA,EAAiBb,CAAAA,CAAI,OAAA,CAAQ,GAAG,CAAA,GAAM,EAAA,CACzC,OAAOA,CAAAA,CAKT,IAAMC,CAAAA,CAASY,CAAAA,CAGf,OAAOb,CAAAA,CAAI,QAAQ,mBAAA,CAAqB,CAACc,CAAAA,CAAOrB,CAAAA,GAAQ,CAEtD,GAAIb,CAAAA,CAAOqB,CAAAA,CAAQR,CAAG,CAAA,CAAG,CACvB,IAAMP,CAAAA,CAAQe,CAAAA,CAAOR,CAAG,CAAA,CAGxB,GAA2BP,CAAAA,EAAU,IAAA,CAAM,CACzC,IAAM6B,CAAAA,CAAU,kBAAA,CAAmB,MAAA,CAAO7B,CAAK,CAAC,CAAA,CAGhD,GAAI6B,CAAAA,GAAY,GAAA,EAAOA,CAAAA,GAAY,IAAA,CACjC,MAAM,IAAI,MAAM,uCAAuC,CAAA,CAGzD,OAAOA,CACT,CACF,CAEA,OAAOD,CACT,CAAC,CACH,CAWO,SAASE,EAAAA,CAAchB,CAAAA,CAAsB,CAClD,OAAO,2BAA2B,IAAA,CAAKA,CAAG,CAC5C,CAEO,IAAMiB,CAAAA,CAAU,IAAM,IAAA,CAAK,GAAA,EAAI,CAEzBC,CAAAA,CAAO,IAAM,CAAC,CAAA,CAcpB,SAASC,CAAAA,CAAmBjC,EAAqB,CACtD,IAAM,CAAA,CAAI,OAAOA,CAAAA,CAEjB,OAA2BA,CAAAA,EAAU,IAAA,CAC5B,KAAA,CAGL,CAAA,GAAMf,CAAAA,EAAU,CAAA,GAAM,QAAA,EAAY,CAAA,GAAM,SAAA,EAIxC,KAAA,CAAM,QAAQe,CAAK,CAAA,CACd,IAAA,CAIP,OAAO,UAAA,GAAejB,CAAAA,EACtB,OAAO,UAAA,CAAW,MAAA,GAAWA,CAAAA,EAC7B,UAAA,CAAW,MAAA,CAAO,QAAA,CAASiB,CAAK,CAAA,EAK9BA,CAAAA,YAAiB,MAAQH,CAAAA,CAAeG,CAAK,CAAA,CACxC,KAAA,CAGL,CAAA,EAAAD,CAAAA,CAASC,CAAK,CAAA,GACF,MAAA,CAAO,cAAA,CAAeA,CAAK,CAAA,GAG3B,MAAA,CAAO,SAAA,EAKjB,OAAOA,CAAAA,CAAM,SAAWd,CAAAA,CAAAA,CAMhC,CAEO,IAAMgD,CAAAA,CAAmBC,CAAAA,EAC9B,IAAI,OAAA,CAASC,CAAAA,EACX,UAAA,CAAWA,CAAAA,CAAS,IAAA,CAAK,GAAA,CAAID,CAAAA,CAAI3C,EAAY,CAAA,CAAG,IAAI,CACtD,CAAA,CAWK,SAAS6C,EAAAA,CAAYvC,CAAAA,CAAWyB,CAAAA,CAAQ,CAAA,CAAQ,CACrD,OAAIA,CAAAA,EAAS9B,EAAAA,CACJK,CAAAA,CAGLA,CAAAA,EAAQC,CAAAA,CAASD,CAAI,CAAA,EAAK,OAAOA,EAAK,IAAA,GAASf,CAAAA,CAC1CsD,EAAAA,CAAYvC,CAAAA,CAAK,IAAA,CAAMyB,CAAAA,CAAQ,CAAC,CAAA,CAGlCzB,CACT,CAYO,SAASwC,CAAAA,CACdC,CAAAA,CACe,CACf,GAAI,CAACA,CAAAA,CACH,OAAO,EAAC,CAGV,IAAMC,CAAAA,CAA+B,EAAC,CAItC,GAAID,CAAAA,YAAmB,OAAA,CACrBA,CAAAA,CAAQ,OAAA,CAAQ,CAACvC,CAAAA,CAAOO,CAAAA,GAAQ,CAC9BiC,CAAAA,CAAcjC,EAAI,WAAA,EAAa,CAAA,CAAIP,EACrC,CAAC,CAAA,CAAA,KAGD,IAAA,IAAWO,CAAAA,IAAOgC,CAAAA,CAEZ7C,CAAAA,CAAO6C,CAAAA,CAAShC,CAAG,CAAA,EAAKA,CAAAA,GAAQ,WAAA,GAClCiC,CAAAA,CAAcjC,EAAI,WAAA,EAAa,CAAA,CAAIgC,CAAAA,CAAQhC,CAAG,CAAA,CAAA,CAKpD,OAAOiC,CACT,CAOO,SAASC,EAAAA,EAAqB,CAEnC,OACE,OAAO,MAAA,GAAW1D,CAAAA,EAAa,OAAO,MAAA,CAAO,gBAAA,GAAqBG,CAEtE,CAUO,SAASwD,EAAAA,CACdC,CAAAA,CACAC,CAAAA,CACsB,CACtB,GAAI,OAAO,YAAA,GAAiB7D,CAAAA,CAC1B,OAAO,IAAI,YAAA,CAAa4D,EAASC,CAAI,CAAA,CAGvC,IAAMC,CAAAA,CAAQ,IAAI,KAAA,CAAMF,CAAO,CAAA,CAC/B,OAAAE,CAAAA,CAAM,IAAA,CAAOD,CAAAA,CAENC,CACT,CAMO,IAAMC,EAAAA,CAAmB,IAAe,CAC7C,IAAMC,CAAAA,CAAO,OAAO,SAAA,GAAchE,CAAAA,EAAc,SAAA,CAAkB,UAAA,CAElE,OAAOgE,CAAAA,EAAQ,CAAC,SAAA,CAAW,IAAA,CAAM,IAAI,CAAA,CAAE,QAAA,CAASA,EAAK,aAAa,CACpE,ECzYA,eAAsBC,CAAAA,CAKpBC,CAAAA,CAA6BnD,CAAAA,CAAAA,GAAYoD,CAAAA,CAA2B,CACpE,GAAI,CAACD,CAAAA,CACH,OAGF,IAAME,CAAAA,CAAS/B,CAAAA,EACbA,GACArB,CAAAA,CAASD,CAAI,CAAA,EACbC,CAAAA,CAASqB,CAAC,CAAA,EACV,MAAA,CAAO,MAAA,CAAOtB,EAAMG,CAAAA,CAAemB,CAAC,CAAC,CAAA,CAEvC,GAAI,OAAO6B,CAAAA,GAAiB/D,CAAAA,CAC1BiE,EAAM,MAAOF,CAAAA,CAA8CnD,CAAAA,CAAM,GAAGoD,CAAI,CAAC,CAAA,CAAA,KAAA,GAChE,KAAA,CAAM,OAAA,CAAQD,CAAY,CAAA,CACnC,IAAA,IAAWG,CAAAA,IAAeH,CAAAA,CACxBE,CAAAA,CAAM,MAAMC,EAAYtD,CAAAA,CAAM,GAAGoD,CAAI,CAAC,EAG5C,CC5BO,IAAMG,EAAAA,CAAN,cAKG,KAAM,CAMd,WAAA,CACEV,CAAAA,CACOW,CAAAA,CAMAC,CAAAA,CAMP,CACA,MAAMZ,CAAO,CAAA,CAbNa,CAAAA,CAAA,IAAA,CAAA,SAAA,CAAAF,CAAAA,CAAAA,CAMAE,CAAAA,CAAA,IAAA,CAAA,UAAA,CAAAD,CAAAA,CAAAA,CAbTC,CAAAA,CAAA,IAAA,CAAA,QAAA,CAAA,CACAA,CAAAA,CAAA,IAAA,CAAA,YAAA,CAAA,CACAA,CAAAA,CAAA,IAAA,CAAA,QAAA,CAAA,CACAA,CAAAA,CAAA,IAAA,CAAA,aAAA,CAAA,CAmBE,KAAK,IAAA,CAAO,YAAA,CACZ,IAAA,CAAK,MAAA,CAASD,CAAAA,CAAWA,CAAAA,CAAS,MAAA,CAAS,CAAA,CAC3C,IAAA,CAAK,UAAA,CAAaA,CAAAA,CAAWA,CAAAA,CAAS,UAAA,CAAa,EAAA,CACnD,IAAA,CAAK,MAAA,CAASD,EACd,IAAA,CAAK,WAAA,CAAc,MACrB,CACF,CAAA,CCpCO,IAAMG,EAAAA,CAAN,cAKGJ,EAA+D,CACvE,WAAA,CACEV,CAAAA,CACAW,CAAAA,CACAC,CAAAA,CAMA,CACA,KAAA,CAAMZ,EAASW,CAAAA,CAASC,CAAQ,CAAA,CAEhC,IAAA,CAAK,IAAA,CAAO,gBACd,CACF,CAAA,CCDA,IAAMG,EAAAA,CAAa,GAAA,CACbC,EAAAA,CAAS,GAAA,CACTC,EAAAA,CAAyB,KAAA,CAAMF,EAAU,EAC5C,IAAA,CAAK,CAAC,CAAA,CACN,GAAA,CAAI,IAAM,EAAE,CAAA,CAETG,CAAAA,CAAS,IAAI,GAAA,CACfC,EAAAA,CAAW,CAAA,CACXC,EAAAA,CAAW,CAAA,CACXC,CAAAA,CAA+B,KAE7BC,EAAAA,CAAiB,CAAC,CAAC1D,CAAAA,CAAK2D,CAAQ,CAAA,GAAyB,CAC7DL,CAAAA,CAAO,OAAOtD,CAAG,CAAA,CAEjB,GAAI,CACF,IAAM4D,CAAAA,CAASD,CAAAA,EAAS,CACpBC,GAAUA,CAAAA,YAAkB,OAAA,EAE9BA,CAAAA,CAAO,KAAA,CAAMnC,CAAI,EAErB,CAAA,MAAQoC,CAAAA,CAAA,CAER,CACF,CAAA,CAEaC,CAAAA,CAAa,CACxB9D,CAAAA,CACA+D,CAAAA,CACAnC,CAAAA,GACS,CACToC,CAAAA,CAAchE,CAAG,CAAA,CAIjB,IAAMiE,CAAAA,CAAUrC,CAAAA,CAAKwB,EAAAA,EAAUK,CAAAA,EAASjC,CAAAA,EAAQ,GAAMgC,EAAAA,CAAW,CAAA,CAAI,CAAA,CAAA,CAGrE,GAAI5B,CAAAA,CAAKwB,EAAAA,EAAUa,GAAWd,EAAAA,EAAcvB,CAAAA,CAAKwB,EAAAA,GAAW,CAAA,CAAG,CAC7DE,CAAAA,CAAO,GAAA,CAAItD,CAAAA,CAAK,CACd,UAAA,CACE0D,EAAAA,CAAe,IAAA,CAAK,IAAA,CAAM,CAAC1D,CAAAA,CAAK+D,CAAE,CAAC,CAAA,CACnC,IAAA,CAAK,GAAA,CAAInC,CAAAA,CAAI3C,EAAY,CAC3B,CACF,CAAC,CAAA,CAED,MACF,CAEA,IAAMiF,CAAAA,CAAAA,CAAQX,EAAAA,CAAWU,CAAAA,EAAWd,EAAAA,CAEpCE,GAAMa,CAAI,CAAA,CAAE,IAAA,CAAK,CAAClE,CAAAA,CAAK+D,CAAE,CAAC,CAAA,CAC1BT,CAAAA,CAAO,GAAA,CAAItD,CAAAA,CAAKkE,CAAI,CAAA,CAEfT,CAAAA,GACHD,EAAAA,CAAWhC,CAAAA,GACXiC,CAAAA,CAAQ,WAAA,CAAY,IAAM,CACxBF,EAAAA,CAAAA,CAAYA,EAAAA,CAAW,CAAA,EAAKJ,EAAAA,CAC5BK,EAAAA,CAAWhC,CAAAA,EAAQ,CACnB,IAAM0C,CAAAA,CAAOb,EAAAA,CAAME,EAAQ,CAAA,CAI3B,QAAStC,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIiD,CAAAA,CAAK,MAAA,CAAQjD,CAAAA,EAAAA,CAC/ByC,EAAAA,CAAeQ,CAAAA,CAAKjD,CAAC,CAAC,CAAA,CAGxBiD,CAAAA,CAAK,MAAA,CAAS,CAAA,CAEV,CAACZ,CAAAA,CAAO,MAAQG,CAAAA,GAClB,aAAA,CAAcA,CAAK,CAAA,CACnBA,CAAAA,CAAQ,IAAA,EAEZ,CAAA,CAAGL,EAAM,GAEb,CAAA,CAEaY,CAAAA,CAAiBhE,CAAAA,EAAsB,CAClD,IAAMmE,CAAAA,CAAgBb,CAAAA,CAAO,GAAA,CAAItD,CAAG,CAAA,CAEpC,GAAImE,CAAAA,GAAkB,MAAA,CAAW,CAE/B,GAAI,KAAA,CAAM,OAAA,CAAQA,CAAa,CAAA,CAC7B,YAAA,CAAaA,CAAAA,CAAc,CAAC,CAAC,CAAA,CAAA,KACxB,CACL,IAAMC,CAAAA,CAAUf,EAAAA,CAAMc,CAAa,CAAA,CAEnC,IAAA,IAASlD,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAImD,CAAAA,CAAQ,MAAA,CAAQnD,CAAAA,EAAAA,CAClC,GAAImD,CAAAA,CAAQnD,CAAC,CAAA,CAAE,CAAC,IAAMjB,CAAAA,CAAK,CACzBoE,CAAAA,CAAQ,MAAA,CAAOnD,CAAAA,CAAG,CAAC,CAAA,CACnB,KACF,CAEJ,CAEAqC,CAAAA,CAAO,MAAA,CAAOtD,CAAG,CAAA,CAEb,CAACsD,CAAAA,CAAO,MAAQG,CAAAA,GAClB,aAAA,CAAcA,CAAK,CAAA,CACnBA,CAAAA,CAAQ,IAAA,EAEZ,CACF,EClGA,IAAMY,CAAAA,CAAsC,IAAI,GAAA,CAazC,SAASC,EAAAA,CACdtE,CAAAA,CACAO,CAAAA,CACAgE,CAAAA,CACAC,EACAC,CAAAA,CACAC,CAAAA,CACiB,CACjB,GAAI,CAAC1E,CAAAA,CACH,OAAO,IAAI,eAAA,CAGb,IAAM2E,CAAAA,CAAMnD,CAAAA,EAAQ,CACdoD,CAAAA,CAAOP,CAAAA,CAAS,GAAA,CAAIrE,CAAG,CAAA,CACzB6E,CAAAA,CAAuC,IAAA,CAG3C,GAAID,CAAAA,CAAM,CACR,IAAME,CAAAA,CAAiBF,CAAAA,CAAK,CAAC,CAAA,CACvBG,CAAAA,CAAoBH,CAAAA,CAAK,CAAC,CAAA,CAGhC,GACE,CAACG,CAAAA,EACDJ,CAAAA,CAAMC,CAAAA,CAAK,CAAC,CAAA,CAAIJ,CAAAA,EAChB,CAACM,CAAAA,CAAe,MAAA,CAAO,OAAA,CAEvB,OAAOA,CAAAA,CAKLC,CAAAA,EACFD,CAAAA,CAAe,KAAA,CACb3C,EAAAA,CAAiB,6BAA8BvD,EAAW,CAC5D,CAAA,CAGFoF,CAAAA,CAAchE,CAAG,CAAA,CACjB6E,CAAAA,CAAcD,CAAAA,CAAK,CAAC,EACtB,CAEA,IAAMI,CAAAA,CAAa,IAAI,eAAA,CAEvB,OAAAX,CAAAA,CAAS,IAAIrE,CAAAA,CAAK,CAChBgF,CAAAA,CACAN,CAAAA,CACAC,CAAAA,CACAF,CAAAA,CACAI,CACF,CAAC,CAAA,CAEGH,CAAAA,EACFZ,CAAAA,CACE9D,CAAAA,CACA,IAAM,CACJiF,EAAAA,CACEjF,CAAAA,CACAmC,GAAiB5B,CAAAA,CAAM,yBAAA,CAA2B1B,EAAa,CACjE,EACF,CAAA,CACA0F,CACF,CAAA,CAGKS,CACT,CASA,eAAsBC,EAAAA,CACpBjF,CAAAA,CACAsC,CAAAA,CAA8C,IAAA,CAC/B,CAEf,GAAItC,CAAAA,CAAK,CACP,IAAM4E,CAAAA,CAAOP,CAAAA,CAAS,GAAA,CAAIrE,CAAG,CAAA,CAEzB4E,CAAAA,GAEEtC,CAAAA,EACiBsC,CAAAA,CAAK,CAAC,CAAA,CACd,KAAA,CAAMtC,CAAK,CAAA,CAGxB4C,GAAelF,CAAG,CAAA,EAEtB,CACF,CAOO,SAASkF,EAAAA,CAAelF,CAAAA,CAA0B,CACvDgE,CAAAA,CAAchE,CAAI,CAAA,CAClBqE,CAAAA,CAAS,MAAA,CAAOrE,CAAI,EACtB,CAsBO,SAASmF,EAAAA,CACdnF,CAAAA,CACAoF,CAAAA,CACM,CACN,IAAMR,CAAAA,CAAOP,CAAAA,CAAS,GAAA,CAAIrE,CAAG,CAAA,CACzB4E,CAAAA,GAEFA,CAAAA,CAAK,CAAC,CAAA,CAAIQ,CAAAA,EAEd,CASO,SAASC,EAAAA,CACdrF,CAAAA,CACAwE,CAAAA,CACmB,CACnB,GAAI,CAACxE,CAAAA,CACH,OAAO,IAAA,CAGT,IAAMsF,CAAAA,CAAUjB,CAAAA,CAAS,GAAA,CAAIrE,CAAG,CAAA,CAEhC,OACEsF,GAEAA,CAAAA,CAAQ,CAAC,CAAA,EAET,CAACA,CAAAA,CAAQ,CAAC,CAAA,EAEV9D,CAAAA,EAAQ,CAAI8D,CAAAA,CAAQ,CAAC,CAAA,CAAId,CAAAA,EAEzB,CAACc,CAAAA,CAAQ,CAAC,EAAE,MAAA,CAAO,OAAA,CAEZA,CAAAA,CAAQ,CAAC,CAAA,CAGX,IACT,CC3MO,SAASC,EAAKC,CAAAA,CAAqB,CACxC,IAAID,CAAAA,CAAO,CAAA,CAEX,IAAA,IAAStE,CAAAA,CAAI,CAAA,CAAGC,EAAMsE,CAAAA,CAAI,MAAA,CAAQvE,CAAAA,CAAIC,CAAAA,CAAKD,CAAAA,EAAAA,CAAK,CAC9C,IAAMwE,CAAAA,CAAOD,CAAAA,CAAI,UAAA,CAAWvE,CAAC,CAAA,CAC7BsE,CAAAA,CAAQA,CAAAA,CAAO,EAAA,CAAmBE,CAAAA,CAAQ,EAC5C,CAEA,OAAO,MAAA,CAAOF,CAAI,CACpB,CCmBA,IAAMG,EAAAA,CAAc,GAAA,CAAS,GAAA,CACvBC,CAAAA,CAAe,IAAI,GAAA,CASnBC,CAAAA,CAAgB,IAAI,GAAA,CAKpBC,GAAuB,IAAI,GAAA,CAS1B,SAASC,EAAAA,CACdC,CAAAA,CACAC,CAAAA,CACM,CACNH,EAAAA,CAAqB,GAAA,CAAIE,CAAAA,CAAMC,CAAQ,CAAA,CAGnCJ,CAAAA,CAAc,GAAA,CAAIG,CAAI,CAAA,GACxBE,GAAmBF,CAAI,CAAA,CACvBG,EAAAA,CAAgBH,CAAI,CAAA,EAExB,CAUO,SAASI,EAAAA,CACdJ,CAAAA,CACAK,CAAAA,CAA+B,IAAA,CAC/B,CACA,IAAMC,CAAAA,CAAYN,CAAAA,GAAS,OAAA,CAAU,EAAI,CAAA,CACnCpB,CAAAA,CAAMnD,CAAAA,EAAQ,CAEpBmE,CAAAA,CAAa,OAAA,CAASW,CAAAA,EAAU,CAC9B,GAAI,CAACA,CAAAA,CAAMD,CAAS,CAAA,CAClB,OAGFC,CAAAA,CAAM,CAAC,EAAI3B,CAAAA,CAGX,IAAM4B,CAAAA,CAAcH,CAAAA,CAAsBE,CAAAA,CAAM,CAAC,CAAA,CAAIA,CAAAA,CAAM,CAAC,CAAA,CAExDC,CAAAA,EACF,OAAA,CAAQ,OAAA,CAAQA,CAAAA,CAAYH,CAAmB,CAAC,EAAE,KAAA,CAAM3E,CAAI,EAEhE,CAAC,EACH,CAUA,eAAsB+E,EAAAA,CACpBxG,CAAAA,CACAoG,CAAAA,CAA+B,KAAA,CACI,CAEnC,GAAI,CAACpG,CAAAA,CACH,OAAO,KAGT,IAAMsG,CAAAA,CAAQX,CAAAA,CAAa,GAAA,CAAI3F,CAAG,CAAA,CAElC,GAAIsG,CAAAA,CAAO,CAETA,CAAAA,CAAM,CAAC,CAAA,CAAI9E,CAAAA,EAAQ,CAEnB,IAAM+E,CAAAA,CAAcH,CAAAA,CAAsBE,EAAM,CAAC,CAAA,CAAIA,CAAAA,CAAM,CAAC,CAAA,CAG5D,GAAIC,CAAAA,CACF,OAAO,MAAMA,CAAAA,CAAYH,CAAmB,CAEhD,CAGA,OAAO,IACT,CAOO,SAASK,EAAAA,CAAmBV,CAAAA,CAAiB,CAClDE,EAAAA,CAAmBF,CAAI,CAAA,CAEvB,IAAMM,CAAAA,CAAYN,CAAAA,GAAS,OAAA,CAAU,CAAA,CAAI,CAAA,CAGzCJ,CAAAA,CAAa,OAAA,CAAQ,CAACW,CAAAA,CAAOtG,IAAQ,CAC/BsG,CAAAA,CAAMD,CAAS,CAAA,EACjBK,EAAAA,CAAkB1G,CAAG,EAEzB,CAAC,EACH,CASA,SAASkG,EAAAA,CAAgBS,CAAAA,CAAkB,CACzC,GAAIf,CAAAA,CAAc,IAAIe,CAAK,CAAA,CACzB,OAGF,IAAMC,CAAAA,CAAUT,EAAAA,CAAc,IAAA,CAAK,IAAA,CAAMQ,CAAAA,CAAO,IAAI,CAAA,CAG9CE,CAAAA,CAAiBhB,EAAAA,CAAqB,GAAA,CAAIc,CAAK,CAAA,CAErD,GAAIE,CAAAA,CAAgB,CAClB,IAAMC,CAAAA,CAAUD,CAAAA,CAAeD,CAAO,CAAA,CAEtChB,CAAAA,CAAc,GAAA,CAAIe,CAAAA,CAAOG,CAAO,CAAA,CAEhC,MACF,CAGI5E,EAAAA,EAAU,GACZ,OAAO,gBAAA,CAAiByE,CAAAA,CAAOC,CAAO,CAAA,CAEtChB,CAAAA,CAAc,GAAA,CAAIe,CAAAA,CAAO,IAAM,MAAA,CAAO,mBAAA,CAAoBA,CAAAA,CAAOC,CAAO,CAAC,CAAA,EAE7E,CAOA,SAASX,GAAmBU,CAAAA,CAAkB,CAC5C,IAAMG,CAAAA,CAAUlB,CAAAA,CAAc,GAAA,CAAIe,CAAK,CAAA,CAEnCG,CAAAA,GACFA,CAAAA,EAAQ,CACRlB,CAAAA,CAAc,MAAA,CAAOe,CAAK,CAAA,EAE9B,CAaO,SAASI,EAAAA,CACd/G,CAAAA,CACAgH,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACA,CACA,IAAMC,CAAAA,CAAW3B,CAAAA,CAAa,GAAA,CAAI3F,CAAG,CAAA,CAEjCsH,CAAAA,EAEFA,CAAAA,CAAS,CAAC,CAAA,CAAIN,CAAAA,CACdM,CAAAA,CAAS,CAAC,CAAA,CAAI9F,CAAAA,EAAQ,CACtB8F,CAAAA,CAAS,CAAC,CAAA,CAAW5B,EAAAA,CACrB4B,CAAAA,CAAS,CAAC,EAAIJ,CAAAA,CACdI,CAAAA,CAAS,CAAC,CAAA,CAAIH,CAAAA,CACdG,CAAAA,CAAS,CAAC,CAAA,CAAIF,CAAAA,CACdE,CAAAA,CAAS,CAAC,CAAA,CAAID,CAAAA,EAEd1B,CAAAA,CAAa,GAAA,CAAI3F,CAAAA,CAAK,CACpBgH,CAAAA,CACAxF,CAAAA,EAAQ,CACDkE,EAAAA,CACPwB,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CACF,CAAC,CAAA,CAGCD,CAAAA,EACFlB,EAAAA,CAAgB,OAAO,EAGrBmB,CAAAA,EACFnB,EAAAA,CAAgB,QAAQ,CAAA,CAGtBgB,CAAAA,EACFpD,CAAAA,CAAW,IAAA,CAAO9D,CAAAA,CAAKwG,EAAAA,CAAW,IAAA,CAAK,IAAA,CAAMxG,CAAAA,CAAK,IAAI,CAAA,CAAGkH,CAAAA,CAAY,GAAI,EAE7E,CAEO,SAASR,EAAAA,CAAkB1G,CAAAA,CAAa,CAC7C2F,CAAAA,CAAa,MAAA,CAAO3F,CAAG,CAAA,CAGvBgE,CAAAA,CAAc,IAAA,CAAOhE,CAAG,EAC1B,CChPA,IAAMuH,CAAAA,CAAY,IAAI,GAAA,CAGf,SAASC,EAAAA,CAAqBxH,CAAAA,CAAayH,CAAAA,CAAuB,CACvE,IAAIC,CAAAA,CAAMH,CAAAA,CAAU,GAAA,CAAIvH,CAAG,CAAA,CAEtB0H,CAAAA,EACHH,CAAAA,CAAU,GAAA,CAAIvH,CAAAA,CAAM0H,EAAM,IAAI,GAAM,CAAA,CAGtCA,CAAAA,CAAI,GAAA,CAAID,CAAE,EACZ,CAEO,SAASE,EAAAA,CAAkB3H,CAAAA,CAAayH,CAAAA,CAAiB,CAC9D,IAAMC,CAAAA,CAAMH,CAAAA,CAAU,IAAIvH,CAAG,CAAA,CAEzB0H,CAAAA,GACFA,CAAAA,CAAI,MAAA,CAAOD,CAAE,CAAA,CAGTC,CAAAA,CAAI,OAAS,CAAA,EACfH,CAAAA,CAAU,MAAA,CAAOvH,CAAG,CAAA,EAG1B,CAEO,SAAS4H,CAAAA,CAAqB5H,EAAagD,CAAAA,CAAa,CAC7D,IAAM6E,CAAAA,CAAMN,CAAAA,CAAU,GAAA,CAAIvH,CAAG,CAAA,CAE7B,GAAI6H,CAAAA,CACF,GAAIA,CAAAA,CAAI,IAAA,GAAS,CAAA,CAAG,CAElB,IAAMJ,EAAKI,CAAAA,CAAI,MAAA,EAAO,CAAE,IAAA,EAAK,CAAE,KAAA,CAC/BJ,CAAAA,CAAIzE,CAAQ,EACd,CAAA,KACE6E,CAAAA,CAAI,OAAA,CAASJ,CAAAA,EAAOA,CAAAA,CAAGzE,CAAQ,CAAC,EAGtC,CAEO,SAAS8E,EAAAA,CAAa9H,CAAAA,CAAoByH,CAAAA,CAA2B,CAC1E,OAAKzH,CAAAA,EAKLwH,EAAAA,CAAexH,CAAAA,CAAKyH,CAAE,CAAA,CAGf,IAAM,CACXE,EAAAA,CAAe3H,CAAAA,CAAKyH,CAAE,EACxB,CAAA,EARShG,CASX,CCnDA,IAAMsG,EAAAA,CAAAA,CAAoBxF,EAAAA,EAAiB,CAAI,EAAA,CAAK,EAAA,EAAM,GAAA,CAE7CyF,CAAAA,CAA+B,CAC1C,QAAA,CAAUhJ,EAAAA,CACV,OAAA,CAAS+I,GACT,OAAA,CAAS,CACP,MAAA,CAAQ1J,CAAAA,CAAmB,mBAAA,CAC3B,iBAAA,CAAmB,mBACrB,CAAA,CACA,KAAA,CAAO,CACL,KAAA,CAAO0J,EAAAA,CAAmB,EAAA,CAC1B,QAAA,CAAUA,EAAAA,CACV,YAAA,CAAc,KACd,OAAA,CAAS,GAAA,CAGT,OAAA,CAAS,CACP,GAAA,CACA,GAAA,CACA,GAAA,CACA,GAAA,CACA,GAAA,CACA,GAAA,CACA,GAAA,CACA,GACF,CACF,CACF,CAAA,CAQO,SAASE,GACdC,CAAAA,CACwB,CACxB,IAAMC,CAAAA,CAAYzI,CAAAA,CAAewI,CAAY,CAAA,CAG7C,OAAOE,CAAAA,CACL,CAAE,KAAA,CAAOJ,CAAAA,CAAc,KAAA,CAAO,OAAA,CAASA,CAAAA,CAAc,OAAQ,EAC7DG,CAAAA,CACAH,CACF,CACF,CAOO,SAASK,EAAAA,EAAkC,CAChD,OAAO,CAAE,GAAGL,CAAc,CAC5B,CASO,SAASM,EAAAA,CACd/H,CAAAA,CACAgI,CAAAA,CAMmE,CAGnE,IAAMC,CAAAA,CAASJ,CAAAA,CACbJ,CAAAA,CACAO,CAAAA,CAAY7I,CAAAA,CAAe6I,CAAS,CAAA,CAAI,EAC1C,CAAA,CAEA,OAAOE,EAAAA,CAAmBlI,CAAAA,CAAKiI,CAAM,CACvC,CASO,SAASC,EAAAA,CACdlI,CAAAA,CACAmI,CAAAA,CACe,CAzHjB,IAAAC,CAAAA,CA0HE,IAAIC,CAAAA,CAASF,CAAAA,CAAc,MAAA,CAC3BE,CAAAA,CAASA,CAAAA,CAAUA,CAAAA,CAAO,WAAA,EAAY,CAAe9J,EAErD,IAAI+J,CAAAA,CAGAD,CAAAA,GAAW9J,CAAAA,EAAO8J,CAAAA,GAAW7J,EAAAA,GAC/B8J,CAAAA,CAAAA,CAAOF,CAAAA,CAAAD,CAAAA,CAAc,IAAA,GAAd,IAAA,CAAAC,CAAAA,CAAsBD,CAAAA,CAAc,IAAA,CAGvCG,CAAAA,EAAQ,OAAOA,IAASnK,CAAAA,EAAUgD,CAAAA,CAAmBmH,CAAI,CAAA,GAC3DA,CAAAA,CAAO,IAAA,CAAK,SAAA,CAAUA,CAAI,CAAA,CAAA,CAAA,CAI9BC,EAAAA,CAAuBJ,CAAAA,CAAc,OAAA,CAASG,CAAI,CAAA,CAGlD,IAAME,CAAAA,CAAcL,EAAc,eAAA,CAC9B,SAAA,CACAA,CAAAA,CAAc,WAAA,CAGZM,CAAAA,CAAa7H,EAAAA,CAAqBZ,CAAAA,CAAKmI,CAAAA,CAAc,aAAa,CAAA,CAClEO,CAAAA,CAAU3I,EAAAA,CAAkB0I,CAAAA,CAAYN,CAAAA,CAAc,MAAM,CAAA,CAE5DQ,EADY3H,EAAAA,CAAchB,CAAG,CAAA,CAE/B,EAAA,CACAmI,CAAAA,CAAc,OAAA,EAAWA,CAAAA,CAAc,MAAA,EAAU,EAAA,CAI/CS,CAAAA,CACJD,CAAAA,EAAWD,CAAAA,EAAW,CAACC,CAAAA,CAAQ,QAAA,CAAS,GAAG,GAAK,CAAC,QAAA,CAAS,IAAA,CAAKD,CAAO,CAAA,CAClE,GAAA,CACA,EAAA,CAEN,OAAAP,CAAAA,CAAc,GAAA,CAAMQ,CAAAA,CAAUC,CAAAA,CAAYF,CAAAA,CAC1CP,CAAAA,CAAc,MAAA,CAASE,CAAAA,CACvBF,EAAc,WAAA,CAAcK,CAAAA,CAC5BL,CAAAA,CAAc,IAAA,CAAOG,CAAAA,CAEdH,CACT,CAWA,SAASI,GACP9G,CAAAA,CACA6G,CAAAA,CACM,CAON,GALI,CAAC7G,CAAAA,EAAW,CAAC6G,CAAAA,EAMfA,aAAgB,QAAA,EACf,OAAO,IAAA,GAASrK,CAAAA,EAAaqK,CAAAA,YAAgB,IAAA,EAC7C,OAAO,IAAA,GAASrK,CAAAA,EAAaqK,CAAAA,YAAgB,IAAA,EAC7C,OAAO,cAAA,GAAmBrK,CAAAA,EAAaqK,CAAAA,YAAgB,cAAA,CAExD,OAGF,IAAIO,CAAAA,CAEJ,GAAI9J,CAAAA,CAAeuJ,CAAI,CAAA,CACrBO,CAAAA,CAAmBhL,CAAAA,CAA2B,uBAAA,CAAA,KAAA,GACrCyK,CAAAA,YAAgB,WAAA,EAAe,WAAA,CAAY,MAAA,CAAOA,CAAI,CAAA,CAC/DO,CAAAA,CAAmBhL,EAA2B,cAAA,CAAA,KAAA,GACrCsD,CAAAA,CAAmBmH,CAAI,CAAA,CAChCO,CAAAA,CAAmB/K,CAAAA,CAAmB,GAAA,CAAMC,EAAAA,CAAAA,KAG5C,OAGE0D,CAAAA,YAAmB,OAAA,CAChBA,CAAAA,CAAQ,GAAA,CAAIzD,CAAY,CAAA,EAC3ByD,CAAAA,CAAQ,IAAIzD,CAAAA,CAAc6K,CAAgB,CAAA,CAG5C5J,CAAAA,CAASwC,CAAO,CAAA,EAChB,CAAC,KAAA,CAAM,OAAA,CAAQA,CAAO,CAAA,EAEtB,CAACD,CAAAA,CAAeC,CAAwB,CAAA,CAAEzD,CAAAA,CAAa,aAAa,CAAA,GAEpEyD,CAAAA,CAAQzD,CAAY,CAAA,CAAI6K,CAAAA,EAE5B,CAmBO,SAAShB,CAAAA,CACdiB,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CAA8B,EAAC,CAChB,CACf,OAAA,MAAA,CAAO,OAAOA,CAAAA,CAAcF,CAAAA,CAAYC,CAAc,CAAA,CAGtDE,EAAAA,CAAY,OAAA,CAASH,CAAAA,CAAYC,CAAAA,CAAgBC,CAAY,CAAA,CAC7DC,EAAAA,CAAY,SAAA,CAAWH,CAAAA,CAAYC,CAAAA,CAAgBC,CAAY,CAAA,CAG/DE,GAAkB,WAAA,CAAaJ,CAAAA,CAAYC,CAAAA,CAAgBC,CAAY,CAAA,CACvEE,EAAAA,CAAkB,YAAA,CAAcJ,CAAAA,CAAYC,CAAAA,CAAgBC,CAAY,CAAA,CACxEE,EAAAA,CAAkB,SAAA,CAAWJ,CAAAA,CAAYC,CAAAA,CAAgBC,CAAY,EAE9DA,CACT,CAKA,SAASE,EAAAA,CAGPC,CAAAA,CACAL,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACM,CACN,IAAMI,CAAAA,CAAkBN,CAAAA,CAAWK,CAAQ,CAAA,CACrCE,CAAAA,CAAiBN,CAAAA,CAAeI,CAAQ,EAE9C,GAAI,CAACC,CAAAA,EAAmB,CAACC,CAAAA,CACvB,OAGF,GAAI,CAACD,CAAAA,CAAiB,CACpBJ,CAAAA,CAAaG,CAAQ,CAAA,CAAIE,CAAAA,CACzB,MACF,CAEA,GAAI,CAACA,CAAAA,CAAgB,CACnBL,CAAAA,CAAaG,CAAQ,CAAA,CAAIC,CAAAA,CACzB,MACF,CAEA,IAAME,CAAAA,CAAU,KAAA,CAAM,OAAA,CAAQF,CAAe,CAAA,CACzCA,CAAAA,CACA,CAACA,CAAe,CAAA,CACdG,CAAAA,CAAS,KAAA,CAAM,OAAA,CAAQF,CAAc,CAAA,CACvCA,CAAAA,CACA,CAACA,CAAc,CAAA,CAGnBL,CAAAA,CAAaG,CAAQ,CAAA,CACnBA,CAAAA,GAAa,YAAA,CAAeI,EAAO,MAAA,CAAOD,CAAO,CAAA,CAAIA,CAAAA,CAAQ,MAAA,CAAOC,CAAM,EAC9E,CAUO,SAASN,EAAAA,CACdE,CAAAA,CACAL,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACM,CACN,IAAMQ,CAAAA,CAAOV,EAAWK,CAAQ,CAAA,CAC1BM,CAAAA,CAAWV,CAAAA,CAAeI,CAAQ,CAAA,CAExC,GAAIM,CAAAA,CACF,GAAIN,CAAAA,GAAa,SAAA,CAAW,CAE1B,IAAMO,CAAAA,CACHF,CAAAA,YAA4D,OAAA,EAC5DC,aACC,OAAA,CACExB,CAAAA,CAAwByB,CAAAA,CAC1BlI,CAAAA,CAAegI,CAAI,CAAA,CACnB,CAAE,GAAIA,CAAuB,CAAA,CAC3BG,CAAAA,CAA2BD,CAAAA,CAC7BlI,CAAAA,CAAeiI,CAAQ,CAAA,CACvBtK,CAAAA,CAAesK,CAAyB,CAAA,CAG5C,IAAA,IAAWhK,CAAAA,IAAO,MAAA,CAAO,IAAA,CAAKkK,CAAS,CAAA,CAAG,CACxC,IAAMC,CAAAA,CAAWnK,CAAAA,CAAI,WAAA,EAAY,CAEjC,IAAA,IAAWoK,CAAAA,IAAe5B,CAAAA,CACpB4B,EAAY,WAAA,EAAY,GAAMD,CAAAA,EAChC,OAAO3B,CAAAA,CAAO4B,CAAW,CAAA,CAI7B5B,CAAAA,CAAOxI,CAAG,CAAA,CAAIkK,CAAAA,CAAUlK,CAAG,EAC7B,CAEAuJ,CAAAA,CAAaG,CAAQ,CAAA,CAAIlB,EAC3B,CAAA,KACEe,CAAAA,CAAaG,CAAQ,CAAA,CAAI,CACvB,GAAGK,CAAAA,CACH,GAAGrK,CAAAA,CAAesK,CAAmC,CACvD,CAAA,CAAA,KAGFA,CAAAA,GAAa,MAAA,EACbxK,CAAAA,CAASuK,CAAI,GACb,EAAGA,CAAAA,YAA4C,OAAA,CAAA,GAG/CR,CAAAA,CAAaG,CAAQ,CAAA,CAAI,CAAE,GAAGK,CAAK,CAAA,EAEvC,CCxUA,IAAMM,EAAAA,CAAS,IAAI,GAAA,CACbC,CAAAA,CAAY,IACZC,EAAAA,CAAqB,EAAA,CACrBC,EAAAA,CAA6B,sBAAA,CAC7BC,EAAAA,CAA2B,qBAAA,CAM3BC,EAAAA,CAA6B,IAAI,GAAA,CAAI,CAEzC,QAAA,CACA,iBAAA,CACA,iBAAA,CAGA,eAAA,CAGA,cAAA,CAGA,SAAA,CACA,SACA,YAAA,CAGA,QAAA,CAGA,WAAA,CACA,kBAAA,CACA,aAAA,CACA,aAAA,CACA,WAAA,CAEA,eAAA,CACA,gBAAA,CACA,aAAA,CACA,YAAA,CAEA,cAAA,CACA,UACF,CAAC,CAAA,CA0BM,SAASC,GACdC,CAAAA,CACAC,CAAAA,CAAgB,IAAA,CACR,CAGR,IAAM7K,CAAAA,CAAM4K,CAAAA,CAAO,QAAA,CAEnB,GAAI5K,CAAAA,EAAO6K,CAAAA,CACT,OAAO,OAAO7K,CAAAA,GAAQtB,CAAAA,CACjBsB,CAAAA,CACAA,EAAyB4K,CAAM,CAAA,CAGtC,GAAM,CACJ,GAAA,CAAArK,CAAAA,CAAM,EAAA,CACN,MAAA,CAAAqI,CAAAA,CAAS9J,CAAAA,CACT,OAAA,CAAAkD,CAAAA,CAAU,IAAA,CACV,IAAA,CAAA6G,CAAAA,CAAO,IAAA,CACP,YAAAE,CAAAA,CAAc,aAChB,CAAA,CAAI6B,CAAAA,CAIAE,CAAAA,CAAgB,EAAA,CACpB,GAAI9I,CAAAA,CAAS,CACX,IAAIrC,CAAAA,CAEAqC,CAAAA,YAAmB,OAAA,CACrBrC,CAAAA,CAAMoC,CAAAA,CAAeC,CAAO,EAE5BrC,CAAAA,CAAMqC,CAAAA,CAKR,IAAM+I,CAAAA,CAAO,MAAA,CAAO,IAAA,CAAKpL,CAAG,CAAA,CACtBuB,EAAM6J,CAAAA,CAAK,MAAA,CAGb7J,CAAAA,CAAM,CAAA,EACR6J,CAAAA,CAAK,IAAA,EAAK,CAGZ,IAAIvF,EAAM,EAAA,CACV,IAAA,IAASvE,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIC,CAAAA,CAAK,EAAED,CAAAA,CACrByJ,EAAAA,CAA2B,GAAA,CAAIK,CAAAA,CAAK9J,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,GACtDuE,GAAOuF,CAAAA,CAAK9J,CAAC,CAAA,CAAI,GAAA,CAAMtB,CAAAA,CAAIoL,CAAAA,CAAK9J,CAAC,CAAC,CAAA,CAAI,GAAA,CAAA,CAI1C6J,CAAAA,CAAgBvF,CAAAA,CAAKC,CAAG,EAC1B,CAGA,GAAIoD,IAAW9J,CAAAA,CAAK,CAClB,IAAMkM,CAAAA,CACJpC,CAAAA,CACA0B,CAAAA,CACA/J,CAAAA,CACA+J,CAAAA,CACAvB,CAAAA,CACAuB,CAAAA,CACAQ,CAAAA,CAEF,OAAOG,EAAAA,CAAiBD,CAAQ,CAClC,CAEA,IAAIE,CAAAA,CAAa,EAAA,CACjB,GAAIrC,CAAAA,CACF,GAAI,OAAOA,CAAAA,GAASnK,CAAAA,EAAUY,CAAAA,CAAeuJ,CAAI,CAAA,CAAG,CAClD,IAAMrD,CAAAA,CAAM,MAAA,CAAOqD,CAAI,EAEvBqC,CAAAA,CAAa1F,CAAAA,CAAI,MAAA,CAAS+E,EAAAA,CAAqB/E,CAAAA,CAAMD,CAAAA,CAAKC,CAAG,EAC/D,CAAA,KAAA,GAAWqD,CAAAA,YAAgB,QAAA,CACzBA,CAAAA,CAAK,OAAA,CAAQ,CAACpJ,CAAAA,CAAOO,CAAAA,GAAQ,CAE3BkL,CAAAA,EACElL,CAAAA,CACA,GAAA,EACC,OAAOP,CAAAA,GAAUf,CAAAA,CAASe,CAAAA,CAAQ,GAAA,CAAM0L,EAAAA,CAAY1L,CAAa,CAAA,CAAA,CAClE,IACJ,CAAC,CAAA,CAEGyL,CAAAA,CAAW,MAAA,CAASX,KACtBW,CAAAA,CAAa3F,CAAAA,CAAK2F,CAAU,CAAA,CAAA,CAAA,KAAA,GAErB1L,CAAAA,CAASqJ,CAAI,CAAA,EAAK,CAACnH,CAAAA,CAAmBmH,CAAI,CAAA,CAGnDqC,CAAAA,CAAa,GAAA,CAAMC,EAAAA,CAAYtC,CAAI,CAAA,CAAA,KAC9B,CACL,IAAMzJ,CAAAA,CAAII,CAAAA,CAASqJ,CAAI,CAAA,CACnB,IAAA,CAAK,SAAA,CAAU5I,EAAAA,CAAW4I,CAAI,CAAC,CAAA,CAC/B,MAAA,CAAOA,CAAI,CAAA,CAEfqC,CAAAA,CAAa9L,CAAAA,CAAE,MAAA,CAASmL,GAAqBhF,CAAAA,CAAKnG,CAAC,CAAA,CAAIA,EACzD,CAKF,IAAM4L,CAAAA,CACJpC,CAAAA,CACA0B,CAAAA,CACA/J,CAAAA,CACA+J,CAAAA,CACAvB,CAAAA,CACAuB,CAAAA,CACAQ,CAAAA,CACAR,CAAAA,CACAY,CAAAA,CAEF,OAAOD,EAAAA,CAAiBD,CAAQ,CAClC,CAEA,IAAMI,EAAAA,CAAY,IAAI,OAAA,CAClBC,EAAAA,CAAe,CAAA,CAQnB,SAASF,EAAAA,CAAYxL,CAAAA,CAAqB,CACxC,IAAI2L,CAAAA,CAAKF,GAAU,GAAA,CAAIzL,CAAG,CAAA,CAE1B,OAAK2L,CAAAA,EACHF,EAAAA,CAAU,GAAA,CAAIzL,CAAAA,CAAM2L,CAAAA,CAAK,EAAED,EAAa,CAAA,CAGnCC,CACT,CAUA,SAASL,EAAAA,CAAiBD,EAA0B,CAClD,OAAOP,EAAAA,CAAyB,IAAA,CAAKO,CAAQ,CAAA,CACzCA,CAAAA,CAAS,OAAA,CAAQR,EAAAA,CAA4B,EAAE,CAAA,CAC7CF,CAAAA,CACA/E,CAAAA,CAAKyF,CAAQ,CAAA,CACfA,CACN,CAQA,SAASO,EAAAA,CAAejF,CAAAA,CAAiC,CAEvD,OAAKA,CAAAA,CAAM,MAAA,CAIJ9E,CAAAA,EAAQ,CAAI8E,CAAAA,CAAM,MAAA,CAHhB,KAIX,CA+BO,SAASkF,EAAAA,CACdxL,CAAAA,CAMY,CACZ,OAAOqK,EAAAA,CAAO,GAAA,CAAIrK,CAAa,CACjC,CAUO,SAASyL,EAAAA,CACdzL,CAAAA,CACAT,CAAAA,CACA0H,CAAAA,CACAC,CAAAA,CACM,CACN,GAAID,CAAAA,GAAQ,CAAA,CAAG,CACbyE,EAAAA,CAAY1L,CAAG,CAAA,CACf,MACF,CAEA,IAAM2L,CAAAA,CAAOnK,CAAAA,EAAQ,CACfoK,CAAAA,CAAQ3E,CAAAA,CAAMA,CAAAA,CAAM,GAAA,CAAO,CAAA,CAC3B4E,CAAAA,CAAc3E,CAAAA,CAAYA,EAAY,GAAA,CAAO,CAAA,CAEnDmD,EAAAA,CAAO,GAAA,CAAIrK,CAAAA,CAAK,CACd,IAAA,CAAAT,CAAAA,CACA,KAAAoM,CAAAA,CACA,KAAA,CAAOE,CAAAA,CAAc,CAAA,CAAIF,CAAAA,CAAOE,CAAAA,CAAc,MAAA,CAC9C,MAAA,CAAQ5E,IAAQ,EAAA,CAAK,MAAA,CAAY0E,CAAAA,CAAOC,CAC1C,CAAC,CAAA,CAEGA,CAAAA,CAAQ,CAAA,EACV9H,CAAAA,CACE,IAAA,CAAO9D,CAAAA,CACP,IAAM,CACJ0L,EAAAA,CAAY1L,CAAAA,CAAK,IAAI,EACvB,CAAA,CACA4L,CACF,EAEJ,CAQO,SAASF,EAAAA,CAAY1L,CAAAA,CAAa8L,CAAAA,CAAyB,KAAA,CAAa,CAC7E,GAAIA,CAAAA,CAAe,CACjB,IAAMxF,CAAAA,CAAQkF,EAAAA,CAASxL,CAAG,CAAA,CAG1B,GAAI,CAACsG,CAAAA,EAAS,CAACiF,EAAAA,CAAejF,CAAK,CAAA,CACjC,MAEJ,CAEA+D,EAAAA,CAAO,MAAA,CAAOrK,CAAG,EACnB,CAgBA,eAAsB+L,GAMpB/L,CAAAA,CACAgM,CAAAA,CACAC,CAAAA,CAMQ,CAER,GAAI,CAACjM,CAAAA,CACH,OAAO,IAAA,CAGT,IAAMsG,CAAAA,CAAQkF,EAAAA,CACZxL,CACF,CAAA,CAEA,GAAI,CAACsG,EACH,OAAO,IAAA,CAGT,IAAM4F,CAAAA,CAAc1M,CAAAA,CAASwM,CAAO,CAAA,CAAItM,CAAAA,CAAesM,CAAO,CAAA,CAAIA,CAAAA,CAE5DG,CAAAA,CAAkB,CACtB,GAAG7F,CAAAA,CAAM,IAAA,CACT,KAAM4F,CACR,CAAA,CAEME,CAAAA,CAAe,CACnB,GAAG9F,CAAAA,CACH,IAAA,CAAM6F,CACR,CAAA,CAKA,OAHA9B,EAAAA,CAAO,GAAA,CAAIrK,CAAAA,CAAKoM,CAAY,CAAA,CAC5BxE,CAAAA,CAAkB5H,EAAKmM,CAAe,CAAA,CAElCF,CAAAA,EAAYA,CAAAA,CAAS,OAAA,CAChB,MAAMzF,EAAAA,CAAWxG,CAAG,CAAA,CAGtB,IACT,CAcO,SAASqM,EAAAA,CAMdC,CAAAA,CACAC,CAAAA,CACA7D,CAAAA,CAM0E,CAE1E,GAAI,CAAC4D,CAAAA,EAAYC,CAAAA,GAAc,MAAA,EAAaA,CAAAA,GAAc,IAAA,CACxD,OAAO,KAIT,IAAMC,CAAAA,CAAS9D,CAAAA,CAAc,WAAA,EAAeV,CAAAA,CAAc,WAAA,CAK1D,GAJIwE,CAAAA,EAAUA,EAAO9D,CAAa,CAAA,EAI9BA,CAAAA,CAAc,KAAA,EAASA,CAAAA,CAAc,KAAA,GAAU,QAAA,CACjD,OAAO,IAAA,CAIT,IAAMpC,CAAAA,CAAQkF,EAAAA,CACZc,CACF,CAAA,CAEA,GAAI,CAAChG,EACH,OAAO,IAAA,CAMT,GAHkBiF,EAAAA,CAAejF,CAAK,CAAA,CAIpC,OAAAoF,EAAAA,CAAYY,CAAQ,CAAA,CACb,IAAA,CAGT,IAAM/M,CAAAA,CAAO+G,CAAAA,CAAM,IAAA,CAInB,OAAO/G,GAAQA,CAAAA,CAAK,UAAA,CAAa,IAAA,CAAOA,CAC1C,CASO,SAASkN,EAAAA,CAMdC,CAAAA,CACAhE,CAAAA,CAMAiE,CAAAA,CAAmB,KAAA,CACb,CAEN,IAAML,CAAAA,CAAW5D,CAAAA,CAAc,QAAA,CAE/B,GAAI4D,CAAAA,CAAU,CACZ,IAAMC,CAAAA,CAAY7D,CAAAA,CAAc,SAAA,CAC1BkE,CAAAA,CAAYlE,CAAAA,CAAc,SAAA,CAGhC,GACE6D,CAAAA,GACC,CAACI,CAAAA,EAAWjE,CAAAA,CAAc,WAAA,CAAA,EAC3B,EAAEkE,GAAaA,CAAAA,CAAUF,CAAAA,CAAQhE,CAAa,CAAA,CAAA,CAE9C+C,EAAAA,CAASa,CAAAA,CAAUI,CAAAA,CAAQH,CAAAA,CAAW7D,CAAAA,CAAc,SAAS,CAAA,CAAA,KACxD,CACL,IAAMpC,CAAAA,CAAQkF,EAAAA,CAASc,CAAQ,EAG3BhG,CAAAA,EAASA,CAAAA,CAAM,IAAA,EAAQA,CAAAA,CAAM,IAAA,CAAK,UAAA,EACpCoF,EAAAA,CAAYY,CAAQ,EAExB,CAEA1E,CAAAA,CAAkB0E,CAAAA,CAAUI,CAAM,CAAA,CAClCxH,EAAAA,CAAeoH,CAAQ,EAEvB,IAAMO,CAAAA,CAAenE,CAAAA,CAAc,QAAA,CAE/BmE,CAAAA,EACF3H,EAAAA,CAAe2H,CAAY,EAE/B,CACF,CC1gBA,eAAsBC,EAAAA,CAMpB9J,CAAAA,CACc,CAlChB,IAAA2F,CAAAA,CAoCE,GAAI,CAAC3F,CAAAA,CACH,OAAO,IAAA,CAIT,IAAI+J,CAAAA,CAAAA,CAAepE,CAAAA,CAAA3F,CAAAA,CAAsB,UAAtB,IAAA,CAAA,MAAA,CAAA2F,CAAAA,CAA+B,GAAA,CAAIpK,CAAAA,CAAAA,CAElDwO,CAAAA,CAEFA,CAAAA,CAAcA,CAAAA,CAAY,WAAA,GAAc,IAAA,EAAK,CAE7CA,CAAAA,CAAc,EAAA,CAIhB,IAAMC,CAAAA,CAAWD,CAAAA,CAAY,KAAA,CAAM,GAAA,CAAK,CAAC,CAAA,CAAE,CAAC,CAAA,CAExCxN,CAAAA,CAEJ,GAAI,CACF,GAAIyN,CAAAA,CAAS,QAAA,CAAS3O,CAAgB,CAAA,EAAK2O,CAAAA,CAAS,QAAA,CAAS,OAAO,CAAA,CAClEzN,CAAAA,CAAO,MAAMyD,CAAAA,CAAS,IAAA,EAAK,CAAA,KAAA,GAAA,CAE1BgK,CAAAA,CAAS,QAAA,CAAS,qBAAqB,GACtCA,CAAAA,CAAS,QAAA,CACP5O,CAAAA,CAA2B,uBAC7B,CAAA,GACF,OAAO4E,CAAAA,CAAS,QAAA,GAAarE,CAAAA,CAE7BY,CAAAA,CAAO,MAAMyD,CAAAA,CAAS,QAAA,EAAS,CAAA,KAAA,GACtB,6CAAA,CAA8C,IAAA,CAAKgK,CAAQ,CAAA,CACpEzN,CAAAA,CAAO,MAAMyD,CAAAA,CAAS,WAAA,EAAY,CAAA,KAAA,GAElCzD,CAAAA,CAAO,MAAMyD,CAAAA,CAAS,IAAA,EAAK,CAEvB,OAAOzD,CAAAA,GAASb,CAAAA,CAAQ,CAC1B,IAAMuO,EAAU1N,CAAAA,CAAK,IAAA,EAAK,CAC1B,GACG0N,CAAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAKA,CAAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAC/CA,CAAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAKA,EAAQ,QAAA,CAAS,GAAG,CAAA,CAEhD,GAAI,CACF1N,CAAAA,CAAO,IAAA,CAAK,KAAA,CAAM0N,CAAO,EAC3B,CAAA,MAAQpJ,CAAAA,CAAA,CAER,CAEJ,CAGJ,CAAA,MAASqJ,EAAQ,CAEf3N,CAAAA,CAAO,KACT,CAEA,OAAOA,CACT,CAUO,IAAM4N,EAAAA,CAAkB,CAM7BnK,CAAAA,CAMA4H,CAAAA,CACAtI,CAAAA,CAKW,IAAA,GAC2D,CACtE,IAAM8K,EAAkBxC,CAAAA,CAAO,eAAA,CACzB0B,CAAAA,CAAW1B,CAAAA,CAAO,QAAA,CAClByC,CAAAA,CAAYtB,EAAAA,CAAO,IAAA,CAAK,KAAMO,CAAkB,CAAA,CAQtD,GAAI,CAACtJ,CAAAA,CACH,OAAO,CACL,EAAA,CAAI,MAEJ,KAAA,CAAAV,CAAAA,CACA,IAAA,CAAM8K,CAAAA,EAAA,IAAA,CAAAA,CAAAA,CAAmB,IAAA,CACzB,OAAA,CAAS,IAAA,CACT,MAAA,CAAAxC,CAAAA,CACA,MAAA,CAAQyC,CAAAA,CACR,UAAA,CAAY,KAAA,CACZ,SAAA,CAAW,MACX,OAAA,CAAS,IACX,CAAA,CAQF,IAAMC,CAAAA,CACJ,OAAO,QAAA,GAAa3O,CAAAA,EAAYqE,CAAAA,YAAoB,QAAA,CAElDzD,CAAAA,CAAOyD,CAAAA,CAAS,IAAA,CAIlBoK,CAAAA,GAAoB,MAAA,GAElB7N,CAAAA,EAAS,MACR,OAAOA,CAAAA,GAASd,CAAAA,EAAU,MAAA,CAAO,IAAA,CAAKc,CAAI,CAAA,CAAE,MAAA,GAAW,CAAA,CAAA,GAE1DyD,CAAAA,CAAS,IAAA,CAAOzD,CAAAA,CAAO6N,CAAAA,CAAAA,CAGrBxC,CAAAA,CAAO,eAAA,GACT5H,CAAAA,CAAS,KAAOzD,CAAAA,CAAOuC,EAAAA,CAAYvC,CAAI,CAAA,CAAA,CAGrCqL,CAAAA,CAAO,MAAA,GACT5H,CAAAA,CAAS,IAAA,CAAOzD,CAAAA,CAAOqL,CAAAA,CAAO,MAAA,CAAOrL,CAAI,CAAA,CAAA,CAG3C,IAAMyC,CAAAA,CAAUD,CAAAA,CAAeiB,EAAS,OAAO,CAAA,CAG/C,GAAIsK,CAAAA,CAAkB,CACpB,IAAMZ,CAAAA,CAKF,CACF,IAAA,CAAM1J,CAAAA,CAAS,IAAA,CACf,QAAA,CAAUA,CAAAA,CAAS,QAAA,CACnB,EAAA,CAAIA,CAAAA,CAAS,GACb,UAAA,CAAYA,CAAAA,CAAS,UAAA,CACrB,IAAA,CAAMA,CAAAA,CAAS,IAAA,CACf,GAAA,CAAKA,CAAAA,CAAS,GAAA,CACd,MAAA,CAAQA,CAAAA,CAAS,MAAA,CACjB,UAAA,CAAYA,CAAAA,CAAS,UAAA,CAGrB,IAAA,CAAM,IACJ,OAAA,CAAQ,OAAA,CACNzD,CAAAA,YAAgB,WAAA,CAAc,IAAI,IAAA,CAAK,CAACA,CAAI,CAAC,CAAA,CAAI,IAAI,IACvD,CAAA,CACF,IAAA,CAAM,IAAM,OAAA,CAAQ,QAAQA,CAAoB,CAAA,CAChD,IAAA,CAAM,IAAM,OAAA,CAAQ,OAAA,CAAQA,CAAc,CAAA,CAE1C,MAAO,KAAO,CAAE,GAAGmN,CAAO,CAAA,CAAA,CAC1B,WAAA,CAAa,IACX,OAAA,CAAQ,QACNnN,CAAAA,YAAgB,WAAA,CAAcA,CAAAA,CAAO,IAAI,WAAA,CAAY,CAAC,CACxD,CAAA,CACF,QAAA,CAAU,IACR,OAAA,CAAQ,OAAA,CAAQA,CAAAA,YAAgB,QAAA,CAAWA,CAAAA,CAAO,IAAI,QAAU,CAAA,CAClE,KAAA,CAAO,IACL,OAAA,CAAQ,OAAA,CACN,IAAI,UAAA,CACFA,CAAAA,YAAgB,WAAA,CAAcA,CAAAA,CAAO,IAAI,WAAA,CAAY,CAAC,CACxD,CACF,CAAA,CAEF,MAAA+C,CAAAA,CACA,IAAA,CAAA/C,CAAAA,CACA,OAAA,CAAAyC,CAAAA,CACA,MAAA,CAAA4I,CAAAA,CACA,MAAA,CAAQyC,CAAAA,CACR,UAAA,CAAY,KAAA,CACZ,SAAA,CAAWrK,CAAAA,CAAS,EAAA,EAAM,CAACV,CAAAA,CAC3B,QAAS,CAAC,CAACA,CACb,CAAA,CAEA,OAAOoK,CACT,CAGA,OAAIlN,EAASwD,CAAQ,CAAA,GACnBA,CAAAA,CAAS,KAAA,CAAQV,CAAAA,CACjBU,CAAAA,CAAS,OAAA,CAAUhB,CAAAA,CACnBgB,EAAS,UAAA,CAAa,KAAA,CACtBA,CAAAA,CAAS,MAAA,CAASqK,CAAAA,CAClBrK,CAAAA,CAAS,SAAA,CAAYA,CAAAA,CAAS,EAAA,EAAM,CAACV,CAAAA,CACrCU,CAAAA,CAAS,OAAA,CAAU,CAAC,CAACV,CAAAA,CAAAA,CAGhBU,CACT,CAAA,CC3OA,SAASuK,EAAAA,CAAkBC,CAAAA,CAAmC,CAC5D,IAAM5L,CAAAA,CAAK,IAAA,CAAK,KAAA,CAAM4L,CAAU,CAAA,CAAIhM,CAAAA,EAAQ,CAE5C,OAAK,KAAA,CAAMI,CAAE,EAGN,IAAA,CAFE,IAAA,CAAK,GAAA,CAAI,CAAA,CAAG,IAAA,CAAK,KAAA,CAAMA,CAAE,CAAC,CAGrC,CAaO,SAAS6L,EAAAA,CACdC,CAAAA,CACe,CACf,GAAI,CAACA,EACH,OAAO,IAAA,CAGT,IAAM1L,CAAAA,CAAU0L,CAAAA,CAAiB,OAAA,EAAW,EAAC,CACvCC,EAAa3L,CAAAA,CAAQ,aAAa,CAAA,CAExC,GAAI2L,CAAAA,CAAY,CAEd,IAAM1J,CAAAA,CAAU,OAAO0J,CAAU,CAAA,CAEjC,GAAI,CAAC,KAAA,CAAM1J,CAAO,CAAA,EAAKA,CAAAA,EAAW,CAAA,CAChC,OAAOA,CAAAA,CAAU,GAAA,CAGnB,IAAMrC,CAAAA,CAAK2L,EAAAA,CAAkBI,CAAU,EAEvC,GAAI/L,CAAAA,GAAO,IAAA,CACT,OAAOA,CAEX,CAGA,IAAMgM,CAAAA,CAAkB,iBAAA,CAIlBC,CAAAA,CACJ7L,CAAAA,CAAQ4L,CAAAA,CAAkB,QAAQ,CAAA,EAClC5L,CAAAA,CAAQ,IAAA,CAAO4L,EAAkB,QAAQ,CAAA,CAE3C,GAAIC,CAAAA,CAAqB,CACvB,IAAM5J,CAAAA,CAAU,MAAA,CAAO4J,CAAmB,CAAA,CAE1C,GAAI,CAAC,KAAA,CAAM5J,CAAO,CAAA,CAChB,OAAOA,EAAU,GAErB,CAIA,IAAM6J,CAAAA,CACJ9L,CAAAA,CAAQ4L,CAAAA,CAAkB,KAAK,CAAA,EAAK5L,CAAAA,CAAQ,IAAA,CAAO4L,CAAAA,CAAkB,KAAK,CAAA,CAE5E,OAAIE,CAAAA,CACKP,EAAAA,CAAkBO,CAAgB,CAAA,CAGpC,IACT,CAkBA,eAAsBC,EAAAA,CAMpBC,CAAAA,CAMApD,CAAAA,CAC4E,CAC5E,GAAM,CACJ,OAAA,CAAAqD,CAAAA,CAAU,CAAA,CACV,KAAA,CAAAC,CAAAA,CAAQ,CAAA,CACR,QAAAC,CAAAA,CAAU,CAAA,CACV,QAAA,CAAAC,CAAAA,CACA,OAAA,CAAAC,CAAAA,CAAU,EAAC,CACX,WAAA,CAAAC,CACF,CAAA,CAAI1D,CAAAA,CAEA2D,CAAAA,CAAU,CAAA,CACVC,CAAAA,CAAWN,CAAAA,CACTO,EAAaR,CAAAA,CAAU,CAAA,CAAIA,CAAAA,CAAU,CAAA,CACvCvB,CAAAA,CAEJ,KAAO6B,CAAAA,EAAWE,CAAAA,EAAY,CAG5B,GAAIF,CAAAA,CAAU,CAAA,EAAK7B,CAAAA,CAAS,CAC1B,IAAMgC,CAAAA,CAAMhC,EAAO,MAAA,CACbiC,CAAAA,CAAUD,CAAAA,CAAI,OAAA,CAEhBC,CAAAA,GACF,MAAMlM,CAAAA,CAAkBkM,CAAAA,CAASjC,EAAQ6B,CAAO,CAAA,CAI5CG,CAAAA,CAAI,UAAA,GACNA,CAAAA,CAAI,QAAA,CAAWA,CAAAA,CAAI,QAAA,CACnBA,EAAI,QAAA,CAAW/D,EAAAA,CAAiB+D,CAAAA,CAAK,KAAK,CAAA,CAAA,EAGhD,CAKAhC,CAAAA,CAAS,MAAMsB,CAAAA,CAAUO,CAAAA,CAAU,CAAA,CAAGA,CAAO,CAAA,CAC7C,IAAMjM,CAAAA,CAAQoK,CAAAA,CAAO,MAGrB,GAAI,CAACpK,CAAAA,CAAO,CACV,GAAIgM,CAAAA,EAAeC,CAAAA,CAAUE,CAAAA,EACD,MAAMH,CAAAA,CAAY5B,CAAAA,CAAQ6B,CAAO,CAAA,CAEpC,CACrB,MAAM5M,CAAAA,CAAgB6M,CAAQ,CAAA,CAC9BA,CAAAA,EAAYL,CAAAA,EAAW,CAAA,CACvBK,CAAAA,CAAW,IAAA,CAAK,GAAA,CAAIA,CAAAA,CAAUJ,CAAAA,EAAYI,CAAQ,CAAA,CAClDD,CAAAA,EAAAA,CACA,QACF,CAGF,KACF,CAWA,GAR2B,MAAMK,EAAAA,CAC/BlC,CAAAA,CACA6B,CAAAA,CACAE,CAAAA,CACAH,CAAAA,CACAD,CACF,CAAA,CAGE,MAKF,GAAI/L,CAAAA,CAAM,MAAA,GAAW,GAAA,EAAOA,CAAAA,CAAM,MAAA,GAAW,GAAA,CAAK,CAEhD,IAAMuM,CAAAA,CAAepB,EAAAA,CAAgBf,CAAM,CAAA,CAIvCmC,CAAAA,GAAiB,IAAA,GACnBL,CAAAA,CAAW,IAAA,CAAK,GAAA,CAAIK,CAAAA,CAAcT,CAAAA,EAAYS,CAAY,CAAA,EAE9D,CAEA,MAAMlN,EAAgB6M,CAAQ,CAAA,CAC9BA,CAAAA,EAAYL,CAAAA,EAAW,CAAA,CACvBK,CAAAA,CAAW,IAAA,CAAK,GAAA,CAAIA,CAAAA,CAAUJ,CAAAA,EAAYI,CAAQ,CAAA,CAClDD,CAAAA,GACF,CAEA,OAAO7B,CACT,CAqBA,eAAsBkC,EAAAA,CAMpBlC,CAAAA,CACA6B,CAAAA,CACAE,CAAAA,CACAH,CAAAA,CAMAD,CAAAA,CAAoB,EAAC,CACH,CA3OpB,IAAA1F,CAAAA,CAAAmG,CAAAA,CA+OE,GAAIP,CAAAA,GAAYE,CAAAA,CACd,OAAO,KAAA,CAIT,GAAIH,CAAAA,CAAa,CACf,IAAM1K,CAAAA,CAAS,MAAM0K,CAAAA,CAAY5B,EAAQ6B,CAAO,CAAA,CAEhD,GAAI3K,CAAAA,GAAW,IAAA,CACb,OAAO,CAACA,CAEZ,CAEA,OAAO,CAAA,CAAEyK,CAAAA,EAAW,EAAC,EAAG,QAAA,CAAA,CAASS,CAAAA,CAAAA,CAAAnG,CAAAA,CAAA+D,CAAAA,CAAO,KAAA,GAAP,IAAA,CAAA,MAAA,CAAA/D,CAAAA,CAAc,MAAA,GAAd,IAAA,CAAAmG,CAAAA,CAAwB,CAAC,CAC5D,CC9OA,eAAsBC,EAAAA,CAMpBf,CAAAA,CAMAgB,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CAAc,CAAA,CACdC,CAAAA,CAAe,CAAA,CAC6D,CAC5E,GAAI,CAACH,CAAAA,CACH,OAAOhB,CAAAA,GAGT,IAAIoB,CAAAA,CAAiB,CAAA,CACjB1C,CAAAA,CAEJ,KAAA,CAAOwC,CAAAA,GAAgB,CAAA,EAAKE,CAAAA,CAAiBF,CAAAA,IACvCC,CAAAA,CAAe,CAAA,EACjB,MAAMxN,CAAAA,CAAgBwN,CAAY,CAAA,CAGpCzC,CAAAA,CAAS,MAAMsB,CAAAA,EAAU,CAEzBoB,CAAAA,EAAAA,CAGG,EAAAF,CAAAA,CAAc,CAAA,EAAKE,CAAAA,EAAkBF,CAAAA,EACtC,CAACF,CAAAA,EACAC,CAAAA,EAAqBA,CAAAA,CAAkBvC,CAAAA,CAAQ0C,CAAc,CAAA,CAAA,CAAA,EAKhE,MAAMzN,EAAgBqN,CAAe,CAAA,CAGvC,OAAOtC,CACT,CCvCA,eAAsB2C,EAAAA,CAMpBjJ,CAAAA,CACA4H,CAAAA,CAKAtF,CAAAA,CAM4E,CAvC9E,IAAAC,CAAAA,CAAAmG,CAAAA,CAwCE,IAAMpC,CAAAA,CAAS,MAAMsB,CAAAA,CAAU5H,CAAmB,CAAA,CAC5C9D,CAAAA,CAAQoK,CAAAA,CAAO,KAAA,CAErB,GAAI,CAACpK,CAAAA,CAEH,OAAAmK,EAAAA,CAAoBC,CAAAA,CAAQhE,CAAa,CAAA,CAElCgE,CAAAA,CAKLhE,CAAAA,CAAc,SAChB,MAAMjG,CAAAA,CAAkBiG,CAAAA,CAAc,OAAA,CAASpG,CAAK,CAAA,CAKtD,IAAMgN,CAAAA,CAAchN,CAAAA,CAAM,WAAA,CAqB1B,GAnBI,CAACgN,CAAAA,GAAAA,CAAe3G,CAAAA,CAAAD,CAAAA,CAAc,MAAA,GAAd,MAAAC,CAAAA,CAAsB,IAAA,CAAA,EACxCD,CAAAA,CAAc,MAAA,CAAO,IAAA,CACnB,aAAA,CACA6G,EAAAA,CAAYjN,CAAsB,CACpC,CAAA,CAKEoG,CAAAA,CAAc,QAAA,GAAa,iBAAA,GAC7BgE,CAAAA,CAAO,IAAA,CAAA,CAAQoC,CAAAA,CAAApG,CAAAA,CAAc,kBAAd,IAAA,CAAAoG,CAAAA,CAAiC,IAAA,CAAA,CAIlDrC,EAAAA,CAAoBC,CAAAA,CAAQhE,CAAAA,CAAe,IAAI,CAAA,CAGrB,CAAC4G,CAAAA,EAAe5G,CAAAA,CAAc,eAAA,CAEjC,CACrB,IAAM8G,CAAAA,CAAW9G,CAAAA,CAAc,SAE/B,GAAI8G,CAAAA,GAAaxQ,EAAAA,CACf,OAAO,OAAA,CAAQ,MAAA,CAAOsD,CAAK,CAAA,CAIzBkN,CAAAA,GAAa,QAAA,EACf,MAAM,IAAI,OAAA,CAAQ,IAAM,IAAI,EAEhC,CAEA,OAAO9C,CACT,CAGA,IAAM+C,EAAAA,CAAoB,CACxB,eAAA,CACA,qBAAA,CACA,QAAA,CACA,WACF,CAAA,CAMA,SAASF,EAAAA,CAAYjN,CAAAA,CAAqC,CAExD,IAAMsI,EAAS,CACb,GAAGtI,CAAAA,CAAM,MAAA,CACT,IAAA,CAAM,MAAA,CACN,IAAA,CAAM,MAAA,CACN,SAAU,MAAA,CACV,QAAA,CAAU,MAAA,CACV,OAAA,CAASP,CAAAA,CAAeO,CAAAA,CAAM,MAAA,CAAO,OAAwB,CAC/D,CAAA,CAEA,IAAA,IAAWD,CAAAA,IAAQoN,EAAAA,CACb7E,CAAAA,CAAO,OAAA,CAAQvI,CAAI,CAAA,GACrBuI,CAAAA,CAAO,OAAA,CAAQvI,CAAI,CAAA,CAAI,YAAA,CAAA,CAI3B,IAAMqN,CAAAA,CAAO,MAAA,CAAO,OAAO,IAAI,KAAA,CAAMpN,CAAAA,CAAM,OAAO,CAAA,CAAGA,CAAAA,CAAO,CAC1D,MAAA,CAAAsI,CAAAA,CACA,OAAA,CAASA,CAAAA,CACT,QAAA,CAAUtI,CAAAA,CAAM,QAAA,EAAY,CAAE,GAAGA,EAAM,QAAA,CAAU,MAAA,CAAAsI,CAAO,CAC1D,CAAC,CAAA,CAED,OAAA8E,CAAAA,CAAK,IAAA,CAAOpN,CAAAA,CAAM,IAAA,CAClBoN,CAAAA,CAAK,KAAA,CAAQpN,CAAAA,CAAM,KAAA,CAEZoN,CACT,CAEO,SAASC,EAAAA,CAOdrN,CAAAA,CACAU,CAAAA,CAMA0F,CAAAA,CAMM,CACNpG,CAAAA,CAAM,MAAA,CAASA,EAAM,MAAA,GAAUU,CAAAA,EAAA,IAAA,CAAA,MAAA,CAAAA,CAAAA,CAAU,MAAA,CAAA,EAAU,CAAA,CACnDV,CAAAA,CAAM,UAAA,CAAaA,EAAM,UAAA,GAAcU,CAAAA,EAAA,IAAA,CAAA,MAAA,CAAAA,CAAAA,CAAU,UAAA,CAAA,EAAc,EAAA,CAC/DV,CAAAA,CAAM,MAAA,CAASA,CAAAA,CAAM,OAAA,CAAUoG,CAAAA,CAC/BpG,CAAAA,CAAM,QAAA,CAAWU,CAAAA,CACjBV,CAAAA,CAAM,WAAA,CAAcA,EAAM,IAAA,GAAS1D,GACrC,CCtIA,IAAMgR,EAAAA,CAAmB,MAAA,CAAO,MAAA,CAAO,CACrC,UAAA,CAAY,IACd,CAAC,CAAA,CAqBD,eAAsBC,EAAAA,CAMpBtP,CAAAA,CACAgI,CAAAA,CAKW,KACiE,CAI5E,GAAIA,CAAAA,EAAa,OAAOA,CAAAA,CAAU,QAAA,EAAa,QAAA,CAAU,CACvD,IAAMuH,CAAAA,CAASzD,EAAAA,CAKb9D,CAAAA,CAAU,QAAA,CAAUA,CAAAA,CAAU,SAAA,CAAWA,CAAS,EAEpD,GAAIuH,CAAAA,CACF,OAAOA,CAEX,CAEA,IAAMC,CAAAA,CAAgBzH,EAAAA,CAKpB/H,CAAAA,CAAKgI,CAAS,CAAA,CAEV,CACJ,OAAA,CAAAhE,CAAAA,CACA,WAAA,CAAAyL,CAAAA,CACA,SAAA1D,CAAAA,CACA,UAAA,CAAA9H,CAAAA,CACA,SAAA,CAAA+H,CAAAA,CACA,SAAA,CAAArF,CAAAA,CACA,cAAA,CAAAE,CAAAA,CACA,kBAAA,CAAAC,CAAAA,CACA,eAAA,CAAA2H,CAAAA,CAAkB,CACpB,CAAA,CAAIe,CAAAA,CACEE,EAAiB1D,CAAAA,GAAc,MAAA,EAAarF,CAAAA,GAAc,MAAA,CAE1DgJ,CAAAA,CAAgB,CAAC,EACrB5D,CAAAA,EACA/H,CAAAA,EACAC,CAAAA,EACAyL,CAAAA,EACAD,CAAAA,EACA5I,CAAAA,EACAC,CAAAA,CAAAA,CAGE8I,CAAAA,CAA2B,IAAA,CAQ/B,GALID,CAAAA,GACFC,CAAAA,CAAYxF,EAAAA,CAAiBoF,CAAa,CAAA,CAAA,CAIxCI,CAAAA,EAAaF,CAAAA,CAAgB,CAC/B,IAAMH,CAAAA,CAASzD,EAAAA,CAKb8D,CAAAA,CAAW5D,CAAAA,CAAWwD,CAAa,CAAA,CAErC,GAAID,EACF,OAAOA,CAEX,CAGA,GAAIK,CAAAA,EAAa3L,CAAAA,CAAY,CAC3B,IAAM4L,EAAW/K,EAAAA,CAEf8K,CAAAA,CAAW3L,CAAU,CAAA,CAEvB,GAAI4L,CAAAA,CACF,OAAOA,CAEX,CAEA,IAAMC,CAAAA,CAAcN,CAAAA,CAAc,KAAA,EAAS,EAAC,CACtC,CAAE,OAAA,CAAA9B,EAAAA,CAAU,CAAA,CAAG,YAAA,CAAAqC,EAAa,CAAA,CAAID,CAAAA,CAGhCE,EAAAA,CAAgB,MAAOnK,EAA8BmI,EAAAA,CAAU,CAAA,GAAM,CAIpEA,EAAAA,GACC4B,CAAAA,EAAa,CAAC/J,CAAAA,GACZc,CAAAA,CACoBmF,EAAAA,CACpB8D,CAAAA,CACA5D,CAAAA,CACAwD,CACF,CAAA,GAKEtE,EAAAA,CAAS0E,CAAAA,CAAWP,EAAAA,CAAkBrD,EAAWrF,CAAS,CAAA,CAC1DU,CAAAA,CAAkBuI,CAAAA,CAAWP,EAAgB,CAAA,CAAA,CAG/ChI,CAAAA,CAAkBuI,CAAAA,CAAWP,EAAgB,CAAA,CAAA,CAKjDG,CAAAA,CAAc,QAAA,CAAWI,CAAAA,CAAAA,CAG3B,IAAM5P,CAAAA,CAAMwP,CAAAA,CAAc,IAGpB/K,EAAAA,CAAaV,EAAAA,CACjB6L,CAAAA,CACA5P,CAAAA,CACAgE,CAAAA,CACAC,CAAAA,EAAc,CAAA,CACd,CAAC,CAACwL,CAAAA,CAEF,CAAC,EAAEzL,CAAAA,GAAY,CAACgK,EAAAA,EAAW+B,EAAAA,CAAAA,CAC7B,EAIM5H,CAAAA,CAAgBqH,CAAAA,CAEtBrH,CAAAA,CAAc,MAAA,CAAS1D,EAAAA,CAAW,MAAA,CAElC,IAAI0H,EAAAA,CAMA1J,CAAAA,CAKO,IAAA,CAEX,GAAI,CACE+M,CAAAA,CAAc,SAAA,GAOZI,CAAAA,EAAa3L,CAAAA,EAAc,CAAC+J,EAAAA,EAC9B,MAAM,IAAA,CAGR,MAAM9L,CAAAA,CAAkBsN,CAAAA,CAAc,SAAA,CAAWrH,CAAa,CAAA,CAAA,CAIhE,IAAMjB,CAAAA,CAAKsI,CAAAA,CAAc,OAAA,CAkBzB,GAhBA/M,CAAAA,CAAYyE,CAAAA,CACR,MAAMA,CAAAA,CACJlH,CAAAA,CACAmI,CACF,CAAA,CACA,MAAM,KAAA,CACJnI,CAAAA,CACAmI,CACF,CAAA,CAQAlJ,CAAAA,CAASwD,CAAQ,CAAA,GAEf,OAAO,QAAA,GAAarE,CAAAA,EAAYqE,CAAAA,YAAoB,SACtDA,CAAAA,CAAS,IAAA,CAAO0F,CAAAA,CAAc,MAAA,CAC1B,MAAMA,CAAAA,CAAc,MAAA,CAAO1F,CAAQ,EACnC,MAAM8J,EAAAA,CAAkB9J,CAAQ,CAAA,CAC3ByE,CAAAA,GAEH,MAAA,GAAUzE,CAAAA,EAAY,MAAA,GAAUA,IAEpCA,CAAAA,CAAW,CAAE,IAAA,CAAMA,CAAS,CAAA,CAAA,CAAA,CAYhCA,CAAAA,CAAS,MAAA,CAAS0F,CAAAA,CAId1F,CAAAA,CAAS,EAAA,GAAO,KAAA,CAAA,EAAa,CAACA,CAAAA,CAAS,EAAA,CAAA,CACzC,MAAM,IAAIE,GACRwF,CAAAA,CAAc,MAAA,CACZ,MAAA,CACAnI,CAAAA,CACA,mBAAA,EACCyC,CAAAA,CAAS,MAAA,EAAU,IAAA,CAAA,CACtB0F,CAAAA,CACA1F,CACF,CAAA,CAIJ0J,EAAAA,CAASS,EAAAA,CAKPnK,CAAAA,CAAU0F,CAAa,CAAA,CAEzB,IAAM8H,CAAAA,CAAaT,CAAAA,CAAc,UAAA,CAE7BS,CAAAA,EACF,MAAM/N,CAAAA,CAAkB+N,CAAAA,CAAY9D,EAAM,EAE9C,CAAA,MAASQ,CAAAA,CAAQ,CACf,IAAM5K,CAAAA,CAAQ4K,CAAAA,CAQdyC,EAAAA,CACErN,EACAU,CAAAA,CACA0F,CACF,CAAA,CAGAgE,EAAAA,CAASS,EAAAA,CAKPnK,CAAAA,CAAU0F,CAAAA,CAAepG,CAAK,EAClC,CAEA,OAAOoK,EACT,CAAA,CAKM+D,EAAAA,CACJxC,EAAAA,CAAU,CAAA,CACL7H,GACC2H,EAAAA,CACE,CAAC2C,EAAAA,CAAGnC,CAAAA,GAAYgC,EAAAA,CAAcnK,CAAAA,CAAqBmI,CAAO,CAAA,CAC1D8B,CACF,CAAA,CACFE,EAAAA,CAEAI,EAAAA,CAA2B,CAACvK,CAAAA,CAAsB,KAAA,GACtDiJ,EAAAA,CACEjJ,EACAqK,EAAAA,CACAV,CACF,CAAA,CAGIa,EAAAA,CAAmB5B,CAAAA,CACrBD,EAAAA,CACE4B,EAAAA,CACA3B,CAAAA,CACAe,CAAAA,CAAc,iBAAA,CACdA,CAAAA,CAAc,kBAAA,CACdA,CAAAA,CAAc,YAChB,CAAA,CACAY,EAAAA,GAGJ,OAAIR,CAAAA,GACE3L,CAAAA,EACFW,EAAAA,CAAmBgL,CAAAA,CAAWS,EAAgB,CAAA,CAAA,CAI5C1J,CAAAA,EAAaE,CAAAA,EAAkBC,CAAAA,GACjCN,EAAAA,CACEoJ,CAAAA,CACAQ,EAAAA,CACA,MAAA,CACAzJ,CAAAA,CACAyJ,EAAAA,CACA,CAAC,CAACvJ,CAAAA,CACF,CAAC,CAACC,CACJ,CAAA,CAAA,CAIGuJ,EACT,CCtUA,SAASC,EAAAA,CAGPjG,CAAAA,CAAyC,CACzC,IAAMkG,CAAAA,CAAYlG,CAAAA,CAAO,SAAA,CAQzB,SAASmG,EAAqBC,CAAAA,CAAqC,CACjE,OAAA,OAAA,CAAQ,KAAA,CAAM,MAAA,CAASA,CAAAA,CAAe,kBAAkB,CAAA,CAEjD,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAC7B,CAEA,IAAMC,CAAAA,CAAsD,CAC1D,OAAArG,CAAAA,CACA,SAAA,CAAAkG,CAAAA,CASA,MAAM,OAAA,CAAQE,CAAAA,CAActI,CAAAA,CAAgB,EAAC,CAAG,CAG9C,IAAMwI,CAAAA,CAAiB/R,CAAAA,CAAO2R,CAAAA,CAAWE,CAAsB,CAAA,CAC3DF,EAAUE,CAAY,CAAA,CACtB,MAAA,CACEG,CAAAA,CACJD,CAAAA,EACC,CAAE,GAAA,CAAK,MAAA,CAAOF,CAAY,CAAE,CAAA,CACzBzQ,CAAAA,CAAM4Q,CAAAA,CAAgB,GAAA,CAItBC,CAAAA,CAAc7Q,CAAAA,CACjB,QAAQ,WAAA,CAAa,EAAE,CAAA,CAEvB,OAAA,CAAQ,eAAA,CAAiB,EAAE,CAAA,CAG9B,GAAI,YAAY,IAAA,CAAK6Q,CAAW,CAAA,CAC9B,MAAM,IAAI,KAAA,CAAM,qCAAqC,CAAA,CAKvD,IAAMC,CAAAA,CAAe,sBAAA,CAAuB,IAAA,CAAKD,CAAW,CAAA,CAAA,CAExDF,CAAAA,EAAA,IAAA,CAAA,MAAA,CAAAA,CAAAA,CAAgB,GAAA,IAAQ3Q,CAAAA,CACtB6H,CAAAA,CAAa+I,CAAAA,CAAiBzI,CAAa,CAAA,CAC3CA,CAAAA,CACFN,CAAAA,CAAaA,EAAawC,CAAAA,CAAQuG,CAAe,CAAA,CAAGzI,CAAa,CAAA,CAIrE,OAAOmH,EAAAA,CAAOtP,CAAAA,CAAK8Q,CAAY,CACjC,CACF,CAAA,CAOA,OAAO,IAAI,KAAA,CACTJ,CAAAA,CACA,CACE,GAAA,CAAIK,CAAAA,CAASC,CAAAA,CAAuB,CAClC,GAAIA,CAAAA,IAAQN,CAAAA,CACV,OAAOA,CAAAA,CAAWM,CAA0C,CAAA,CAK9D,GAAI,EAAA,OAAOA,CAAAA,EAAS,QAAA,EAAYA,CAAAA,GAAS,QAKzC,OAAIpS,CAAAA,CAAO2R,CAAAA,CAAWS,CAAI,CAAA,CACjBN,CAAAA,CAAW,OAAA,CAAQ,IAAA,CAAK,KAAMM,CAAI,CAAA,CAGpCR,CAAAA,CAAqB,IAAA,CAAK,IAAA,CAAMQ,CAAI,CAC7C,CACF,CACF,CACF","file":"index.global.js","sourcesContent":["export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CHARSET_UTF_8 = 'charset=utf-8';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\nexport const FUNCTION = 'function';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n\nexport const REJECT = 'reject';\n\n// Larger timer delays overflow and fire immediately in browsers and Node.js (~24.8 days)\nexport const MAX_DELAY_MS = 2147483647;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, MAX_DELAY_MS, OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\n// Prevent stack overflow with recursion depth limit\nconst MAX_DEPTH = 10;\n\nexport const hasOwn = (o: any, k: string) =>\n Object.prototype.hasOwnProperty.call(o, k);\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 (hasOwn(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function checks for dangerous properties like '__proto__', 'constructor',\n * and 'prototype'. If none are present, the object is returned as-is (zero-copy fast path).\n * Otherwise, a shallow copy is created with the dangerous properties removed.\n *\n * @param obj - The object to sanitize\n * @returns A safe object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const hasProto = hasOwn(obj, '__proto__');\n const hasCtor = hasOwn(obj, 'constructor');\n const hasPrototype = hasOwn(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n // Copy key by key, as a spread compiled to assignments would let \"__proto__\" set the prototype\n const safeObj = {} as Record;\n\n for (const key of Object.keys(obj)) {\n if (key !== '__proto__' && key !== 'constructor' && key !== 'prototype') {\n safeObj[key] = obj[key];\n }\n }\n\n return safeObj as T;\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 // Without a prototype, a \"__proto__\" key is kept as a regular property instead of setting the prototype\n const sortedObj = Object.create(null) as Record;\n\n Object.keys(obj)\n .sort()\n .forEach((k) => (sortedObj[k] = obj[k]));\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 + (baseUrl.includes('?') ? '&' : '?') + 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, depth = 0) => {\n // Stop recursion if maximum depth is reached\n if (depth >= MAX_DEPTH) {\n return s;\n }\n\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 depth + 1,\n );\n }\n } else if (isObject(obj)) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key], depth + 1);\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], depth + 1);\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 // This is for compatibility with server frameworks that expect the literal notation\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 || url.indexOf(':') === -1) {\n return url;\n }\n\n // Use a single RegExp and avoid unnecessary casts and function calls\n // Precompute keys for faster lookup\n const params = urlPathParams as DefaultUrlParams;\n\n // Use a replacer function that avoids extra work\n return url.replace(/:([a-zA-Z0-9_]+)/g, (match, key) => {\n // Use hasOwnProperty for strict key existence check\n if (hasOwn(params, key)) {\n const value = params[key];\n\n // Only replace if value is not undefined or null\n if (value !== undefined && value !== null) {\n const encoded = encodeURIComponent(String(value));\n\n // These can't be encoded, and URL parsers would move the request to another path\n if (encoded === '.' || encoded === '..') {\n throw new Error('Path params \".\" and \"..\" not allowed.');\n }\n\n return encoded;\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL starts with a scheme (e.g., \"http://\", \"https://\").\n * A \"://\" appearing later, e.g. in a query string, does not make the URL absolute.\n *\n * @param url - The URL string to check.\n * @returns `true` if the URL is absolute, otherwise `false`.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n}\n\nexport const timeNow = () => Date.now();\n\nexport const noop = () => {};\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 (value === 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 (\n typeof globalThis !== UNDEFINED &&\n typeof globalThis.Buffer !== UNDEFINED &&\n globalThis.Buffer.isBuffer(value)\n ) {\n return false;\n }\n\n if (value instanceof Date || isSearchParams(value)) {\n return false;\n }\n\n if (isObject(value)) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` (plain object)\n if (proto === Object.prototype) {\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 const delayInvocation = (ms: number): Promise =>\n new Promise((resolve) =>\n setTimeout(resolve, Math.min(ms, MAX_DELAY_MS), true),\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, depth = 0): any {\n if (depth >= MAX_DEPTH) {\n return data;\n }\n\n if (data && isObject(data) && typeof data.data !== UNDEFINED) {\n return flattenData(data.data, depth + 1);\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 // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key.toLowerCase()] = value;\n });\n } else {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n // Assigning \"__proto__\" would set the prototype of the result\n if (hasOwn(headers, key) && key !== '__proto__') {\n headersObject[key.toLowerCase()] = headers[key];\n }\n }\n }\n\n return headersObject;\n}\n\n/**\n * Determines if the current environment is a browser.\n *\n * @returns {boolean} - True if running in a browser environment, false otherwise.\n */\nexport function isBrowser(): boolean {\n // For node and some mobile frameworks like React Native, `add/removeEventListener` doesn't exist on window!\n return (\n typeof window !== UNDEFINED && typeof window.addEventListener === FUNCTION\n );\n}\n\n/**\n * Creates an abort/timeout error compatible with all JS runtimes.\n * Falls back to a plain Error with the correct `name` when DOMException is unavailable (e.g. React Native).\n *\n * @param {string} message - The error message.\n * @param {string} name - The error name (e.g. 'AbortError', 'TimeoutError').\n * @returns {DOMException | Error} - An error object with the specified name.\n */\nexport function createAbortError(\n message: string,\n name: string,\n): DOMException | Error {\n if (typeof DOMException !== UNDEFINED) {\n return new DOMException(message, name);\n }\n\n const error = new Error(message);\n error.name = name;\n\n return error;\n}\n\n/**\n * Detects if the user is on a slow network connection\n * @returns {boolean} True if connection is slow, false otherwise or if detection unavailable\n */\nexport const isSlowConnection = (): boolean => {\n const conn = typeof navigator !== UNDEFINED && (navigator as any).connection;\n\n return conn && ['slow-2g', '2g', '3g'].includes(conn.effectiveType);\n};\n","import { FUNCTION } from './constants';\nimport type { InterceptorFunction } from './types/interceptor-manager';\nimport { isObject, sanitizeObject } from './utils';\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 Args - Type of additional arguments.\n * @template I - Type of interceptors.\n *\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n * @param {T} data - The data object to process.\n * @param {...Args} args - Additional arguments to pass to interceptors.\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptors<\n T extends object,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Args extends any[] = any[],\n I = InterceptorFunction | InterceptorFunction[],\n>(interceptors: I | undefined, data: T, ...args: Args): Promise {\n if (!interceptors) {\n return;\n }\n\n const merge = (v: unknown) =>\n v &&\n isObject(data) &&\n isObject(v) &&\n Object.assign(data, sanitizeObject(v));\n\n if (typeof interceptors === FUNCTION) {\n merge(await (interceptors as InterceptorFunction)(data, ...args));\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n merge(await interceptor(data, ...args));\n }\n }\n}\n","import type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\n/**\n * This is a base error class\n */\nexport class FetchError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends Error {\n status: number;\n statusText: string;\n config: RequestConfig;\n isCancelled: boolean;\n\n constructor(\n message: string,\n public request: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n public response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message);\n\n this.name = 'FetchError';\n this.status = response ? response.status : 0;\n this.statusText = response ? response.statusText : '';\n this.config = request;\n this.isCancelled = false;\n }\n}\n","import { FetchError } from './fetch-error';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\nexport class ResponseError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends FetchError {\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message, request, response);\n\n this.name = 'ResponseError';\n }\n}\n","/**\n * @module timeout-wheel\n * @description\n * Ultra-minimal timing wheel implementation optimized for max performance & many requests.\n * For most of the cases it's 4-100x faster than setTimeout and setInterval alone.\n * Provides efficient scheduling and cancellation of timeouts using a circular array.\n *\n * Position 0 → 1 → 2 → ... → 599 → 0 → 1 → 2 ...\n * Time: 0s 1s 2s 599s 600s 601s 602s\n *\n * The timing wheel consists of 600 slots (one per second for 10 min).\n * Each slot contains a list of timeout items, each associated with a unique key and callback.\n * Timeouts are scheduled by placing them in the appropriate slot based on the delay in seconds.\n * The wheel advances every second, executing and removing callbacks as their timeouts expire.\n * Defaults to setTimeout if the delay doesn't fit in the wheel (~10 minutes) or is not divisible by 1000.\n *\n * @remarks\n * - Designed for minimal footprint and simplicity.\n * - Only supports second-level granularity (minimum timeout: 1 second).\n * - Timeouts never fire early, but may fire up to 1 second late.\n * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { MAX_DELAY_MS } from './constants';\nimport { noop, timeNow } from './utils';\n\ntype TimeoutCallback = () => unknown | Promise;\ntype TimeoutItem = [string, TimeoutCallback]; // [key, callback]\n\nconst WHEEL_SIZE = 600; // 600 slots for 10 min (1 slot per second)\nconst SECOND = 1000; // 1 second in milliseconds\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\nlet lastTick = 0; // Time when the wheel last advanced (or started)\nlet timer: NodeJS.Timeout | null = null;\n\nconst handleCallback = ([key, callback]: TimeoutItem): void => {\n keyMap.delete(key);\n\n try {\n const result = callback();\n if (result && result instanceof Promise) {\n // Silently ignore async errors to prevent wheel from stopping\n result.catch(noop);\n }\n } catch {\n // Ignore callback errors to prevent wheel from stopping\n }\n};\n\nexport const addTimeout = (\n key: string,\n cb: TimeoutCallback,\n ms: number,\n): void => {\n removeTimeout(key);\n\n // A running wheel is already part-way through its current second, so the timeout\n // waits one more slot to never fire early. A new wheel starts its first second now.\n const seconds = ms / SECOND + (timer && timeNow() !== lastTick ? 1 : 0);\n\n // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || seconds >= WHEEL_SIZE || ms % SECOND !== 0) {\n keyMap.set(key, [\n setTimeout(\n handleCallback.bind(null, [key, cb]),\n Math.min(ms, MAX_DELAY_MS),\n ),\n ]); // Store timeout ID instead of slot\n\n return;\n }\n\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n lastTick = timeNow();\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n lastTick = timeNow();\n const slot = wheel[position];\n\n // Use slot.length directly (not cached) so mid-iteration mutations\n // from callbacks (e.g. removeTimeout) are handled correctly\n for (let i = 0; i < slot.length; i++) {\n handleCallback(slot[i]);\n }\n\n slot.length = 0; // Reuse array, avoid GC allocation\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }, SECOND);\n }\n};\n\nexport const removeTimeout = (key: string): void => {\n const slotOrTimeout = keyMap.get(key);\n\n if (slotOrTimeout !== undefined) {\n // It's a Timeout object from setTimeout\n if (Array.isArray(slotOrTimeout)) {\n clearTimeout(slotOrTimeout[0]);\n } else {\n const slotArr = wheel[slotOrTimeout];\n\n for (let i = 0; i < slotArr.length; i++) {\n if (slotArr[i][0] === key) {\n slotArr.splice(i, 1);\n break;\n }\n }\n }\n\n keyMap.delete(key);\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }\n};\n\nexport const clearAllTimeouts = () => {\n // Clear native setTimeout timeouts first!\n keyMap.forEach((value) => {\n if (Array.isArray(value)) {\n clearTimeout(value[0]);\n }\n });\n\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n\n keyMap.clear();\n\n for (let i = 0; i < WHEEL_SIZE; i++) {\n wheel[i].length = 0;\n }\n\n position = 0;\n};\n","/**\n * @module inflight-manager\n *\n * Manages in-flight asynchronous requests using unique keys to enable deduplication and cancellation.\n *\n * Provides utilities for:\n * - Deduplication of requests within a configurable time window (`dedupeTime`)\n * - Timeout management and automatic request abortion\n * - AbortController lifecycle and cancellation logic\n * - Concurrency control and request state tracking\n * - In-flight promise deduplication to prevent duplicate network calls\n *\n * @remarks\n * - Requests with the same key within the deduplication interval share the same AbortController and in-flight promise.\n * - Supports cancellation of previous requests when a new one with the same key is issued, if `isCancellable` is enabled.\n * - Timeout logic ensures requests are aborted after a specified duration, if enabled.\n * - Internal queue state is managed via a Map, keyed by request identifier.\n * - Polled requests are also marked as \"in-flight\" to prevent duplicate requests.\n */\n\nimport { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { createAbortError, timeNow } from './utils';\n\nexport type InFlightItem = [\n AbortController, // AbortController for the request\n boolean, // Whether timeout is enabled for the request\n number, // Timestamp when the request was marked in-flight\n boolean, // isCancellable - whether the request can be cancelled\n Promise | null, // Optional in-flight promise for deduplication\n];\n\nconst inFlight: Map = 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 {string | null} key - Unique key for the request (e.g. cache key).\n * @param {string} url - The request URL (for error messages/timeouts).\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 {AbortController} - A promise that resolves to an AbortController.\n */\nexport function markInFlight(\n key: string | null,\n url: string,\n timeout: number | undefined,\n dedupeTime: number,\n isCancellable: boolean,\n isTimeoutEnabled: boolean,\n): AbortController {\n if (!key) {\n return new AbortController();\n }\n\n const now = timeNow();\n const item = inFlight.get(key);\n let prevPromise: Promise | null = null;\n\n // Previous request is in-flight, check if we can reuse it\n if (item) {\n const prevController = item[0];\n const prevIsCancellable = item[3];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (\n !prevIsCancellable &&\n now - item[2] < dedupeTime &&\n !prevController.signal.aborted\n ) {\n return prevController;\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 (prevIsCancellable) {\n prevController.abort(\n createAbortError('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n removeTimeout(key);\n prevPromise = item[4];\n }\n\n const controller = new AbortController();\n\n inFlight.set(key, [\n controller,\n isTimeoutEnabled,\n now,\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n createAbortError(url + ' aborted due to timeout', TIMEOUT_ERROR),\n );\n },\n timeout as number,\n );\n }\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param key - Unique key for the request.\n * @param {boolean} error - Optional error to abort the request with. If null, the request is simply removed but no abort sent.\n * @returns {Promise} - A promise that resolves when the request is aborted and removed.\n */\nexport async function abortRequest(\n key: string | null,\n error: DOMException | Error | null | string = null,\n): Promise {\n // If the key is not in the queue, there's nothing to remove\n if (key) {\n const item = inFlight.get(key);\n\n if (item) {\n // If the request is not yet aborted, abort it with the provided error\n if (error) {\n const controller = item[0];\n controller.abort(error);\n }\n\n removeInFlight(key);\n }\n }\n}\n\n/**\n * Removes a request from the in-flight queue without aborting or clearing timeout.\n *\n * @param key - Unique key for the request.\n */\nexport function removeInFlight(key: string | null): void {\n removeTimeout(key!);\n inFlight.delete(key!);\n}\n\n/**\n * Gets the AbortController for a request key.\n *\n * @param key - Unique key for the request.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n key: string,\n): Promise {\n const item = inFlight.get(key);\n\n return item?.[0];\n}\n\n/**\n * Adds helpers for in-flight promise deduplication.\n *\n * @param key - Unique key for the request.\n * @param promise - The promise to store.\n */\nexport function setInFlightPromise(\n key: string,\n promise: Promise,\n): void {\n const item = inFlight.get(key);\n if (item) {\n // store the promise at index 4 — item is already the Map's reference, no need to re-set\n item[4] = promise;\n }\n}\n\n/**\n * Retrieves the in-flight promise for a request key if it exists and is within the dedupeTime interval.\n *\n * @param key - Unique key for the request.\n * @param dedupeTime - Deduplication time in milliseconds.\n * @returns {Promise | null} - The in-flight promise or null.\n */\nexport function getInFlightPromise(\n key: string | null,\n dedupeTime: number,\n): Promise | null {\n if (!key) {\n return null;\n }\n\n const prevReq = inFlight.get(key);\n\n if (\n prevReq &&\n // If the request is in-flight and has a promise\n prevReq[4] &&\n // If the request is cancellable, we will not reuse it\n !prevReq[3] &&\n // If the request is within the dedupeTime\n timeNow() - prevReq[2] < dedupeTime &&\n // If one request is cancelled, ALL deduped requests get cancelled\n !prevReq[0].signal.aborted\n ) {\n return prevReq[4] as Promise;\n }\n\n return null;\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","/**\n * @module revalidator-manager\n *\n * Provides utilities for managing cache revalidation functions, including:\n * - Registering and unregistering revalidators for specific cache keys.\n * - Triggering revalidation for a given key.\n * - Enabling or disabling automatic revalidation on window focus and if user comes back online for specific keys.\n * - Attaching and removing global focus and online event handlers to trigger revalidation.\n *\n * Revalidators are functions that can be registered to revalidate cache entries when needed.\n * They are typically used to refresh data in the cache when the window gains focus or when specific actions occur.\n * @performance O(1) lookup by key makes it blazing fast to register, unregister, and revalidate cache entries.\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n * @remarks\n * - Designed to be used in various environments (Deno, Node.js, Bun, Browser, etc.) to ensure cache consistency and freshness.\n */\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { FetchResponse } from './types';\nimport { isBrowser, noop, timeNow } from './utils';\n\nexport type RevalidatorFn = (\n isStaleRevalidation?: boolean,\n) => Promise;\n\ntype EventType = 'focus' | 'online';\n\ntype RevalidatorEntry = [\n RevalidatorFn, // main revalidator\n number, // lastUsed\n number, // ttl\n number?, // staleTime\n RevalidatorFn?, // bgRevalidator\n boolean?, // refetchOnFocus\n boolean?, // refetchOnReconnect\n];\n\nconst DEFAULT_TTL = 3 * 60 * 1000; // Default TTL of 3 minutes\nconst revalidators = new Map();\n\n/**\n * Stores cleanup functions for active event handlers (browser or custom providers).\n * Each entry removes the corresponding event listener when called.\n * @remarks\n * - Improves performance by reducing the number of event listeners.\n * - Enables efficient O(1) lookup and management of event handlers for revalidation.\n */\nconst eventHandlers = new Map void>();\n\n/** Subscribe to an event and return a cleanup function */\nexport type EventProvider = (handler: () => void) => () => void;\n\nconst customEventProviders = new Map();\n\n/**\n * Registers a custom event provider for 'focus' or 'online' events.\n * Useful for non-browser environments like React Native.\n *\n * @param type - The event type ('focus' or 'online').\n * @param provider - A function that subscribes to the event and returns a cleanup function.\n */\nexport function setEventProvider(\n type: EventType,\n provider: EventProvider,\n): void {\n customEventProviders.set(type, provider);\n\n // Re-register if already active\n if (eventHandlers.has(type)) {\n removeEventHandler(type);\n addEventHandler(type);\n }\n}\n\n/**\n * Triggers revalidation for all registered entries based on the given event type.\n * For example, if it's a 'focus' event, it will revalidate entries that have the `refetchOnFocus` flag set.\n * Updates the timestamp and invokes the revalidator function for each applicable entry.\n *\n * @param type - The type of event that caused the revalidation (e.g., 'focus' or 'online').\n * @param isStaleRevalidation - If `true`, uses background revalidator and doesn't mark as in-flight.\n */\nexport function revalidateAll(\n type: EventType,\n isStaleRevalidation: boolean = true,\n) {\n const flagIndex = type === 'focus' ? 5 : 6;\n const now = timeNow();\n\n revalidators.forEach((entry) => {\n if (!entry[flagIndex]) {\n return;\n }\n\n entry[1] = now;\n\n // If it's a stale revalidation, use the background revalidator function\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n if (revalidator) {\n Promise.resolve(revalidator(isStaleRevalidation)).catch(noop);\n }\n });\n}\n\n/**\n * Revalidates an entry by executing the registered revalidation function.\n *\n * @param key The unique identifier for the cache entry to revalidate. If `null`, no revalidation occurs.\n * @param isStaleRevalidation - If `true`, it does not mark revalidated requests as in-flight.\n * @returns A promise that resolves to the result of the revalidator function, or\n * `null` if no key or revalidator is found, or a `FetchResponse` if applicable.\n */\nexport async function revalidate(\n key: string | null,\n isStaleRevalidation: boolean = false,\n): Promise {\n // If no key is provided, no revalidation occurs\n if (!key) {\n return null;\n }\n\n const entry = revalidators.get(key);\n\n if (entry) {\n // Update only the lastUsed timestamp without resetting the whole array\n entry[1] = timeNow();\n\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n // If no revalidator function is registered, return null\n if (revalidator) {\n return await revalidator(isStaleRevalidation);\n }\n }\n\n // If no revalidator is registered for the key, return null\n return null;\n}\n\n/**\n * Removes all revalidators associated with the specified event type.\n *\n * @param type - The event type whose revalidators should be removed.\n */\nexport function removeRevalidators(type: EventType) {\n removeEventHandler(type);\n\n const flagIndex = type === 'focus' ? 5 : 6;\n\n // Clear all revalidators with this flag\n revalidators.forEach((entry, key) => {\n if (entry[flagIndex]) {\n removeRevalidator(key);\n }\n });\n}\n\n/**\n * Registers a generic revalidation event handler for the specified event type.\n * Supports browser window events and custom event providers (e.g. for React Native).\n * Ensures the handler is only added once.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'online').\n */\nfunction addEventHandler(event: EventType) {\n if (eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n // Priority 1: Custom event provider (works in any environment including React Native)\n const customProvider = customEventProviders.get(event);\n\n if (customProvider) {\n const cleanup = customProvider(handler);\n\n eventHandlers.set(event, cleanup);\n\n return;\n }\n\n // Priority 2: Browser window events\n if (isBrowser()) {\n window.addEventListener(event, handler);\n\n eventHandlers.set(event, () => window.removeEventListener(event, handler));\n }\n}\n\n/**\n * Removes the event handler for the specified event type.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n const cleanup = eventHandlers.get(event);\n\n if (cleanup) {\n cleanup();\n eventHandlers.delete(event);\n }\n}\n\n/**\n * Registers a revalidation functions for a specific cache key.\n *\n * @param {string} key Cache key to utilize\n * @param {RevalidatorFn} revalidatorFn Main revalidation function (marks in-flight requests)\n * @param {number} [ttl] Time to live in milliseconds (default: 3 minutes)\n * @param {number} [staleTime] Time (in seconds) after which the cache entry is considered stale\n * @param {RevalidatorFn} [bgRevalidatorFn] For stale revalidation (does not mark in-flight requests)\n * @param {boolean} [refetchOnFocus] Whether to revalidate on window focus\n * @param {boolean} [refetchOnReconnect] Whether to revalidate on network reconnect\n */\nexport function addRevalidator(\n key: string,\n revalidatorFn: RevalidatorFn, // Main revalidation function (marks in-flight requests)\n ttl?: number,\n staleTime?: number,\n bgRevalidatorFn?: RevalidatorFn, // For stale revalidation (does not mark in-flight requests)\n refetchOnFocus?: boolean,\n refetchOnReconnect?: boolean,\n) {\n const existing = revalidators.get(key);\n\n if (existing) {\n // Update in-place to avoid allocating a new tuple array\n existing[0] = revalidatorFn;\n existing[1] = timeNow();\n existing[2] = ttl ?? DEFAULT_TTL;\n existing[3] = staleTime;\n existing[4] = bgRevalidatorFn;\n existing[5] = refetchOnFocus;\n existing[6] = refetchOnReconnect;\n } else {\n revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\n ]);\n }\n\n if (refetchOnFocus) {\n addEventHandler('focus');\n }\n\n if (refetchOnReconnect) {\n addEventHandler('online');\n }\n\n if (staleTime) {\n addTimeout('s:' + key, revalidate.bind(null, key, true), staleTime * 1000);\n }\n}\n\nexport function removeRevalidator(key: string) {\n revalidators.delete(key);\n\n // Clean up stale timer\n removeTimeout('s:' + key);\n}\n\n/**\n * Periodically cleans up expired revalidators from the registry.\n * Removes any revalidator whose TTL has expired.\n *\n * @param {number} intervalMs How often to run cleanup (default: 3 minutes)\n * @returns {() => void} A function to stop the periodic cleanup\n */\nexport function startRevalidatorCleanup(\n intervalMs: number = DEFAULT_TTL,\n): () => void {\n const intervalId = setInterval(() => {\n const now = timeNow();\n\n revalidators.forEach(\n ([, lastUsed, ttl, , , refetchOnFocus, refetchOnReconnect], key) => {\n // Skip focus-only or reconnect-only revalidators to keep them alive\n if (refetchOnFocus || refetchOnReconnect) {\n return;\n }\n\n if (ttl > 0 && now - lastUsed > ttl) {\n removeRevalidator(key);\n }\n },\n );\n }, intervalMs);\n\n return () => clearInterval(intervalId);\n}\n","/**\n * Manages a set of listeners (subscribers) for arbitrary string keys, allowing cross-context or cross-component\n * cache updates and synchronization. Provides functions to add, remove, and notify listeners, as well as a\n * convenient subscribe/unsubscribe API.\n *\n * @template T - The type of the response object passed to listeners.\n *\n * @remarks\n * - Listeners are grouped by a string key, which typically represents a cache key or resource identifier.\n * - When `notifySubscribers` is called for a key, all listeners registered for that key are invoked with the provided response.\n * - The `subscribe` function returns an unsubscribe function for convenient cleanup.\n *\n * @example\n * ```ts\n * const unsubscribe = subscribe('user:123', (response) => {\n * // handle updated data\n * });\n * // Later, to stop listening:\n * unsubscribe();\n * ```\n */\n\nimport { noop } from './utils';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Listener = (response: T) => void;\n\nconst listeners = new Map>();\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n let set = listeners.get(key);\n\n if (!set) {\n listeners.set(key, (set = new Set()));\n }\n\n set.add(fn);\n}\n\nexport function removeListener(key: string, fn: Listener) {\n const set = listeners.get(key);\n\n if (set) {\n set.delete(fn);\n\n // If the set is empty, remove the key from the listeners map\n if (set.size === 0) {\n listeners.delete(key);\n }\n }\n}\n\nexport function notifySubscribers(key: string, response: T) {\n const fns = listeners.get(key);\n\n if (fns) {\n if (fns.size === 1) {\n // If there's only one listener, call it directly\n const fn = fns.values().next().value;\n fn!(response);\n } else {\n fns.forEach((fn) => fn(response));\n }\n }\n}\n\nexport function subscribe(key: string | null, fn: (response: T) => void) {\n if (!key) {\n // No op if no key is provided\n return noop;\n }\n\n addListener(key, fn);\n\n // Return an unsubscribe function\n return () => {\n removeListener(key, fn);\n };\n}\n","import { processHeaders } from './utils';\nimport {\n GET,\n APPLICATION_JSON,\n HEAD,\n STRING,\n CHARSET_UTF_8,\n CONTENT_TYPE,\n REJECT,\n UNDEFINED,\n APPLICATION_CONTENT_TYPE,\n} from './constants';\nimport type {\n HeadersObject,\n Method,\n RequestConfig,\n} from './types/request-handler';\nimport {\n replaceUrlPathParams,\n appendQueryParams,\n isSearchParams,\n isJSONSerializable,\n isSlowConnection,\n isAbsoluteUrl,\n sanitizeObject,\n isObject,\n} from './utils';\n\nconst defaultTimeoutMs = (isSlowConnection() ? 60 : 30) * 1000;\n\nexport const defaultConfig: RequestConfig = {\n strategy: REJECT,\n timeout: defaultTimeoutMs, // 30 seconds (60 on slow connections)\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n },\n retry: {\n delay: defaultTimeoutMs / 30, // 1 second (2 on slow connections)\n maxDelay: defaultTimeoutMs, // 30 seconds (60 on slow connections)\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 * Overwrites the default configuration with the provided custom configuration.\n *\n * @param {Partial} customConfig - The custom configuration to merge into the default config.\n * @returns {Partial} - The updated default configuration object.\n */\nexport function setDefaultConfig(\n customConfig: Partial,\n): Partial {\n const sanitized = sanitizeObject(customConfig);\n\n // Merge nested retry and headers settings into the current defaults instead of replacing them\n return mergeConfigs(\n { retry: defaultConfig.retry, headers: defaultConfig.headers },\n sanitized,\n defaultConfig,\n );\n}\n\n/**\n * Returns a shallow copy of the current default configuration.\n *\n * @returns {RequestConfig} - The current default configuration.\n */\nexport function getDefaultConfig(): RequestConfig {\n return { ...defaultConfig };\n}\n\n/**\n * Build request configuration from defaults and overrides.\n * This function merges the default configuration with the provided request configuration,\n * @param {string} url - Request url\n * @param {RequestConfig | null | undefined} reqConfig - Request configuration\n * @return {RequestConfig} - Merged request configuration\n */\nexport function buildConfig(\n url: string,\n reqConfig?: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null,\n): RequestConfig {\n // Merging gives the request its own copies of nested objects like headers, so that\n // mutations (e.g. by interceptors) never leak into the global defaults\n const merged = mergeConfigs(\n defaultConfig,\n reqConfig ? sanitizeObject(reqConfig) : {},\n );\n\n return buildFetcherConfig(url, merged);\n}\n\n/**\n * Builds the fetcher configuration by setting the method, body, headers, and URL.\n * It also handles query parameters and path parameters. This fn mutates the passed `requestConfig` object.\n * @param {string} url - The endpoint URL to which the request will be sent.\n * @param {RequestConfig} requestConfig - The request configuration object containing method, body, headers, and other options.\n * @return {RequestConfig} - The modified request configuration object with the URL, method, body, and headers set appropriately.\n **/\nexport function buildFetcherConfig(\n url: string,\n requestConfig: RequestConfig,\n): RequestConfig {\n let method = requestConfig.method as Method;\n method = method ? (method.toUpperCase() as Method) : GET;\n\n let body: RequestConfig['data'] | undefined;\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (method !== GET && method !== HEAD) {\n body = requestConfig.body ?? requestConfig.data;\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (body && typeof body !== STRING && isJSONSerializable(body)) {\n body = JSON.stringify(body);\n }\n }\n\n setContentTypeIfNeeded(requestConfig.headers, body);\n\n // Native fetch compatible settings\n const credentials = requestConfig.withCredentials\n ? 'include'\n : requestConfig.credentials;\n\n // The explicitly passed query params\n const dynamicUrl = replaceUrlPathParams(url, requestConfig.urlPathParams);\n const urlPath = appendQueryParams(dynamicUrl, requestConfig.params);\n const isFullUrl = isAbsoluteUrl(url);\n const baseURL = isFullUrl\n ? ''\n : requestConfig.baseURL || requestConfig.apiUrl || '';\n\n // Join as a path, as plain concatenation could extend the host of the baseURL,\n // e.g. \"https://api.example.com\" + \".evil.com\" would point to another host\n const separator =\n baseURL && urlPath && !baseURL.endsWith('/') && !/^[/?#]/.test(urlPath)\n ? '/'\n : '';\n\n requestConfig.url = baseURL + separator + urlPath;\n requestConfig.method = method;\n requestConfig.credentials = credentials;\n requestConfig.body = body;\n\n return requestConfig;\n}\n\n/**\n * Ensures the `Content-Type` header is set to `application/json; charset=utf-8`\n * if it is not already present and the request method and body meet specific conditions.\n *\n * @param headers - The headers object to modify. Can be an instance of `Headers`\n * or a plain object conforming to `HeadersInit`.\n * @param body - The optional body of the request. If no body is provided and the\n * method is 'GET' or 'HEAD', the function exits without modifying headers.\n */\nfunction setContentTypeIfNeeded(\n headers?: HeadersInit | HeadersObject,\n body?: unknown,\n): void {\n // If no headers are provided, or if the body is not set and the method is PUT or DELETE, do nothing\n if (!headers || !body) {\n return;\n }\n\n // Types that should not have Content-Type set (browser handles these)\n if (\n body instanceof FormData || // Browser automatically sets multipart/form-data with boundary\n (typeof Blob !== UNDEFINED && body instanceof Blob) || // Blob/File already have their own MIME types, don't override\n (typeof File !== UNDEFINED && body instanceof File) ||\n (typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream) // Stream type should be determined by the stream source\n ) {\n return;\n }\n\n let contentTypeValue: string;\n\n if (isSearchParams(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded';\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'octet-stream';\n } else if (isJSONSerializable(body)) {\n contentTypeValue = APPLICATION_JSON + ';' + CHARSET_UTF_8;\n } else {\n // Do not set Content-Type if content is not recognizable\n return;\n }\n\n if (headers instanceof Headers) {\n if (!headers.has(CONTENT_TYPE)) {\n headers.set(CONTENT_TYPE, contentTypeValue);\n }\n } else if (\n isObject(headers) &&\n !Array.isArray(headers) &&\n // Header names are case-insensitive, so check the normalized (lowercase) headers\n !processHeaders(headers as HeadersObject)[CONTENT_TYPE.toLowerCase()]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\n/**\n * Merges two request configurations, applying overrides from the second config to the first.\n * Handles special merging for nested properties like 'retry' and 'headers' (deep merge),\n * and concatenates interceptor arrays for 'onRequest', 'onResponse', and 'onError'.\n * If a target config is provided, it mutates that object; otherwise, creates a new one.\n *\n * @param {RequestConfig} baseConfig - The base configuration object to merge from.\n * @param {RequestConfig} overrideConfig - The override configuration object to apply on top of the base.\n * @param {RequestConfig} [targetConfig={}] - Optional target configuration object to merge into (mutated in place).\n * @returns {RequestConfig} The merged configuration object.\n *\n * @example\n * const base = { timeout: 5000, headers: { 'Accept': 'application/json' } };\n * const override = { timeout: 10000, headers: { 'Authorization': 'Bearer token' } };\n * const merged = mergeConfigs(base, override);\n * // Result: { timeout: 10000, headers: { Accept: 'application/json', Authorization: 'Bearer token' } }\n */\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig = {},\n): RequestConfig {\n Object.assign(targetConfig, baseConfig, overrideConfig);\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', baseConfig, overrideConfig, targetConfig);\n mergeConfig('headers', baseConfig, overrideConfig, targetConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', baseConfig, overrideConfig, targetConfig);\n mergeInterceptors('onResponse', baseConfig, overrideConfig, targetConfig);\n mergeInterceptors('onError', baseConfig, overrideConfig, targetConfig);\n\n return targetConfig;\n}\n\n/**\n * Efficiently merges interceptor functions from base and new configs\n */\nfunction mergeInterceptors<\n K extends 'onRequest' | 'onResponse' | 'onError' | 'onRetry',\n>(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const baseInterceptor = baseConfig[property];\n const newInterceptor = overrideConfig[property];\n\n if (!baseInterceptor && !newInterceptor) {\n return;\n }\n\n if (!baseInterceptor) {\n targetConfig[property] = newInterceptor;\n return;\n }\n\n if (!newInterceptor) {\n targetConfig[property] = baseInterceptor;\n return;\n }\n\n const baseArr = Array.isArray(baseInterceptor)\n ? baseInterceptor\n : [baseInterceptor];\n const newArr = Array.isArray(newInterceptor)\n ? newInterceptor\n : [newInterceptor];\n\n // This is the only LIFO interceptor, so we apply it after the response is prepared\n targetConfig[property] =\n property === 'onResponse' ? newArr.concat(baseArr) : baseArr.concat(newArr);\n}\n\n/**\n * Merges the specified property from the base configuration and the override configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and override configurations. Must be a key of RequestConfig.\n * @param {RequestConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestConfig} overrideConfig - The override configuration object that contains user-specific settings to merge.\n * @param {RequestConfig} targetConfig - The configuration object that will receive the merged properties.\n */\nexport function mergeConfig(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n if (override) {\n if (property === 'headers') {\n // Handle Headers instances which don't expose entries as own enumerable properties\n const isInstance =\n (base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers;\n const merged: HeadersObject = isInstance\n ? processHeaders(base)\n : { ...(base as HeadersObject) };\n const overrides: HeadersObject = isInstance\n ? processHeaders(override)\n : sanitizeObject(override as HeadersObject);\n\n // Header names are case-insensitive, so replace existing entries instead of duplicating them\n for (const key of Object.keys(overrides)) {\n const lowerKey = key.toLowerCase();\n\n for (const existingKey in merged) {\n if (existingKey.toLowerCase() === lowerKey) {\n delete merged[existingKey];\n }\n }\n\n merged[key] = overrides[key];\n }\n\n targetConfig[property] = merged as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...sanitizeObject(override as Record),\n } as RequestConfig[K];\n }\n } else if (\n override === undefined &&\n isObject(base) &&\n !((base as Headers | HeadersObject) instanceof Headers)\n ) {\n // Copy so that mutating the merged config never changes the base config\n targetConfig[property] = { ...base } as RequestConfig[K];\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport type {\n CacheKeyFunction,\n DefaultResponse,\n FetchResponse,\n MutationSettings,\n RequestConfig,\n} from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, STRING } from './constants';\nimport {\n isJSONSerializable,\n isObject,\n isSearchParams,\n sanitizeObject,\n sortObject,\n timeNow,\n} from './utils';\nimport { revalidate } from './revalidator-manager';\nimport { notifySubscribers } from './pubsub-manager';\nimport type { DefaultPayload, DefaultParams, DefaultUrlParams } from './types';\nimport { removeInFlight } from './inflight-manager';\nimport { addTimeout } from './timeout-wheel';\nimport { defaultConfig } from './config-handler';\nimport { processHeaders } from './utils';\n\nexport const IMMEDIATE_DISCARD_CACHE_TIME = 0; // Use it for cache entries that need to be persistent until unused by components or manually deleted\n\nconst _cache = new Map>();\nconst DELIMITER = '|';\nconst MIN_LENGTH_TO_HASH = 64;\nconst CACHE_KEY_SANITIZE_PATTERN = /[^\\w\\-_|/:@.?=&~%#]/g;\nconst CACHE_KEY_NEEDS_SANITIZE = /[^\\w\\-_|/:@.?=&~%#]/; // Non-global for fast test\n\n/**\n * Headers that may affect HTTP response content and should be included in cache key generation.\n * All header names must be lowercase to match normalized request headers.\n */\nconst CACHE_KEY_HEADER_WHITELIST = new Set([\n // Content negotiation\n 'accept', // Affects response format (e.g. JSON, HTML)\n 'accept-language', // Affects localization of the response\n 'accept-encoding', // Affects response compression (e.g. gzip, br)\n\n // Authentication\n 'authorization', // Affects access to protected resources\n\n // Request body metadata\n 'content-type', // Affects how the request body is interpreted\n\n // Optional headers\n 'referer', // May influence behavior in some APIs\n 'origin', // Relevant in CORS or tenant-specific APIs\n 'user-agent', // Included only for reason if server returns client-specific content\n\n // Cookies — only if server uses session-based responses\n 'cookie', // Can fragment cache heavily; use only if necessary\n\n // Custom headers that may affect response content\n 'x-api-key', // Token-based access, often affects authorization\n 'x-requested-with', // AJAX requests (used historically for distinguishing frontend calls)\n 'x-client-id', // Per-client/partner identity; often used in multi-tenant APIs\n 'x-tenant-id', // Multi-tenant segmentation; often changes response per tenant\n 'x-user-id', // Explicit user context (less common, but may exist)\n\n 'x-app-version', // Used for version-specific behavior (e.g. mobile apps)\n 'x-feature-flag', // Controls feature rollout behavior server-side\n 'x-device-id', // Used when response varies per device/app instance\n 'x-platform', // e.g. 'ios', 'android', 'web' — used in apps that serve different content\n\n 'x-session-id', // Only if backend uses it to affect the response directly (rare)\n 'x-locale', // Sometimes used in addition to or instead of `accept-language`\n]);\n\n/**\n * Generates a unique 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 {RequestConfig} config - 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 {RequestCredentials} [credentials=\"same-origin\"] - Whether to include credentials (include, same-origin, omit).\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @returns {string} - A unique cache key string based on the provided options.\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(\n config: RequestConfig,\n cacheKeyCheck = true,\n): string {\n // This is super fast. Effectively a no-op if cacheKey is\n // a string or a function that returns a string.\n const key = config.cacheKey;\n\n if (key && cacheKeyCheck) {\n return typeof key === STRING\n ? (key as string)\n : (key as CacheKeyFunction)(config);\n }\n\n const {\n url = '',\n method = GET,\n headers = null,\n body = null,\n credentials = 'same-origin',\n } = config;\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 let headersString = '';\n if (headers) {\n let obj: Record;\n\n if (headers instanceof Headers) {\n obj = processHeaders(headers);\n } else {\n obj = headers as Record;\n }\n\n // Filter headers to only include those that affect request identity\n // Include only headers that affect request identity, not execution behavior\n const keys = Object.keys(obj);\n const len = keys.length;\n\n // Sort keys manually for fastest deterministic output\n if (len > 1) {\n keys.sort();\n }\n\n let str = '';\n for (let i = 0; i < len; ++i) {\n if (CACHE_KEY_HEADER_WHITELIST.has(keys[i].toLowerCase())) {\n str += keys[i] + ':' + obj[keys[i]] + ';';\n }\n }\n\n headersString = hash(str);\n }\n\n // For GET requests, return early with shorter cache key\n if (method === GET) {\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString;\n\n return sanitizeCacheKey(cacheStr);\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING || isSearchParams(body)) {\n const str = String(body);\n\n bodyString = str.length < MIN_LENGTH_TO_HASH ? str : hash(str); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Files can't be read synchronously, so they are identified by their object\n bodyString +=\n key +\n '=' +\n (typeof value === STRING ? value : 'F' + getObjectId(value as File)) +\n '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (isObject(body) && !isJSONSerializable(body)) {\n // Blobs, buffers, streams etc. can't be read synchronously, so they are identified by their object.\n // Two different bodies never share a key, while the same body object is still deduplicated.\n bodyString = 'B' + getObjectId(body);\n } else {\n const o = isObject(body)\n ? JSON.stringify(sortObject(body))\n : String(body);\n\n bodyString = o.length > MIN_LENGTH_TO_HASH ? hash(o) : o;\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString +\n DELIMITER +\n bodyString;\n\n return sanitizeCacheKey(cacheStr);\n}\n\nconst objectIds = new WeakMap();\nlet lastObjectId = 0;\n\n/**\n * Returns a unique id for an object, e.g. a request body that can't be serialized.\n *\n * @param {object} obj - The object to identify.\n * @returns {number} - The id of the object.\n */\nfunction getObjectId(obj: object): number {\n let id = objectIds.get(obj);\n\n if (!id) {\n objectIds.set(obj, (id = ++lastObjectId));\n }\n\n return id;\n}\n\n/**\n * Prevents cache poisoning by removal of control chars and unusual characters.\n * When anything is removed, a hash of the original key is appended so that keys\n * differing only in the removed characters (e.g. `?a[]=1` and `?a=1`) don't collide.\n *\n * @param {string} cacheStr - The raw cache key.\n * @returns {string} - The sanitized cache key.\n */\nfunction sanitizeCacheKey(cacheStr: string): string {\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '') +\n DELIMITER +\n hash(cacheStr)\n : cacheStr;\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the expiry time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(entry: CacheEntry): boolean {\n // No expiry time means the entry never expires\n if (!entry.expiry) {\n return false;\n }\n\n return timeNow() > entry.expiry;\n}\n\n/**\n * Retrieves a cached response from the internal cache using the provided key.\n *\n * @param key - The unique key identifying the cached entry. If null, returns null.\n * @returns The cached {@link FetchResponse} if found, otherwise null.\n */\nexport function getCacheData<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n key: string | null,\n): FetchResponse | null {\n if (!key) {\n return null;\n }\n\n const entry = _cache.get(key);\n\n return entry ? entry.data : null;\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 * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string | null,\n):\n | CacheEntry<\n FetchResponse\n >\n | null\n | undefined {\n return _cache.get(key as string);\n}\n\n/**\n * Sets a new cache entry or updates an existing one, with optional TTL (time-to-live).\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {number} [ttl] - Optional TTL in seconds. If not provided, the cache entry will not expire.\n * @param {number} [staleTime] - Optional stale time in seconds. If provided, the cache entry will be considered stale after this time.\n */\nexport function setCache(\n key: string,\n data: T,\n ttl?: number,\n staleTime?: number,\n): void {\n if (ttl === 0) {\n deleteCache(key);\n return;\n }\n\n const time = timeNow();\n const ttlMs = ttl ? ttl * 1000 : 0;\n const staleTimeMs = staleTime ? staleTime * 1000 : 0; // Ensure default value for staleTime\n\n _cache.set(key, {\n data,\n time,\n stale: staleTimeMs > 0 ? time + staleTimeMs : undefined, // Use undefined if staleTime is not set\n expiry: ttl === -1 ? undefined : time + ttlMs,\n });\n\n if (ttlMs > 0) {\n addTimeout(\n 'c:' + key,\n () => {\n deleteCache(key, true);\n },\n ttlMs,\n );\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n * @param {boolean} [removeExpired=false] - If true, only deletes the cache entry if it is expired or stale.\n */\nexport function deleteCache(key: string, removeExpired: boolean = false): void {\n if (removeExpired) {\n const entry = getCache(key);\n\n // If the entry does not exist, or it is neither expired nor stale, do not delete\n if (!entry || !isCacheExpired(entry)) {\n return;\n }\n }\n\n _cache.delete(key);\n}\n\n/**\n * Prunes the cache by removing entries that have expired based on the provided cache time.\n */\nexport function pruneCache(): void {\n _cache.clear();\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string | null} key Cache key to utilize. If null, no mutation occurs.\n * @param {ResponseData} newData - The new data to be cached.\n * @param {MutationSettings|undefined} settings - Mutation settings.\n */\nexport async function mutate<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n key: string | null,\n newData: ResponseData,\n settings?: MutationSettings,\n): Promise | null> {\n // If no key is provided, do nothing\n if (!key) {\n return null;\n }\n\n const entry = getCache(\n key,\n );\n\n if (!entry) {\n return null;\n }\n\n const updatedData = isObject(newData) ? sanitizeObject(newData) : newData;\n\n const updatedResponse = {\n ...entry.data,\n data: updatedData,\n };\n\n const updatedEntry = {\n ...entry,\n data: updatedResponse,\n };\n\n _cache.set(key, updatedEntry);\n notifySubscribers(key, updatedResponse);\n\n if (settings && settings.refetch) {\n return await revalidate(key);\n }\n\n return null;\n}\n\n/**\n * Retrieves a cached response if available and valid, otherwise returns null.\n *\n * @template ResponseData - The type of the response data.\n * @template RequestBody - The type of the request body.\n * @template QueryParams - The type of the query parameters.\n * @template PathParams - The type of the path parameters.\n * @param {string | null} cacheKey - The cache key to look up.\n * @param {number | undefined} cacheTime - The maximum time to cache entry.\n * @param {RequestConfig} requestConfig - The fetcher configuration.\n * @returns {FetchResponse | null} - The cached response or null.\n */\nexport function getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n cacheKey: string | null,\n cacheTime: number | undefined,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): FetchResponse | null {\n // If cache key or time is not provided, return null\n if (!cacheKey || cacheTime === undefined || cacheTime === null) {\n return null;\n }\n\n // Check if cache should be bypassed\n const buster = requestConfig.cacheBuster || defaultConfig.cacheBuster;\n if (buster && buster(requestConfig)) {\n return null;\n }\n\n if (requestConfig.cache && requestConfig.cache === 'reload') {\n return null; // Skip cache lookup entirely\n }\n\n // Retrieve the cached entry\n const entry = getCache(\n cacheKey,\n );\n\n if (!entry) {\n return null;\n }\n\n const isExpired = isCacheExpired(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n const data = entry.data;\n\n // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n // The placeholder stored while a request is in flight is not a response, so treat it as a miss\n return data && data.isFetching ? null : data;\n}\n\n/**\n * Sets or deletes the response cache based on cache settings and notifies subscribers.\n *\n * @param {FetchResponse} output - The response to cache.\n * @param {RequestConfig} requestConfig - The request configuration.\n * @param {boolean} [isError=false] - Whether the response is an error.\n */\nexport function handleResponseCache<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n output: FetchResponse,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n isError: boolean = false,\n): void {\n // It is string as it is called once request is made\n const cacheKey = requestConfig.cacheKey as string;\n\n if (cacheKey) {\n const cacheTime = requestConfig.cacheTime;\n const skipCache = requestConfig.skipCache;\n\n // Fast path: only set cache if cacheTime is positive and not skipping cache\n if (\n cacheTime &&\n (!isError || requestConfig.cacheErrors) &&\n !(skipCache && skipCache(output, requestConfig))\n ) {\n setCache(cacheKey, output, cacheTime, requestConfig.staleTime);\n } else {\n const entry = getCache(cacheKey);\n\n // Don't let the in-flight placeholder outlive a request whose result isn't cached\n if (entry && entry.data && entry.data.isFetching) {\n deleteCache(cacheKey);\n }\n }\n\n notifySubscribers(cacheKey, output);\n removeInFlight(cacheKey);\n\n const prevCacheKey = requestConfig._prevKey;\n\n if (prevCacheKey) {\n removeInFlight(prevCacheKey);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { mutate } from './cache-manager';\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n FUNCTION,\n OBJECT,\n STRING,\n} from './constants';\nimport {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n ResponseError,\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n} from './types';\nimport { flattenData, isObject, processHeaders } from './utils';\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 ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse,\n): Promise {\n // Bail early if response is null or undefined\n if (!response) {\n return null;\n }\n\n // Get the content-type header once\n let contentType = (response as Response).headers?.get(CONTENT_TYPE);\n\n if (contentType) {\n // Lowercase and trim for consistent matching\n contentType = contentType.toLowerCase().trim();\n } else {\n contentType = '';\n }\n\n // Split for mime type without charset\n const mimeType = contentType.split(';', 1)[0];\n\n let data;\n\n try {\n if (mimeType.includes(APPLICATION_JSON) || mimeType.includes('+json')) {\n data = await response.json(); // Parse JSON response\n } else if (\n (mimeType.includes('multipart/form-data') || // Parse as FormData\n mimeType.includes(\n APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded', // Handle URL-encoded forms\n )) &&\n typeof response.formData === FUNCTION\n ) {\n data = await response.formData();\n } else if (/^(image|video|audio)\\/|octet-stream|pdf|zip/.test(mimeType)) {\n data = await response.arrayBuffer(); // Parse as ArrayBuffer for binary types\n } else {\n data = await response.text();\n\n if (typeof data === STRING) {\n const trimmed = data.trim();\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n data = JSON.parse(trimmed);\n } catch {\n // leave as text if parsing fails\n }\n }\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\n/**\n * Prepare response object with additional information.\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} config - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\nexport const prepareResponse = <\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n config: RequestConfig,\n error: ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null,\n): FetchResponse => {\n const defaultResponse = config.defaultResponse;\n const cacheKey = config.cacheKey;\n const mutatator = mutate.bind(null, cacheKey as string) as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >['mutate'];\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 ?? null,\n headers: null,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: false,\n isError: true,\n } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n const isNativeResponse =\n typeof Response === FUNCTION && response instanceof Response;\n\n let data = response.data;\n\n // Set the default response if the provided data is an empty object\n if (\n defaultResponse !== undefined &&\n (data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0))\n ) {\n response.data = data = defaultResponse;\n }\n\n if (config.flattenResponse) {\n response.data = data = flattenData(data);\n }\n\n if (config.select) {\n response.data = data = config.select(data);\n }\n\n const headers = processHeaders(response.headers);\n\n // Native fetch Response extended by extra information\n if (isNativeResponse) {\n const output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > = {\n body: response.body,\n bodyUsed: response.bodyUsed,\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 // Convert methods to use arrow functions to preserve correct return types\n blob: () =>\n Promise.resolve(\n data instanceof ArrayBuffer ? new Blob([data]) : new Blob(),\n ), // Lazily construct Blob from ArrayBuffer\n json: () => Promise.resolve(data as ResponseData), // Return the already parsed JSON data\n text: () => Promise.resolve(data as string), // Return the already parsed text data\n // The body was already read, so a copy of this response is returned instead of Response.clone()\n clone: () => ({ ...output }),\n arrayBuffer: () =>\n Promise.resolve(\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0),\n ), // Return the ArrayBuffer directly\n formData: () =>\n Promise.resolve(data instanceof FormData ? data : new FormData()), // Return the already parsed FormData\n bytes: () =>\n Promise.resolve(\n new Uint8Array(\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0),\n ),\n ),\n // Enhance the response with extra information\n error,\n data,\n headers,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: response.ok && !error,\n isError: !!error,\n };\n\n return output;\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 (isObject(response)) {\n response.error = error;\n response.headers = headers;\n response.isFetching = false;\n response.mutate = mutatator;\n response.isSuccess = response.ok && !error;\n response.isError = !!error;\n }\n\n return response;\n};\n","import { applyInterceptors } from './interceptor-manager';\nimport type { FetchResponse, RetryConfig, RetryFunction } from './types';\nimport { delayInvocation, timeNow } from './utils';\nimport { generateCacheKey } from './cache-manager';\n\nfunction getMsFromHttpDate(dateString: string): number | null {\n const ms = Date.parse(dateString) - timeNow();\n\n if (!isNaN(ms)) {\n return Math.max(0, Math.floor(ms));\n }\n return null;\n}\n\n/**\n * Calculates the number of milliseconds to wait before retrying a request,\n * based on the `Retry-After` HTTP header in the provided response.\n *\n * The function supports both numeric (seconds) and HTTP-date formats for the `Retry-After` header.\n * - If the header is a number, it is interpreted as seconds and converted to milliseconds.\n * - If the header is a date, the function calculates the difference between the date and the current time.\n *\n * @param extendedResponse - The response object containing headers, or `null`.\n * @returns The number of milliseconds to wait before retrying, or `null` if the header is not present or invalid.\n */\nexport function getRetryAfterMs(\n extendedResponse: FetchResponse | null,\n): number | null {\n if (!extendedResponse) {\n return null;\n }\n\n const headers = extendedResponse.headers || {};\n const retryAfter = headers['retry-after'];\n\n if (retryAfter) {\n // Try parsing as seconds\n const seconds = Number(retryAfter);\n\n if (!isNaN(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n const ms = getMsFromHttpDate(retryAfter);\n\n if (ms !== null) {\n return ms;\n }\n }\n\n // Headers are already in lowercase\n const RATELIMIT_RESET = 'ratelimit-reset';\n\n // Unix timestamp when the rate limit window resets (relative to current time)\n // Fallback to checking 'ratelimit-reset-after' OR 'x-ratelimit-reset-after' headers\n const rateLimitResetAfter =\n headers[RATELIMIT_RESET + '-after'] ||\n headers['x-' + RATELIMIT_RESET + '-after'];\n\n if (rateLimitResetAfter) {\n const seconds = Number(rateLimitResetAfter);\n\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n }\n\n // ISO 8601 datetime when the rate limit resets\n // Fallback to checking 'ratelimit-reset-at' 'x-ratelimit-reset-at' headers\n const rateLimitResetAt =\n headers[RATELIMIT_RESET + '-at'] || headers['x-' + RATELIMIT_RESET + '-at'];\n\n if (rateLimitResetAt) {\n return getMsFromHttpDate(rateLimitResetAt);\n }\n\n return null;\n}\n\n/**\n * Executes a request function with retry logic according to the provided configuration.\n *\n * The function attempts the request up to the specified number of retries, applying delay and backoff strategies.\n * Retries can be triggered based on response status codes, custom logic, or the presence of a `Retry-After` header.\n * Optionally, an `onRetry` interceptor can be invoked before each retry attempt.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param requestFn - The function that performs the request. Receives `isStaleRevalidation` and `attempt` as arguments.\n * @param config - The retry configuration, including retry count, delay, backoff, retry conditions, and hooks.\n * @returns A promise resolving to the fetch response, or rejecting if all retries are exhausted.\n * @throws Error if the maximum number of retries is exceeded or a non-retriable error occurs.\n */\nexport async function withRetry<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation: boolean,\n attempt: number,\n ) => Promise<\n FetchResponse\n >,\n config: RetryConfig,\n): Promise> {\n const {\n retries = 0,\n delay = 0,\n backoff = 1,\n maxDelay,\n retryOn = [],\n shouldRetry,\n } = config;\n\n let attempt = 0;\n let waitTime = delay;\n const maxRetries = retries > 0 ? retries : 0;\n let output: FetchResponse;\n\n while (attempt <= maxRetries) {\n // Subsequent attempts will have output defined, but the first attempt may not.\n // Let's apply onRetry interceptor and regenerate cache key if ot really changes.\n if (attempt > 0 && output!) {\n const cfg = output.config;\n const onRetry = cfg.onRetry;\n\n if (onRetry) {\n await applyInterceptors(onRetry, output, attempt);\n\n // If the key was automatically generated, we need to regenerate it as config may change.\n // We don't detect whether config changed for performance reasons.\n if (cfg._isAutoKey) {\n cfg._prevKey = cfg.cacheKey as string;\n cfg.cacheKey = generateCacheKey(cfg, false);\n }\n }\n }\n\n // Performance optimization: Call the request function with the current attempt number\n // If this is the first attempt, we pass `isStaleRevalidation` as `false`,\n // otherwise we pass `true` to indicate that this is a stale revalidation (no cache hit).\n output = await requestFn(attempt > 0, attempt);\n const error = output.error;\n\n // Check if we should retry based on successful response\n if (!error) {\n if (shouldRetry && attempt < maxRetries) {\n const shouldRetryResult = await shouldRetry(output, attempt);\n\n if (shouldRetryResult) {\n await delayInvocation(waitTime);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n continue;\n }\n }\n\n break;\n }\n\n // Determine if we should stop retrying\n const shouldStopRetrying = await getShouldStopRetrying(\n output,\n attempt,\n maxRetries,\n shouldRetry,\n retryOn,\n );\n\n if (shouldStopRetrying) {\n break;\n }\n\n // If we should not stop retrying, continue to the next attempt\n // Handle rate limiting if the error status is 429 (Too Many Requests) or 503 (Service Unavailable)\n if (error.status === 429 || error.status === 503) {\n // Try to extract the \"Retry-After\" value from the response headers\n const retryAfterMs = getRetryAfterMs(output);\n\n // If a valid retry-after value is found, override the wait time before next retry\n // Cap it with maxDelay so that a server can't make the client wait indefinitely\n if (retryAfterMs !== null) {\n waitTime = Math.min(retryAfterMs, maxDelay || retryAfterMs);\n }\n }\n\n await delayInvocation(waitTime);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n }\n\n return output!;\n}\n\n/**\n * Determines whether to stop retrying based on the error, current attempt count, and retry configuration.\n *\n * This function checks:\n * - If the maximum number of retries has been reached.\n * - If a custom `shouldRetry` callback is provided, its result is used to decide.\n * - If no custom logic is provided, falls back to checking if the error status is included in the `retryOn` list.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param output - The response object containing the error and request configuration.\n * @param attempt - The current retry attempt number.\n * @param maxRetries - The maximum number of retry attempts allowed.\n * @param shouldRetry - Optional custom function to determine if a retry should occur.\n * @param retryOn - Optional list of HTTP status codes that should trigger a retry.\n * @returns A promise resolving to `true` if retrying should stop, or `false` to continue retrying.\n */\nexport async function getShouldStopRetrying<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n output: FetchResponse,\n attempt: number,\n maxRetries: number,\n shouldRetry?: RetryFunction<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n retryOn: number[] = [],\n): Promise {\n // Safety first: always respect max retries\n // We check retries provided regardless of the shouldRetry being provided so to avoid infinite loops.\n // It is a fail-safe so to prevent excessive retry attempts even if custom retry logic suggests a retry.\n if (attempt === maxRetries) {\n return true;\n }\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n\n if (result !== null) {\n return !result;\n }\n }\n\n return !(retryOn || []).includes(output.error?.status ?? 0);\n}\n","import type { RequestConfig, FetchResponse } from './types';\nimport { delayInvocation } from './utils';\n\n/**\n * Executes a request function with polling, stopping when shouldStopPolling returns true,\n * pollingInterval is not set, or maxAttempts is reached.\n *\n * @template Output The type of the output returned by the request function.\n * @param requestFn - The function that performs a single request (with retries).\n * @param pollingInterval - Interval in ms between polling attempts.\n * @param shouldStopPolling - Function to determine if polling should stop.\n * @param maxAttempts - Maximum number of polling attempts, default: 0 (unlimited).\n * @param pollingDelay - Delay in ms before each polling attempt, default: 0.\n * @returns The final output from the last request.\n */\nexport async function withPolling<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation?: boolean,\n attempt?: number,\n ) => Promise<\n FetchResponse\n >,\n pollingInterval?: RequestConfig['pollingInterval'],\n shouldStopPolling?: RequestConfig['shouldStopPolling'],\n maxAttempts = 0,\n pollingDelay = 0,\n): Promise> {\n if (!pollingInterval) {\n return requestFn();\n }\n\n let pollingAttempt = 0;\n let output: FetchResponse;\n\n while (maxAttempts === 0 || pollingAttempt < maxAttempts) {\n if (pollingDelay > 0) {\n await delayInvocation(pollingDelay);\n }\n\n output = await requestFn();\n\n pollingAttempt++;\n\n if (\n (maxAttempts > 0 && pollingAttempt >= maxAttempts) ||\n !pollingInterval ||\n (shouldStopPolling && shouldStopPolling(output, pollingAttempt))\n ) {\n break;\n }\n\n await delayInvocation(pollingInterval);\n }\n\n return output!;\n}\n","import type { ResponseError } from './errors/response-error';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n} from './types/request-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { handleResponseCache } from './cache-manager';\nimport { ABORT_ERROR, REJECT } from './constants';\nimport {\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n HeadersObject,\n} from './types';\nimport { processHeaders } from './utils';\n\n/**\n * Handles final processing for both success and error responses\n * Applies error interceptors, caching, notifications, and error strategy\n */\nexport async function withErrorHandling<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n isStaleRevalidation: boolean,\n requestFn: (\n isStaleRevalidation: boolean,\n ) => Promise<\n FetchResponse\n >,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): Promise> {\n const output = await requestFn(isStaleRevalidation);\n const error = output.error;\n\n if (!error) {\n // SUCCESS PATH\n handleResponseCache(output, requestConfig);\n\n return output;\n }\n\n // ERROR PATH\n\n if (requestConfig.onError) {\n await applyInterceptors(requestConfig.onError, error);\n }\n\n // Timeouts and request cancellations using AbortController do not throw any errors unless rejectCancelled is true.\n // Only handle the error if the request was not cancelled, or if it was cancelled and rejectCancelled is true.\n const isCancelled = error.isCancelled;\n\n if (!isCancelled && requestConfig.logger?.warn) {\n requestConfig.logger.warn(\n 'FETCH ERROR',\n redactError(error as ResponseError),\n );\n }\n\n // The defaultResponse strategy returns the default response in place of the error data.\n // The original data stays available through error.response.\n if (requestConfig.strategy === 'defaultResponse') {\n output.data = (requestConfig.defaultResponse ?? null) as typeof output.data;\n }\n\n // Handle cache and notifications FIRST (before strategy)\n handleResponseCache(output, requestConfig, true);\n\n // handle error strategy as the last part\n const shouldHandleError = !isCancelled || requestConfig.rejectCancelled;\n\n if (shouldHandleError) {\n const strategy = requestConfig.strategy;\n // Reject the promise\n if (strategy === REJECT) {\n return Promise.reject(error);\n }\n\n // Hang the promise\n if (strategy === 'silent') {\n await new Promise(() => null);\n }\n }\n\n return output;\n}\n\n// Credential headers that must not end up in logs\nconst SENSITIVE_HEADERS = [\n 'authorization',\n 'proxy-authorization',\n 'cookie',\n 'x-api-key',\n];\n\n/**\n * Creates a copy of the error for logging, with credential headers masked and the request body removed.\n * The error itself is left untouched.\n */\nfunction redactError(error: ResponseError): ResponseError {\n // Cache keys are dropped too, as they can contain short request bodies\n const config = {\n ...error.config,\n body: undefined,\n data: undefined,\n cacheKey: undefined,\n _prevKey: undefined,\n headers: processHeaders(error.config.headers as HeadersObject),\n };\n\n for (const name of SENSITIVE_HEADERS) {\n if (config.headers[name]) {\n config.headers[name] = '[REDACTED]';\n }\n }\n\n const copy = Object.assign(new Error(error.message), error, {\n config,\n request: config,\n response: error.response && { ...error.response, config },\n });\n\n copy.name = error.name;\n copy.stack = error.stack;\n\n return copy;\n}\n\nexport function enhanceError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): void {\n error.status = error.status || response?.status || 0;\n error.statusText = error.statusText || response?.statusText || '';\n error.config = error.request = requestConfig;\n error.response = response;\n error.isCancelled = error.name === ABORT_ERROR;\n}\n","import type {\n DefaultResponse,\n RequestConfig,\n FetchResponse,\n} from './types/request-handler';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n} from './types/api-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { ResponseError } from './errors/response-error';\nimport { isObject } from './utils';\nimport {\n markInFlight,\n setInFlightPromise,\n getInFlightPromise,\n} from './inflight-manager';\nimport { parseResponseData, prepareResponse } from './response-parser';\nimport { generateCacheKey, getCachedResponse, setCache } from './cache-manager';\nimport { withRetry } from './retry-handler';\nimport { withPolling } from './polling-handler';\nimport { notifySubscribers } from './pubsub-manager';\nimport { addRevalidator } from './revalidator-manager';\nimport { enhanceError, withErrorHandling } from './error-handler';\nimport { FUNCTION } from './constants';\nimport { buildConfig } from './config-handler';\n\nconst inFlightResponse = Object.freeze({\n isFetching: true,\n});\n\n/**\n * Sends an HTTP request to the specified URL using the provided configuration and returns a typed response.\n *\n * @typeParam ResponseData - The expected shape of the response data. Defaults to `DefaultResponse`.\n * @typeParam RequestBody - The type of the request payload/body. Defaults to `DefaultPayload`.\n * @typeParam QueryParams - The type of the query parameters. Defaults to `DefaultParams`.\n * @typeParam PathParams - The type of the path parameters. Defaults to `DefaultUrlParams`.\n *\n * @param url - The endpoint URL to which the request will be sent.\n * @param config - Optional configuration object for the request, including headers, method, body, query, and path parameters.\n *\n * @returns A promise that resolves to a `FetchResponse` containing the typed response data and request metadata.\n *\n * @example\n * ```typescript\n * const { data } = await fetchf('/api/user', { method: 'GET' });\n * console.log(data);\n * ```\n */\nexport async function fetchf<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n): Promise> {\n // Ultra-fast early cache check if cacheKey is provided as a string\n // For workloads dominated by repeated requests, this string caching optimization\n // can potentially support millions of requests per second with minimal CPU overhead\n if (reqConfig && typeof reqConfig.cacheKey === 'string') {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(reqConfig.cacheKey, reqConfig.cacheTime, reqConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n const fetcherConfig = buildConfig<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(url, reqConfig);\n\n const {\n timeout,\n cancellable,\n cacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n refetchOnFocus,\n refetchOnReconnect,\n pollingInterval = 0,\n } = fetcherConfig;\n const isCacheEnabled = cacheTime !== undefined || staleTime !== undefined;\n\n const needsCacheKey = !!(\n cacheKey ||\n timeout ||\n dedupeTime ||\n isCacheEnabled ||\n cancellable ||\n refetchOnFocus ||\n refetchOnReconnect\n );\n\n let _cacheKey: string | null = null;\n\n // Generate cache key if required\n if (needsCacheKey) {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n // Cache handling logic\n if (_cacheKey && isCacheEnabled) {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(_cacheKey, cacheTime, fetcherConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n // Deduplication logic\n if (_cacheKey && dedupeTime) {\n const inflight = getInFlightPromise<\n FetchResponse\n >(_cacheKey, dedupeTime);\n\n if (inflight) {\n return inflight;\n }\n }\n\n const retryConfig = fetcherConfig.retry || {};\n const { retries = 0, resetTimeout } = retryConfig;\n\n // The actual request logic as a function (one poll attempt, with retries)\n const doRequestOnce = async (isStaleRevalidation: boolean, attempt = 0) => {\n // If cache key is specified, we will handle optimistic updates\n // and mark the request as in-flight, so to catch \"fetching\" state.\n // This is useful for Optimistic UI updates (e.g., showing loading spinners).\n if (!attempt) {\n if (_cacheKey && !isStaleRevalidation) {\n if (staleTime) {\n const existingCache = getCachedResponse(\n _cacheKey,\n cacheTime,\n fetcherConfig,\n );\n\n // Don't notify subscribers when cache exists\n // Let them continue showing stale data during background revalidation\n if (!existingCache) {\n setCache(_cacheKey, inFlightResponse, cacheTime, staleTime);\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n } else {\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n }\n\n // Attach cache key so that it can be reused in interceptors or in the final response\n fetcherConfig.cacheKey = _cacheKey;\n }\n\n const url = fetcherConfig.url as string;\n\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = markInFlight(\n _cacheKey,\n url,\n timeout,\n dedupeTime || 0,\n !!cancellable,\n // Enable timeout either by default or when retries & resetTimeout are enabled\n !!(timeout && (!attempt || resetTimeout)),\n );\n\n // Do not create a shallow copy to maintain idempotency here.\n // This ensures the original object is mutated by interceptors whenever needed, including retry logic.\n const requestConfig = fetcherConfig;\n\n requestConfig.signal = controller.signal;\n\n let output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n let response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n try {\n if (fetcherConfig.onRequest) {\n // Zero-allocation yield to microtask queue so the outer fetchf() can call setInFlightPromise()\n // before onRequest interceptors run. This ensures that if onRequest triggers\n // another fetchf() with the same cacheKey, getInFlightPromise() finds item[4].\n // On retries (attempt > 0), setInFlightPromise() was already called during the first attempt.\n // The promise stored in item[4] is the outer doRequestPromise which covers all retries.\n // So the race only matters on the very first attempt when the outer scope hasn't had a chance to call setInFlightPromise() yet.\n if (_cacheKey && dedupeTime && !attempt) {\n await null;\n }\n\n await applyInterceptors(fetcherConfig.onRequest, requestConfig);\n }\n\n // Custom fetcher\n const fn = fetcherConfig.fetcher;\n\n response = (fn\n ? await fn(\n url,\n requestConfig,\n )\n : await fetch(\n url,\n requestConfig as RequestInit,\n )) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Custom fetcher may return a raw data object instead of a Response instance\n if (isObject(response)) {\n // Case 1: Native Response instance\n if (typeof Response === FUNCTION && response instanceof Response) {\n response.data = requestConfig.parser\n ? await requestConfig.parser(response)\n : await parseResponseData(response);\n } else if (fn) {\n // Case 2: Custom fetcher that returns a response object\n if (!('data' in response && 'body' in response)) {\n // Case 3: Raw data, wrap it\n response = { data: response } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n }\n\n // Attach config and data to the response\n // This is useful for custom fetchers that do not return a Response instance\n // and for interceptors that may need to access the request config\n response.config = requestConfig;\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n // This is the pattern for fetch responses as per spec, but custom fetchers may not follow it so we check for `ok` property\n if (response.ok !== undefined && !response.ok) {\n throw new ResponseError(\n requestConfig.method +\n ' to ' +\n url +\n ' failed! Status: ' +\n (response.status || null),\n requestConfig,\n response,\n );\n }\n }\n\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig);\n\n const onResponse = fetcherConfig.onResponse;\n\n if (onResponse) {\n await applyInterceptors(onResponse, output);\n }\n } catch (_error) {\n const error = _error as ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Append additional information to Network, CORS or any other fetch() errors\n enhanceError(\n error,\n response,\n requestConfig,\n );\n\n // Prepare Extended Response\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig, error);\n }\n\n return output;\n };\n\n // Inline and minimize function wrappers for performance\n // When retries are enabled, forward isStaleRevalidation so the first attempt\n // of a background SWR revalidation doesn't incorrectly mark the request as in-flight\n const baseRequest =\n retries > 0\n ? (isStaleRevalidation: boolean) =>\n withRetry(\n (_, attempt) => doRequestOnce(isStaleRevalidation, attempt),\n retryConfig,\n )\n : doRequestOnce;\n\n const requestWithErrorHandling = (isStaleRevalidation = false) =>\n withErrorHandling(\n isStaleRevalidation,\n baseRequest,\n fetcherConfig,\n );\n\n // Avoid unnecessary function wrapping if polling is not enabled\n const doRequestPromise = pollingInterval\n ? withPolling(\n requestWithErrorHandling,\n pollingInterval,\n fetcherConfig.shouldStopPolling,\n fetcherConfig.maxPollingAttempts,\n fetcherConfig.pollingDelay,\n )\n : requestWithErrorHandling();\n\n // If deduplication is enabled, store the in-flight promise immediately\n if (_cacheKey) {\n if (dedupeTime) {\n setInFlightPromise(_cacheKey, doRequestPromise);\n }\n\n // Only register revalidator when revalidation features are actually requested\n if (staleTime || refetchOnFocus || refetchOnReconnect) {\n addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\n );\n }\n }\n\n return doRequestPromise;\n}\n","import type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n RequestConfigUrlRequired,\n} from './types/api-handler';\nimport { fetchf } from '.';\nimport { mergeConfigs } from './config-handler';\nimport { hasOwn } from './utils';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if passed as \"fetcher\".\n * @see https://github.com/MattCCC/fetchff#configuration\n *\n * @param {Object} config - Configuration object for the API fetcher (see link above for full options).\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {string} [config.baseURL] - The base URL for the API.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\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 EndpointTypes extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\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 const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\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 endpointName - The name of the API endpoint to call.\n * @param requestConfig - Additional configuration for the request.\n * @returns A promise that resolves with the response from the API provider.\n */\n async request(endpointName, requestConfig = {}) {\n // Use global and per-endpoint settings\n // Only own properties are endpoints, not ones inherited like \"constructor\"\n const endpointConfig = hasOwn(endpoints, endpointName as string)\n ? endpoints[endpointName]\n : undefined;\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // URL parsers ignore leading control characters and spaces, drop tabs and newlines,\n // and treat backslashes like slashes, so check the URL the way it will be resolved\n const resolvedUrl = url\n .replace(/[\\t\\n\\r]/g, '')\n // eslint-disable-next-line no-control-regex -- matching control characters is the point\n .replace(/^[\\x00-\\x20]+/, '');\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (/^[/\\\\]{2}/.test(resolvedUrl)) {\n throw new Error('Protocol-relative URLs not allowed.');\n }\n\n // Prevent potential Server-Side Request Forgery attack and leakage of credentials when same instance is used for external requests\n // Any scheme counts here, as e.g. \"http:\\\\host\" or \"http:host\" can also point to another host\n const mergedConfig = /^[a-z][a-z\\d+\\-.]*:/i.test(resolvedUrl)\n ? // Merge endpoints configs for absolute URLs only if urls match\n endpointConfig?.url === url\n ? mergeConfigs(_endpointConfig, requestConfig)\n : requestConfig\n : mergeConfigs(mergeConfigs(config, _endpointConfig), requestConfig);\n\n // We prevent potential Server-Side Request Forgery attack and leakage of credentials as the same instance is not used for external requests\n // Retrigger fetch to ensure completely new instance of handler being triggered for external URLs\n return fetchf(url, mergedConfig);\n },\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 | symbol) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Symbols (e.g. inspection hooks) are never endpoints, and returning a function\n // for \"then\" would make the instance a thenable that never settles when awaited\n if (typeof prop === 'symbol' || prop === 'then') {\n return undefined;\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (hasOwn(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"]} \ No newline at end of file +{"version":3,"sources":["../../src/constants.ts","../../src/utils.ts","../../src/interceptor-manager.ts","../../src/errors/fetch-error.ts","../../src/errors/response-error.ts","../../src/timeout-wheel.ts","../../src/inflight-manager.ts","../../src/hash.ts","../../src/revalidator-manager.ts","../../src/pubsub-manager.ts","../../src/config-handler.ts","../../src/cache-manager.ts","../../src/response-parser.ts","../../src/retry-handler.ts","../../src/polling-handler.ts","../../src/upload-progress.ts","../../src/download-progress.ts","../../src/error-handler.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"names":["APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CHARSET_UTF_8","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","FUNCTION","ABORT_ERROR","TIMEOUT_ERROR","GET","HEAD","REJECT","MAX_DELAY_MS","MAX_DEPTH","hasOwn","o","k","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","key","sortObject","sortedObj","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","v","buildParams","prefix","depth","i","len","replaceUrlPathParams","urlPathParams","match","colonKey","braceKey","encoded","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","signal","resolve","done","timer","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","isPageHidden","isOffline","applyInterceptors","interceptors","args","merge","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","wheel","keyMap","position","lastTick","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","customEventProviders","setEventProvider","type","provider","removeEventHandler","addEventHandler","revalidateAll","isStaleRevalidation","isThrottled","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeRevalidator","event","handler","customProvider","cleanup","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","focusThrottleInterval","listeners","addListener","fn","set","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","merged","buildFetcherConfig","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","separator","contentTypeValue","INTERCEPTORS","baseConfig","overrideConfig","targetConfig","mergeConfig","property","mergeInterceptors","baseInterceptor","newInterceptor","base","override","isInstance","overrides","lowerKey","existingKey","_cache","stores","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADERS","generateCacheKey","config","cacheKeyCheck","headersString","keys","cacheStr","sanitizeCacheKey","bodyString","getObjectId","objectIds","lastObjectId","id","isCacheExpired","getCacheData","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","scheduleExpiry","removeExpired","store","callStore","persistCache","status","statusText","getStoredCache","isCacheBypassed","restoreCache","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","buster","getCachedResponse","cacheKey","cacheTime","handleResponseCache","output","isError","skipCache","prevCacheKey","parseResponseData","responseType","contentType","mimeType","trimmed","_error","prepareResponse","defaultResponse","mutatator","isNativeResponse","getMsFromHttpDate","dateString","getRetryAfterMs","extendedResponse","retryAfter","RATELIMIT_RESET","rateLimitResetAfter","rateLimitResetAt","withRetry","requestFn","retries","delay","backoff","maxDelay","retryOn","shouldRetry","jitter","methods","attempt","waitTime","maxRetries","cfg","onRetry","getShouldStopRetrying","retryDelay","withJitter","retryAfterMs","_b","_c","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","refreshWhenHidden","refreshWhenOffline","pollingAttempt","NULL_BODY_STATUSES","FORBIDDEN_HEADERS","isStream","toProgress","loaded","total","fetchWithUploadProgress","sendWithXhr","sendStreamed","reject","xhr","abort","settle","line","index","onAbort","stream","blob","chunk","withDownloadProgress","onDownloadProgress","counted","withErrorHandling","isCancelled","logger","redactError","strategy","SENSITIVE_HEADERS","copy","enhanceError","inFlightResponse","fetchf","cached","fetcherConfig","cancellable","isCacheEnabled","isETagEnabled","needsCacheKey","_cacheKey","initialResponse","stored","restored","toResponse","inflight","retryConfig","resetTimeout","userSignal","doRequestOnce","init","withETag","onResponse","baseRequest","_","onLoadingSlow","loadingTimeout","requestWithErrorHandling","doRequestPromise","etag","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","resolvedUrl","mergedConfig","_target","prop"],"mappings":"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","file":"index.global.js","sourcesContent":["export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CHARSET_UTF_8 = 'charset=utf-8';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\nexport const FUNCTION = 'function';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n\nexport const REJECT = 'reject';\n\n// Larger timer delays overflow and fire immediately in browsers and Node.js (~24.8 days)\nexport const MAX_DELAY_MS = 2147483647;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, MAX_DELAY_MS, OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\n// Prevent stack overflow with recursion depth limit\nconst MAX_DEPTH = 10;\n\nexport const hasOwn = (o: any, k: string) =>\n Object.prototype.hasOwnProperty.call(o, k);\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 (hasOwn(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function checks for dangerous properties like '__proto__', 'constructor',\n * and 'prototype'. If none are present, the object is returned as-is (zero-copy fast path).\n * Otherwise, a shallow copy is created with the dangerous properties removed.\n *\n * @param obj - The object to sanitize\n * @returns A safe object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const hasProto = hasOwn(obj, '__proto__');\n const hasCtor = hasOwn(obj, 'constructor');\n const hasPrototype = hasOwn(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n // Copy key by key, as a spread compiled to assignments would let \"__proto__\" set the prototype\n const safeObj = {} as Record;\n\n for (const key of Object.keys(obj)) {\n if (key !== '__proto__' && key !== 'constructor' && key !== 'prototype') {\n safeObj[key] = obj[key];\n }\n }\n\n return safeObj as T;\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 // Without a prototype, a \"__proto__\" key is kept as a regular property instead of setting the prototype\n const sortedObj = Object.create(null) as Record;\n\n Object.keys(obj)\n .sort()\n .forEach((k) => (sortedObj[k] = obj[k]));\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 + (baseUrl.includes('?') ? '&' : '?') + 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, depth = 0) => {\n // Stop recursion if maximum depth is reached\n if (depth >= MAX_DEPTH) {\n return s;\n }\n\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 depth + 1,\n );\n }\n } else if (isObject(obj)) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key], depth + 1);\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], depth + 1);\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 // This is for compatibility with server frameworks that expect the literal notation\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 `:` or `{}` (like in OpenAPI paths), where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:` or `{}`.\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 || (url.indexOf(':') === -1 && url.indexOf('{') === -1)) {\n return url;\n }\n\n // Use a single RegExp and avoid unnecessary casts and function calls\n // Precompute keys for faster lookup\n const params = urlPathParams as DefaultUrlParams;\n\n // Use a replacer function that avoids extra work\n return url.replace(/:(\\w+)|\\{(\\w+)\\}/g, (match, colonKey, braceKey) => {\n const key = colonKey || braceKey;\n\n // Use hasOwnProperty for strict key existence check\n if (hasOwn(params, key)) {\n const value = params[key];\n\n // Only replace if value is not undefined or null\n if (value !== undefined && value !== null) {\n const encoded = encodeURIComponent(String(value));\n\n // These can't be encoded, and URL parsers would move the request to another path\n if (encoded === '.' || encoded === '..') {\n throw new Error('Path params \".\" and \"..\" not allowed.');\n }\n\n return encoded;\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL starts with a scheme (e.g., \"http://\", \"https://\").\n * A \"://\" appearing later, e.g. in a query string, does not make the URL absolute.\n *\n * @param url - The URL string to check.\n * @returns `true` if the URL is absolute, otherwise `false`.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n}\n\nexport const timeNow = () => Date.now();\n\nexport const noop = () => {};\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 (value === 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 (\n typeof globalThis !== UNDEFINED &&\n typeof globalThis.Buffer !== UNDEFINED &&\n globalThis.Buffer.isBuffer(value)\n ) {\n return false;\n }\n\n if (value instanceof Date || isSearchParams(value)) {\n return false;\n }\n\n if (isObject(value)) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` (plain object)\n if (proto === Object.prototype) {\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\n/**\n * Waits for the given time. When a signal is passed, the wait ends early once it is aborted.\n *\n * @param {number} ms - The time to wait in milliseconds.\n * @param {AbortSignal} [signal] - An optional signal that ends the wait when aborted.\n * @returns {Promise} - A promise that resolves with `true` once the wait is over.\n */\nexport const delayInvocation = (\n ms: number,\n signal?: AbortSignal,\n): Promise =>\n new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n if (signal) {\n signal.removeEventListener('abort', done);\n }\n resolve(true);\n };\n const timer = setTimeout(done, Math.min(ms, MAX_DELAY_MS));\n\n if (signal) {\n if (signal.aborted) {\n done();\n } else {\n signal.addEventListener('abort', done);\n }\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, depth = 0): any {\n if (depth >= MAX_DEPTH) {\n return data;\n }\n\n if (data && isObject(data) && typeof data.data !== UNDEFINED) {\n return flattenData(data.data, depth + 1);\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 // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key.toLowerCase()] = value;\n });\n } else {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n // Assigning \"__proto__\" would set the prototype of the result\n if (hasOwn(headers, key) && key !== '__proto__') {\n headersObject[key.toLowerCase()] = headers[key];\n }\n }\n }\n\n return headersObject;\n}\n\n/**\n * Determines if the current environment is a browser.\n *\n * @returns {boolean} - True if running in a browser environment, false otherwise.\n */\nexport function isBrowser(): boolean {\n // For node and some mobile frameworks like React Native, `add/removeEventListener` doesn't exist on window!\n return (\n typeof window !== UNDEFINED && typeof window.addEventListener === FUNCTION\n );\n}\n\n/**\n * Creates an abort/timeout error compatible with all JS runtimes.\n * Falls back to a plain Error with the correct `name` when DOMException is unavailable (e.g. React Native).\n *\n * @param {string} message - The error message.\n * @param {string} name - The error name (e.g. 'AbortError', 'TimeoutError').\n * @returns {DOMException | Error} - An error object with the specified name.\n */\nexport function createAbortError(\n message: string,\n name: string,\n): DOMException | Error {\n if (typeof DOMException !== UNDEFINED) {\n return new DOMException(message, name);\n }\n\n const error = new Error(message);\n error.name = name;\n\n return error;\n}\n\n/**\n * Detects if the user is on a slow network connection\n * @returns {boolean} True if connection is slow, false otherwise or if detection unavailable\n */\nexport const isSlowConnection = (): boolean => {\n const conn = typeof navigator !== UNDEFINED && (navigator as any).connection;\n\n return conn && ['slow-2g', '2g', '3g'].includes(conn.effectiveType);\n};\n\n/**\n * Detects if the page is hidden, e.g. when its tab is in the background or the window is minimized\n * @returns {boolean} True if the page is hidden, false otherwise or outside browsers\n */\nexport const isPageHidden = (): boolean =>\n typeof document !== UNDEFINED && document.visibilityState === 'hidden';\n\n/**\n * Detects if the browser is offline\n * @returns {boolean} True if the browser is offline, false otherwise or if the connection state is unknown\n */\nexport const isOffline = (): boolean =>\n typeof navigator !== UNDEFINED && navigator.onLine === false;\n","import { FUNCTION } from './constants';\nimport type { InterceptorFunction } from './types/interceptor-manager';\nimport { isObject, sanitizeObject } from './utils';\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 Args - Type of additional arguments.\n * @template I - Type of interceptors.\n *\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n * @param {T} data - The data object to process.\n * @param {...Args} args - Additional arguments to pass to interceptors.\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptors<\n T extends object,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Args extends any[] = any[],\n I = InterceptorFunction | InterceptorFunction[],\n>(interceptors: I | undefined, data: T, ...args: Args): Promise {\n if (!interceptors) {\n return;\n }\n\n const merge = (v: unknown) =>\n v &&\n isObject(data) &&\n isObject(v) &&\n Object.assign(data, sanitizeObject(v));\n\n if (typeof interceptors === FUNCTION) {\n merge(await (interceptors as InterceptorFunction)(data, ...args));\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n merge(await interceptor(data, ...args));\n }\n }\n}\n","import type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\n/**\n * This is a base error class\n */\nexport class FetchError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends Error {\n // Declared only, and set in the constructor, as class fields would need a helper in the ES2018 bundle\n declare status: number;\n declare statusText: string;\n declare config: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >;\n declare isCancelled: boolean;\n declare request: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >;\n declare response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null;\n\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message);\n\n this.request = request;\n this.response = response;\n this.status = response ? response.status : 0;\n this.statusText = response ? response.statusText : '';\n this.config = request;\n this.isCancelled = false;\n this.name = 'FetchError';\n }\n}\n","import { FetchError } from './fetch-error';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\nexport class ResponseError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends FetchError {\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message, request, response);\n\n this.name = 'ResponseError';\n }\n}\n","/**\n * @module timeout-wheel\n * @description\n * Ultra-minimal timing wheel implementation optimized for max performance & many requests.\n * For most of the cases it's 4-100x faster than setTimeout and setInterval alone.\n * Provides efficient scheduling and cancellation of timeouts using a circular array.\n *\n * Position 0 → 1 → 2 → ... → 599 → 0 → 1 → 2 ...\n * Time: 0s 1s 2s 599s 600s 601s 602s\n *\n * The timing wheel consists of 600 slots (one per second for 10 min).\n * Each slot contains a list of timeout items, each associated with a unique key and callback.\n * Timeouts are scheduled by placing them in the appropriate slot based on the delay in seconds.\n * The wheel advances every second, executing and removing callbacks as their timeouts expire.\n * Defaults to setTimeout if the delay doesn't fit in the wheel (~10 minutes) or is not divisible by 1000.\n *\n * @remarks\n * - Designed for minimal footprint and simplicity.\n * - Only supports second-level granularity (minimum timeout: 1 second).\n * - Timeouts never fire early, but may fire up to 1 second late.\n * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { MAX_DELAY_MS } from './constants';\nimport { noop, timeNow } from './utils';\n\ntype TimeoutCallback = () => unknown | Promise;\ntype TimeoutItem = [string, TimeoutCallback]; // [key, callback]\n\nconst WHEEL_SIZE = 600; // 600 slots for 10 min (1 slot per second)\nconst SECOND = 1000; // 1 second in milliseconds\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\nlet lastTick = 0; // Time when the wheel last advanced (or started)\nlet timer: NodeJS.Timeout | null = null;\n\nconst handleCallback = ([key, callback]: TimeoutItem): void => {\n keyMap.delete(key);\n\n try {\n const result = callback();\n if (result && result instanceof Promise) {\n // Silently ignore async errors to prevent wheel from stopping\n result.catch(noop);\n }\n } catch {\n // Ignore callback errors to prevent wheel from stopping\n }\n};\n\nexport const addTimeout = (\n key: string,\n cb: TimeoutCallback,\n ms: number,\n): void => {\n removeTimeout(key);\n\n // A running wheel is already part-way through its current second, so the timeout\n // waits one more slot to never fire early. A new wheel starts its first second now.\n const seconds = ms / SECOND + (timer && timeNow() !== lastTick ? 1 : 0);\n\n // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || seconds >= WHEEL_SIZE || ms % SECOND !== 0) {\n keyMap.set(key, [\n setTimeout(\n handleCallback.bind(null, [key, cb]),\n Math.min(ms, MAX_DELAY_MS),\n ),\n ]); // Store timeout ID instead of slot\n\n return;\n }\n\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n lastTick = timeNow();\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n lastTick = timeNow();\n const slot = wheel[position];\n\n // Use slot.length directly (not cached) so mid-iteration mutations\n // from callbacks (e.g. removeTimeout) are handled correctly\n for (let i = 0; i < slot.length; i++) {\n handleCallback(slot[i]);\n }\n\n slot.length = 0; // Reuse array, avoid GC allocation\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }, SECOND);\n }\n};\n\nexport const removeTimeout = (key: string): void => {\n const slotOrTimeout = keyMap.get(key);\n\n if (slotOrTimeout !== undefined) {\n // It's a Timeout object from setTimeout\n if (Array.isArray(slotOrTimeout)) {\n clearTimeout(slotOrTimeout[0]);\n } else {\n const slotArr = wheel[slotOrTimeout];\n\n for (let i = 0; i < slotArr.length; i++) {\n if (slotArr[i][0] === key) {\n slotArr.splice(i, 1);\n break;\n }\n }\n }\n\n keyMap.delete(key);\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }\n};\n\nexport const clearAllTimeouts = () => {\n // Clear native setTimeout timeouts first!\n keyMap.forEach((value) => {\n if (Array.isArray(value)) {\n clearTimeout(value[0]);\n }\n });\n\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n\n keyMap.clear();\n\n for (let i = 0; i < WHEEL_SIZE; i++) {\n wheel[i].length = 0;\n }\n\n position = 0;\n};\n","/**\n * @module inflight-manager\n *\n * Manages in-flight asynchronous requests using unique keys to enable deduplication and cancellation.\n *\n * Provides utilities for:\n * - Deduplication of requests within a configurable time window (`dedupeTime`)\n * - Timeout management and automatic request abortion\n * - AbortController lifecycle and cancellation logic\n * - Concurrency control and request state tracking\n * - In-flight promise deduplication to prevent duplicate network calls\n *\n * @remarks\n * - Requests with the same key within the deduplication interval share the same AbortController and in-flight promise.\n * - Supports cancellation of previous requests when a new one with the same key is issued, if `isCancellable` is enabled.\n * - Timeout logic ensures requests are aborted after a specified duration, if enabled.\n * - Internal queue state is managed via a Map, keyed by request identifier.\n * - Polled requests are also marked as \"in-flight\" to prevent duplicate requests.\n */\n\nimport { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { createAbortError, timeNow } from './utils';\n\nexport type InFlightItem = [\n AbortController, // AbortController for the request\n boolean, // Whether timeout is enabled for the request\n number, // Timestamp when the request was marked in-flight\n boolean, // isCancellable - whether the request can be cancelled\n Promise | null, // Optional in-flight promise for deduplication\n];\n\nconst inFlight: Map = 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 {string | null} key - Unique key for the request (e.g. cache key).\n * @param {string} url - The request URL (for error messages/timeouts).\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 {AbortController} - A promise that resolves to an AbortController.\n */\nexport function markInFlight(\n key: string | null,\n url: string,\n timeout: number | undefined,\n dedupeTime: number,\n isCancellable: boolean,\n isTimeoutEnabled: boolean,\n): AbortController {\n if (!key) {\n return new AbortController();\n }\n\n const now = timeNow();\n const item = inFlight.get(key);\n let prevPromise: Promise | null = null;\n\n // Previous request is in-flight, check if we can reuse it\n if (item) {\n const prevController = item[0];\n const prevIsCancellable = item[3];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (\n !prevIsCancellable &&\n now - item[2] < dedupeTime &&\n !prevController.signal.aborted\n ) {\n return prevController;\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 (prevIsCancellable) {\n prevController.abort(\n createAbortError('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n removeTimeout(key);\n prevPromise = item[4];\n }\n\n const controller = new AbortController();\n\n inFlight.set(key, [\n controller,\n isTimeoutEnabled,\n now,\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n createAbortError(url + ' aborted due to timeout', TIMEOUT_ERROR),\n );\n },\n timeout as number,\n );\n }\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param key - Unique key for the request.\n * @param {boolean} error - Optional error to abort the request with. If null, the request is simply removed but no abort sent.\n * @returns {Promise} - A promise that resolves when the request is aborted and removed.\n */\nexport async function abortRequest(\n key: string | null,\n error: DOMException | Error | null | string = null,\n): Promise {\n // If the key is not in the queue, there's nothing to remove\n if (key) {\n const item = inFlight.get(key);\n\n if (item) {\n // If the request is not yet aborted, abort it with the provided error\n if (error) {\n const controller = item[0];\n controller.abort(error);\n }\n\n removeInFlight(key);\n }\n }\n}\n\n/**\n * Removes a request from the in-flight queue without aborting or clearing timeout.\n *\n * @param key - Unique key for the request.\n */\nexport function removeInFlight(key: string | null): void {\n removeTimeout(key!);\n inFlight.delete(key!);\n}\n\n/**\n * Gets the AbortController for a request key.\n *\n * @param key - Unique key for the request.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n key: string,\n): Promise {\n const item = inFlight.get(key);\n\n return item && item[0];\n}\n\n/**\n * Adds helpers for in-flight promise deduplication.\n *\n * @param key - Unique key for the request.\n * @param promise - The promise to store.\n */\nexport function setInFlightPromise(\n key: string,\n promise: Promise,\n): void {\n const item = inFlight.get(key);\n if (item) {\n // store the promise at index 4 — item is already the Map's reference, no need to re-set\n item[4] = promise;\n }\n}\n\n/**\n * Retrieves the in-flight promise for a request key if it exists and is within the dedupeTime interval.\n *\n * @param key - Unique key for the request.\n * @param dedupeTime - Deduplication time in milliseconds.\n * @returns {Promise | null} - The in-flight promise or null.\n */\nexport function getInFlightPromise(\n key: string | null,\n dedupeTime: number,\n): Promise | null {\n if (!key) {\n return null;\n }\n\n const prevReq = inFlight.get(key);\n\n if (\n prevReq &&\n // If the request is in-flight and has a promise\n prevReq[4] &&\n // If the request is cancellable, we will not reuse it\n !prevReq[3] &&\n // If the request is within the dedupeTime\n timeNow() - prevReq[2] < dedupeTime &&\n // If one request is cancelled, ALL deduped requests get cancelled\n !prevReq[0].signal.aborted\n ) {\n return prevReq[4] as Promise;\n }\n\n return null;\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","/**\n * @module revalidator-manager\n *\n * Provides utilities for managing cache revalidation functions, including:\n * - Registering and unregistering revalidators for specific cache keys.\n * - Triggering revalidation for a given key.\n * - Enabling or disabling automatic revalidation on window focus and if user comes back online for specific keys.\n * - Attaching and removing global focus and online event handlers to trigger revalidation.\n *\n * Revalidators are functions that can be registered to revalidate cache entries when needed.\n * They are typically used to refresh data in the cache when the window gains focus or when specific actions occur.\n * @performance O(1) lookup by key makes it blazing fast to register, unregister, and revalidate cache entries.\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n * @remarks\n * - Designed to be used in various environments (Deno, Node.js, Bun, Browser, etc.) to ensure cache consistency and freshness.\n */\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { FetchResponse } from './types';\nimport { isBrowser, noop, timeNow } from './utils';\n\nexport type RevalidatorFn = (\n isStaleRevalidation?: boolean,\n) => Promise;\n\ntype EventType = 'focus' | 'online';\n\ntype RevalidatorEntry = [\n RevalidatorFn, // main revalidator\n number, // lastUsed\n number, // ttl\n number?, // staleTime\n RevalidatorFn?, // bgRevalidator\n boolean?, // refetchOnFocus\n boolean?, // refetchOnReconnect\n number?, // focusThrottleInterval\n];\n\nconst DEFAULT_TTL = 3 * 60 * 1000; // Default TTL of 3 minutes\nconst revalidators = new Map();\n\n/**\n * Stores cleanup functions for active event handlers (browser or custom providers).\n * Each entry removes the corresponding event listener when called.\n * @remarks\n * - Improves performance by reducing the number of event listeners.\n * - Enables efficient O(1) lookup and management of event handlers for revalidation.\n */\nconst eventHandlers = new Map void>();\n\n/** Subscribe to an event and return a cleanup function */\nexport type EventProvider = (handler: () => void) => () => void;\n\nconst customEventProviders = new Map();\n\n/**\n * Registers a custom event provider for 'focus' or 'online' events.\n * Useful for non-browser environments like React Native.\n *\n * @param type - The event type ('focus' or 'online').\n * @param provider - A function that subscribes to the event and returns a cleanup function.\n */\nexport function setEventProvider(\n type: EventType,\n provider: EventProvider,\n): void {\n customEventProviders.set(type, provider);\n\n // Re-register if already active\n if (eventHandlers.has(type)) {\n removeEventHandler(type);\n addEventHandler(type);\n }\n}\n\n/**\n * Triggers revalidation for all registered entries based on the given event type.\n * For example, if it's a 'focus' event, it will revalidate entries that have the `refetchOnFocus` flag set.\n * Updates the timestamp and invokes the revalidator function for each applicable entry.\n *\n * @param type - The type of event that caused the revalidation (e.g., 'focus' or 'online').\n * @param isStaleRevalidation - If `true`, uses background revalidator and doesn't mark as in-flight.\n * @param isThrottled - If `true`, skips entries that were requested or revalidated within their `focusThrottleInterval`.\n */\nexport function revalidateAll(\n type: EventType,\n isStaleRevalidation: boolean = true,\n isThrottled: boolean = false,\n) {\n const flagIndex = type === 'focus' ? 5 : 6;\n const now = timeNow();\n\n revalidators.forEach((entry) => {\n if (!entry[flagIndex] || (isThrottled && now - entry[1] < entry[7]!)) {\n return;\n }\n\n entry[1] = now;\n\n // If it's a stale revalidation, use the background revalidator function\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n if (revalidator) {\n Promise.resolve(revalidator(isStaleRevalidation)).catch(noop);\n }\n });\n}\n\n/**\n * Revalidates an entry by executing the registered revalidation function.\n *\n * @param key The unique identifier for the cache entry to revalidate. If `null`, no revalidation occurs.\n * @param isStaleRevalidation - If `true`, it does not mark revalidated requests as in-flight.\n * @returns A promise that resolves to the result of the revalidator function, or\n * `null` if no key or revalidator is found, or a `FetchResponse` if applicable.\n */\nexport async function revalidate(\n key: string | null,\n isStaleRevalidation: boolean = false,\n): Promise {\n // If no key is provided, no revalidation occurs\n if (!key) {\n return null;\n }\n\n const entry = revalidators.get(key);\n\n if (entry) {\n // Update only the lastUsed timestamp without resetting the whole array\n entry[1] = timeNow();\n\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n // If no revalidator function is registered, return null\n if (revalidator) {\n return await revalidator(isStaleRevalidation);\n }\n }\n\n // If no revalidator is registered for the key, return null\n return null;\n}\n\n/**\n * Removes all revalidators associated with the specified event type.\n *\n * @param type - The event type whose revalidators should be removed.\n */\nexport function removeRevalidators(type: EventType) {\n removeEventHandler(type);\n\n const flagIndex = type === 'focus' ? 5 : 6;\n\n // Clear all revalidators with this flag\n revalidators.forEach((entry, key) => {\n if (entry[flagIndex]) {\n removeRevalidator(key);\n }\n });\n}\n\n/**\n * Registers a generic revalidation event handler for the specified event type.\n * Supports browser window events and custom event providers (e.g. for React Native).\n * Ensures the handler is only added once.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'online').\n */\nfunction addEventHandler(event: EventType) {\n if (eventHandlers.has(event)) {\n return;\n }\n\n // Focus events are throttled, so that e.g. switching between tabs quickly doesn't revalidate every time\n const handler = revalidateAll.bind(null, event, true, event === 'focus');\n\n // Priority 1: Custom event provider (works in any environment including React Native)\n const customProvider = customEventProviders.get(event);\n\n if (customProvider) {\n const cleanup = customProvider(handler);\n\n eventHandlers.set(event, cleanup);\n\n return;\n }\n\n // Priority 2: Browser window events\n if (isBrowser()) {\n window.addEventListener(event, handler);\n\n eventHandlers.set(event, () => window.removeEventListener(event, handler));\n }\n}\n\n/**\n * Removes the event handler for the specified event type.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n const cleanup = eventHandlers.get(event);\n\n if (cleanup) {\n cleanup();\n eventHandlers.delete(event);\n }\n}\n\n/**\n * Registers a revalidation functions for a specific cache key.\n *\n * @param {string} key Cache key to utilize\n * @param {RevalidatorFn} revalidatorFn Main revalidation function (marks in-flight requests)\n * @param {number} [ttl] Time to live in milliseconds (default: 3 minutes)\n * @param {number} [staleTime] Time (in seconds) after which the cache entry is considered stale\n * @param {RevalidatorFn} [bgRevalidatorFn] For stale revalidation (does not mark in-flight requests)\n * @param {boolean} [refetchOnFocus] Whether to revalidate on window focus\n * @param {boolean} [refetchOnReconnect] Whether to revalidate on network reconnect\n * @param {number} [focusThrottleInterval] Time (in milliseconds) after a request or revalidation during which focus events don't revalidate it\n */\nexport function addRevalidator(\n key: string,\n revalidatorFn: RevalidatorFn, // Main revalidation function (marks in-flight requests)\n ttl?: number,\n staleTime?: number,\n bgRevalidatorFn?: RevalidatorFn, // For stale revalidation (does not mark in-flight requests)\n refetchOnFocus?: boolean,\n refetchOnReconnect?: boolean,\n focusThrottleInterval?: number,\n) {\n // Existing entries are updated in place\n const entry = revalidators.get(key) || ([] as unknown as RevalidatorEntry);\n\n entry[0] = revalidatorFn;\n entry[1] = timeNow();\n entry[2] = ttl ?? DEFAULT_TTL;\n entry[3] = staleTime;\n entry[4] = bgRevalidatorFn;\n entry[5] = refetchOnFocus;\n entry[6] = refetchOnReconnect;\n entry[7] = focusThrottleInterval;\n\n revalidators.set(key, entry);\n\n if (refetchOnFocus) {\n addEventHandler('focus');\n }\n\n if (refetchOnReconnect) {\n addEventHandler('online');\n }\n\n if (staleTime) {\n addTimeout('s:' + key, revalidate.bind(null, key, true), staleTime * 1000);\n }\n}\n\nexport function removeRevalidator(key: string) {\n revalidators.delete(key);\n\n // Clean up stale timer\n removeTimeout('s:' + key);\n}\n\n/**\n * Periodically cleans up expired revalidators from the registry.\n * Removes any revalidator whose TTL has expired.\n *\n * @param {number} intervalMs How often to run cleanup (default: 3 minutes)\n * @returns {() => void} A function to stop the periodic cleanup\n */\nexport function startRevalidatorCleanup(\n intervalMs: number = DEFAULT_TTL,\n): () => void {\n const intervalId = setInterval(() => {\n const now = timeNow();\n\n revalidators.forEach(\n ([, lastUsed, ttl, , , refetchOnFocus, refetchOnReconnect], key) => {\n // Skip focus-only or reconnect-only revalidators to keep them alive\n if (refetchOnFocus || refetchOnReconnect) {\n return;\n }\n\n if (ttl > 0 && now - lastUsed > ttl) {\n removeRevalidator(key);\n }\n },\n );\n }, intervalMs);\n\n return () => clearInterval(intervalId);\n}\n","/**\n * Manages a set of listeners (subscribers) for arbitrary string keys, allowing cross-context or cross-component\n * cache updates and synchronization. Provides functions to add, remove, and notify listeners, as well as a\n * convenient subscribe/unsubscribe API.\n *\n * @template T - The type of the response object passed to listeners.\n *\n * @remarks\n * - Listeners are grouped by a string key, which typically represents a cache key or resource identifier.\n * - When `notifySubscribers` is called for a key, all listeners registered for that key are invoked with the provided response.\n * - The `subscribe` function returns an unsubscribe function for convenient cleanup.\n *\n * @example\n * ```ts\n * const unsubscribe = subscribe('user:123', (response) => {\n * // handle updated data\n * });\n * // Later, to stop listening:\n * unsubscribe();\n * ```\n */\n\nimport { noop } from './utils';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Listener = (response: T) => void;\n\nconst listeners = new Map>();\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n let set = listeners.get(key);\n\n if (!set) {\n listeners.set(key, (set = new Set()));\n }\n\n set.add(fn);\n}\n\nexport function removeListener(key: string, fn: Listener) {\n const set = listeners.get(key);\n\n if (set) {\n set.delete(fn);\n\n // If the set is empty, remove the key from the listeners map\n if (set.size === 0) {\n listeners.delete(key);\n }\n }\n}\n\nexport function notifySubscribers(key: string, response: T) {\n const fns = listeners.get(key);\n\n if (fns) {\n if (fns.size === 1) {\n // If there's only one listener, call it directly\n const fn = fns.values().next().value;\n fn!(response);\n } else {\n fns.forEach((fn) => fn(response));\n }\n }\n}\n\nexport function subscribe(key: string | null, fn: (response: T) => void) {\n if (!key) {\n // No op if no key is provided\n return noop;\n }\n\n addListener(key, fn);\n\n // Return an unsubscribe function\n return () => {\n removeListener(key, fn);\n };\n}\n","import { processHeaders } from './utils';\nimport {\n GET,\n APPLICATION_JSON,\n HEAD,\n STRING,\n CHARSET_UTF_8,\n CONTENT_TYPE,\n REJECT,\n UNDEFINED,\n APPLICATION_CONTENT_TYPE,\n} from './constants';\nimport type {\n HeadersObject,\n Method,\n RequestConfig,\n} from './types/request-handler';\nimport {\n replaceUrlPathParams,\n appendQueryParams,\n isSearchParams,\n isJSONSerializable,\n isSlowConnection,\n isAbsoluteUrl,\n sanitizeObject,\n isObject,\n} from './utils';\n\nconst defaultTimeoutMs = (isSlowConnection() ? 60 : 30) * 1000;\n\nexport const defaultConfig: RequestConfig = {\n strategy: REJECT,\n timeout: defaultTimeoutMs, // 30 seconds (60 on slow connections)\n loadingTimeout: defaultTimeoutMs / 10, // 3 seconds (6 on slow connections)\n focusThrottleInterval: 5000, // 5 seconds\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n },\n retry: {\n delay: defaultTimeoutMs / 30, // 1 second (2 on slow connections)\n maxDelay: defaultTimeoutMs, // 30 seconds (60 on slow connections)\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 // Idempotent methods, which can be repeated safely, unlike e.g. POST requests that create resources\n methods: [GET, HEAD, 'PUT', 'DELETE', 'OPTIONS', 'TRACE'],\n },\n};\n\n/**\n * Overwrites the default configuration with the provided custom configuration.\n *\n * @param {Partial} customConfig - The custom configuration to merge into the default config.\n * @returns {Partial} - The updated default configuration object.\n */\nexport function setDefaultConfig(\n customConfig: Partial,\n): Partial {\n const sanitized = sanitizeObject(customConfig);\n\n // Merge nested retry and headers settings into the current defaults instead of replacing them\n return mergeConfigs(\n { retry: defaultConfig.retry, headers: defaultConfig.headers },\n sanitized,\n defaultConfig,\n );\n}\n\n/**\n * Returns a shallow copy of the current default configuration.\n *\n * @returns {RequestConfig} - The current default configuration.\n */\nexport function getDefaultConfig(): RequestConfig {\n return { ...defaultConfig };\n}\n\n/**\n * Build request configuration from defaults and overrides.\n * This function merges the default configuration with the provided request configuration,\n * @param {string} url - Request url\n * @param {RequestConfig | null | undefined} reqConfig - Request configuration\n * @return {RequestConfig} - Merged request configuration\n */\nexport function buildConfig(\n url: string,\n reqConfig?: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null,\n): RequestConfig {\n // Merging gives the request its own copies of nested objects like headers, so that\n // mutations (e.g. by interceptors) never leak into the global defaults\n const merged = mergeConfigs(\n defaultConfig,\n reqConfig ? sanitizeObject(reqConfig) : {},\n );\n\n return buildFetcherConfig(url, merged);\n}\n\n/**\n * Builds the fetcher configuration by setting the method, body, headers, and URL.\n * It also handles query parameters and path parameters. This fn mutates the passed `requestConfig` object.\n * @param {string} url - The endpoint URL to which the request will be sent.\n * @param {RequestConfig} requestConfig - The request configuration object containing method, body, headers, and other options.\n * @return {RequestConfig} - The modified request configuration object with the URL, method, body, and headers set appropriately.\n **/\nexport function buildFetcherConfig(\n url: string,\n requestConfig: RequestConfig,\n): RequestConfig {\n let method = requestConfig.method as Method;\n method = method ? (method.toUpperCase() as Method) : GET;\n\n let body: RequestConfig['data'] | undefined;\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (method !== GET && method !== HEAD) {\n body = requestConfig.body ?? requestConfig.data;\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (body && typeof body !== STRING && isJSONSerializable(body)) {\n body = JSON.stringify(body);\n }\n }\n\n setContentTypeIfNeeded(requestConfig.headers, body);\n\n // Native fetch compatible settings\n const credentials = requestConfig.withCredentials\n ? 'include'\n : requestConfig.credentials;\n\n // The explicitly passed query params\n const dynamicUrl = replaceUrlPathParams(url, requestConfig.urlPathParams);\n const urlPath = appendQueryParams(dynamicUrl, requestConfig.params);\n const isFullUrl = isAbsoluteUrl(url);\n const baseURL = isFullUrl\n ? ''\n : requestConfig.baseURL || requestConfig.apiUrl || '';\n\n // Join as a path, as plain concatenation could extend the host of the baseURL,\n // e.g. \"https://api.example.com\" + \".evil.com\" would point to another host\n const separator =\n baseURL && urlPath && !baseURL.endsWith('/') && !/^[/?#]/.test(urlPath)\n ? '/'\n : '';\n\n requestConfig.url = baseURL + separator + urlPath;\n requestConfig.method = method;\n requestConfig.credentials = credentials;\n requestConfig.body = body;\n\n return requestConfig;\n}\n\n/**\n * Ensures the `Content-Type` header is set to `application/json; charset=utf-8`\n * if it is not already present and the request method and body meet specific conditions.\n *\n * @param headers - The headers object to modify. Can be an instance of `Headers`\n * or a plain object conforming to `HeadersInit`.\n * @param body - The optional body of the request. If no body is provided and the\n * method is 'GET' or 'HEAD', the function exits without modifying headers.\n */\nfunction setContentTypeIfNeeded(\n headers?: HeadersInit | HeadersObject,\n body?: unknown,\n): void {\n // If no headers are provided, or if the body is not set and the method is PUT or DELETE, do nothing\n if (!headers || !body) {\n return;\n }\n\n // Types that should not have Content-Type set (browser handles these)\n if (\n body instanceof FormData || // Browser automatically sets multipart/form-data with boundary\n (typeof Blob !== UNDEFINED && body instanceof Blob) || // Blob/File (a File is a Blob) already have their own MIME types, don't override\n (typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream) // Stream type should be determined by the stream source\n ) {\n return;\n }\n\n let contentTypeValue: string;\n\n if (isSearchParams(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded';\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'octet-stream';\n } else if (isJSONSerializable(body)) {\n contentTypeValue = APPLICATION_JSON + ';' + CHARSET_UTF_8;\n } else {\n // Do not set Content-Type if content is not recognizable\n return;\n }\n\n if (headers instanceof Headers) {\n if (!headers.has(CONTENT_TYPE)) {\n headers.set(CONTENT_TYPE, contentTypeValue);\n }\n } else if (\n isObject(headers) &&\n !Array.isArray(headers) &&\n // Header names are case-insensitive, so check the normalized (lowercase) headers\n !processHeaders(headers as HeadersObject)[CONTENT_TYPE.toLowerCase()]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\n// The interceptors that are merged instead of replaced\nconst INTERCEPTORS = [\n 'onRequest',\n 'onResponse',\n 'onError',\n 'onLoadingSlow',\n] as const;\n\n/**\n * Merges two request configurations, applying overrides from the second config to the first.\n * Handles special merging for nested properties like 'retry' and 'headers' (deep merge),\n * and concatenates interceptor arrays for 'onRequest', 'onResponse', 'onError' and 'onLoadingSlow'.\n * If a target config is provided, it mutates that object; otherwise, creates a new one.\n *\n * @param {RequestConfig} baseConfig - The base configuration object to merge from.\n * @param {RequestConfig} overrideConfig - The override configuration object to apply on top of the base.\n * @param {RequestConfig} [targetConfig={}] - Optional target configuration object to merge into (mutated in place).\n * @returns {RequestConfig} The merged configuration object.\n *\n * @example\n * const base = { timeout: 5000, headers: { 'Accept': 'application/json' } };\n * const override = { timeout: 10000, headers: { 'Authorization': 'Bearer token' } };\n * const merged = mergeConfigs(base, override);\n * // Result: { timeout: 10000, headers: { Accept: 'application/json', Authorization: 'Bearer token' } }\n */\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig = {},\n): RequestConfig {\n Object.assign(targetConfig, baseConfig, overrideConfig);\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', baseConfig, overrideConfig, targetConfig);\n mergeConfig('headers', baseConfig, overrideConfig, targetConfig);\n\n // Merge interceptors efficiently\n for (const property of INTERCEPTORS) {\n mergeInterceptors(property, baseConfig, overrideConfig, targetConfig);\n }\n\n return targetConfig;\n}\n\n/**\n * Efficiently merges interceptor functions from base and new configs\n */\nfunction mergeInterceptors<\n K extends\n 'onRequest' | 'onResponse' | 'onError' | 'onRetry' | 'onLoadingSlow',\n>(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const baseInterceptor = baseConfig[property];\n const newInterceptor = overrideConfig[property];\n\n if (baseInterceptor && newInterceptor) {\n // This is the only LIFO interceptor, so we apply it after the response is prepared\n targetConfig[property] = (\n property === 'onResponse'\n ? [].concat(newInterceptor as never, baseInterceptor as never)\n : [].concat(baseInterceptor as never, newInterceptor as never)\n ) as RequestConfig[K];\n } else if (baseInterceptor || newInterceptor) {\n targetConfig[property] = baseInterceptor || newInterceptor;\n }\n}\n\n/**\n * Merges the specified property from the base configuration and the override configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and override configurations. Must be a key of RequestConfig.\n * @param {RequestConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestConfig} overrideConfig - The override configuration object that contains user-specific settings to merge.\n * @param {RequestConfig} targetConfig - The configuration object that will receive the merged properties.\n */\nexport function mergeConfig(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n if (override) {\n if (property === 'headers') {\n // Handle Headers instances which don't expose entries as own enumerable properties\n const isInstance =\n (base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers;\n const merged: HeadersObject = isInstance\n ? processHeaders(base)\n : { ...(base as HeadersObject) };\n const overrides: HeadersObject = isInstance\n ? processHeaders(override)\n : sanitizeObject(override as HeadersObject);\n\n // Header names are case-insensitive, so replace existing entries instead of duplicating them\n for (const key of Object.keys(overrides)) {\n const lowerKey = key.toLowerCase();\n\n for (const existingKey in merged) {\n if (existingKey.toLowerCase() === lowerKey) {\n delete merged[existingKey];\n }\n }\n\n merged[key] = overrides[key];\n }\n\n targetConfig[property] = merged as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...sanitizeObject(override as Record),\n } as RequestConfig[K];\n }\n } else if (\n override === undefined &&\n isObject(base) &&\n !((base as Headers | HeadersObject) instanceof Headers)\n ) {\n // Copy so that mutating the merged config never changes the base config\n targetConfig[property] = { ...base } as RequestConfig[K];\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport type {\n CacheKeyFunction,\n DefaultResponse,\n FetchResponse,\n MutationSettings,\n RequestConfig,\n} from './types/request-handler';\nimport type {\n CacheEntry,\n CacheStore,\n StoredResponse,\n} from './types/cache-manager';\nimport { GET, STRING } from './constants';\nimport {\n isJSONSerializable,\n isObject,\n isSearchParams,\n noop,\n sanitizeObject,\n sortObject,\n timeNow,\n} from './utils';\nimport { revalidate } from './revalidator-manager';\nimport { notifySubscribers } from './pubsub-manager';\nimport type { DefaultPayload, DefaultParams, DefaultUrlParams } from './types';\nimport { removeInFlight } from './inflight-manager';\nimport { addTimeout } from './timeout-wheel';\nimport { defaultConfig } from './config-handler';\nimport { processHeaders } from './utils';\n\nexport const IMMEDIATE_DISCARD_CACHE_TIME = 0; // Use it for cache entries that need to be persistent until unused by components or manually deleted\n\nconst _cache = new Map>();\n// The cache stores that keep copies of cache entries, by cache key\nconst stores = new Map();\nconst DELIMITER = '|';\nconst MIN_LENGTH_TO_HASH = 64;\nconst CACHE_KEY_SANITIZE_PATTERN = /[^\\w\\-_|/:@.?=&~%#]/g;\nconst CACHE_KEY_NEEDS_SANITIZE = /[^\\w\\-_|/:@.?=&~%#]/; // Non-global for fast test\n\n/**\n * Headers that may affect HTTP response content and should be included in cache key generation.\n * Header names are matched case-insensitively.\n *\n * - Content negotiation: accept (response format, e.g. JSON or HTML), accept-language (localization), accept-encoding (compression)\n * - Authentication: authorization (access to protected resources)\n * - Request body metadata: content-type (how the request body is interpreted)\n * - Optional: referer (may influence behavior in some APIs), origin (CORS or tenant-specific APIs),\n * user-agent (if the server returns client-specific content), cookie (session-based responses; can fragment the cache heavily)\n * - Custom headers that may affect response content: x-api-key (token-based access), x-requested-with (AJAX requests),\n * x-client-id (per-client/partner identity), x-tenant-id (multi-tenant segmentation), x-user-id (explicit user context),\n * x-app-version (version-specific behavior), x-feature-flag (feature rollout), x-device-id (per device/app instance),\n * x-platform (e.g. 'ios', 'android', 'web'), x-session-id (if it affects the response directly), x-locale (like accept-language)\n */\nconst CACHE_KEY_HEADERS =\n /^(accept(-language|-encoding)?|authorization|content-type|referer|origin|user-agent|cookie|x-(api-key|requested-with|client-id|tenant-id|user-id|app-version|feature-flag|device-id|platform|session-id|locale))$/i;\n\n/**\n * Generates a unique 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 {RequestConfig} config - 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 {RequestCredentials} [credentials=\"same-origin\"] - Whether to include credentials (include, same-origin, omit).\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @returns {string} - A unique cache key string based on the provided options.\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(\n config: RequestConfig,\n cacheKeyCheck = true,\n): string {\n // This is super fast. Effectively a no-op if cacheKey is\n // a string or a function that returns a string.\n const key = config.cacheKey;\n\n if (key && cacheKeyCheck) {\n return typeof key === STRING\n ? (key as string)\n : (key as CacheKeyFunction)(config);\n }\n\n const {\n url = '',\n method = GET,\n headers = null,\n body = null,\n credentials = 'same-origin',\n } = config;\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 let headersString = '';\n if (headers) {\n let obj: Record;\n\n if (headers instanceof Headers) {\n obj = processHeaders(headers);\n } else {\n obj = headers as Record;\n }\n\n // Filter headers to only include those that affect request identity\n // Include only headers that affect request identity, not execution behavior\n const keys = Object.keys(obj);\n const len = keys.length;\n\n // Sort keys manually for fastest deterministic output\n if (len > 1) {\n keys.sort();\n }\n\n let str = '';\n for (let i = 0; i < len; ++i) {\n if (CACHE_KEY_HEADERS.test(keys[i])) {\n str += keys[i] + ':' + obj[keys[i]] + ';';\n }\n }\n\n headersString = hash(str);\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString;\n\n // For GET requests, return early with shorter cache key\n if (method === GET) {\n return sanitizeCacheKey(cacheStr);\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING || isSearchParams(body)) {\n const str = String(body);\n\n bodyString = str.length < MIN_LENGTH_TO_HASH ? str : hash(str); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Files can't be read synchronously, so they are identified by their object\n bodyString +=\n key +\n '=' +\n (typeof value === STRING ? value : 'F' + getObjectId(value as File)) +\n '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (isObject(body) && !isJSONSerializable(body)) {\n // Blobs, buffers, streams etc. can't be read synchronously, so they are identified by their object.\n // Two different bodies never share a key, while the same body object is still deduplicated.\n bodyString = 'B' + getObjectId(body);\n } else {\n const o = isObject(body)\n ? JSON.stringify(sortObject(body))\n : String(body);\n\n bodyString = o.length > MIN_LENGTH_TO_HASH ? hash(o) : o;\n }\n }\n\n return sanitizeCacheKey(cacheStr + DELIMITER + bodyString);\n}\n\nconst objectIds = new WeakMap();\nlet lastObjectId = 0;\n\n/**\n * Returns a unique id for an object, e.g. a request body that can't be serialized.\n *\n * @param {object} obj - The object to identify.\n * @returns {number} - The id of the object.\n */\nfunction getObjectId(obj: object): number {\n let id = objectIds.get(obj);\n\n if (!id) {\n objectIds.set(obj, (id = ++lastObjectId));\n }\n\n return id;\n}\n\n/**\n * Prevents cache poisoning by removal of control chars and unusual characters.\n * When anything is removed, a hash of the original key is appended so that keys\n * differing only in the removed characters (e.g. `?a[]=1` and `?a=1`) don't collide.\n *\n * @param {string} cacheStr - The raw cache key.\n * @returns {string} - The sanitized cache key.\n */\nfunction sanitizeCacheKey(cacheStr: string): string {\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '') +\n DELIMITER +\n hash(cacheStr)\n : cacheStr;\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the expiry time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(entry: CacheEntry): boolean {\n // No expiry time means the entry never expires\n if (!entry.expiry) {\n return false;\n }\n\n return timeNow() > entry.expiry;\n}\n\n/**\n * Retrieves a cached response from the internal cache using the provided key.\n *\n * @param key - The unique key identifying the cached entry. If null, returns null.\n * @returns The cached {@link FetchResponse} if found, otherwise null.\n */\nexport function getCacheData<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n key: string | null,\n): FetchResponse | null {\n if (!key) {\n return null;\n }\n\n const entry = _cache.get(key);\n\n return entry ? entry.data : null;\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 * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string | null,\n):\n | CacheEntry<\n FetchResponse\n >\n | null\n | undefined {\n return _cache.get(key as string);\n}\n\n/**\n * Sets a new cache entry or updates an existing one, with optional TTL (time-to-live).\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {number} [ttl] - Optional TTL in seconds. If not provided, the cache entry will not expire.\n * @param {number} [staleTime] - Optional stale time in seconds. If provided, the cache entry will be considered stale after this time.\n */\nexport function setCache(\n key: string,\n data: T,\n ttl?: number,\n staleTime?: number,\n): void {\n if (ttl === 0) {\n deleteCache(key);\n return;\n }\n\n const time = timeNow();\n const ttlMs = ttl ? ttl * 1000 : 0;\n const staleTimeMs = staleTime ? staleTime * 1000 : 0; // Ensure default value for staleTime\n\n _cache.set(key, {\n data,\n time,\n stale: staleTimeMs > 0 ? time + staleTimeMs : undefined, // Use undefined if staleTime is not set\n expiry: ttl === -1 ? undefined : time + ttlMs,\n });\n\n if (ttlMs > 0) {\n scheduleExpiry(key, ttlMs);\n }\n}\n\n/**\n * Deletes a cache entry once it expires.\n *\n * @param {string} key Cache key to utilize\n * @param {number} ms - The time until the entry expires, in milliseconds.\n */\nfunction scheduleExpiry(key: string, ms: number): void {\n addTimeout('c:' + key, () => deleteCache(key, true), ms);\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n * @param {boolean} [removeExpired=false] - If true, only deletes the cache entry if it is expired or stale.\n */\nexport function deleteCache(key: string, removeExpired: boolean = false): void {\n if (removeExpired) {\n const entry = getCache(key);\n\n // If the entry does not exist, or it is neither expired nor stale, do not delete\n if (!entry || !isCacheExpired(entry)) {\n return;\n }\n }\n\n _cache.delete(key);\n\n const store = stores.get(key);\n\n if (store) {\n stores.delete(key);\n callStore(() => store.delete(key));\n }\n}\n\n/**\n * Prunes the cache by removing entries that have expired based on the provided cache time.\n */\nexport function pruneCache(): void {\n _cache.clear();\n stores.clear();\n}\n\n/**\n * Calls a cache store method. Store errors, e.g. of a full localStorage, are ignored so that they can't break requests.\n *\n * @param {() => unknown} fn - The function calling the store.\n */\nfunction callStore(fn: () => unknown): void {\n try {\n Promise.resolve(fn()).catch(noop);\n } catch {\n // Ignored\n }\n}\n\n/**\n * Saves a copy of a cached response in a cache store, so that it can be restored later, e.g. after a page reload.\n *\n * @param {string} key Cache key to utilize\n * @param {CacheStore} [store] - The cache store. If not provided, nothing is saved.\n */\nfunction persistCache(key: string, store?: CacheStore): void {\n const entry = _cache.get(key);\n\n if (store && entry) {\n const { data, status, statusText, headers } = entry.data as FetchResponse;\n\n stores.set(key, store);\n callStore(() =>\n store.set(key, { ...entry, data: { data, status, statusText, headers } }),\n );\n }\n}\n\n/**\n * Reads the entry of a cache key from the cache store of a request, e.g. one saved during a previous page load.\n * Expired entries are deleted from the store.\n *\n * @param {string} key Cache key to utilize\n * @param {RequestConfig} requestConfig - The request configuration.\n * @returns {Promise | null>} - The stored entry, or null if there is no valid one or the in-memory cache has an entry already.\n */\nexport async function getStoredCache(\n key: string,\n requestConfig: RequestConfig,\n): Promise | null> {\n const store = requestConfig.cacheStore;\n\n if (!store || isCacheBypassed(requestConfig)) {\n return null;\n }\n\n let entry: CacheEntry | null | undefined;\n\n try {\n entry = await store.get(key);\n } catch {\n // A failing store is treated like an empty one\n return null;\n }\n\n // Another request may have cached a response in the meantime\n if (!entry || _cache.has(key)) {\n return null;\n }\n\n if (isCacheExpired(entry)) {\n callStore(() => store.delete(key));\n\n return null;\n }\n\n return entry;\n}\n\n/**\n * Caches a response restored from a cache store in memory, keeping its original stale and expiry times.\n *\n * @param {string} key Cache key to utilize\n * @param {CacheEntry} entry - The cache entry with the restored response.\n * @param {CacheStore} store - The cache store that the response was restored from.\n * @returns {boolean} - True if the restored response is fresh, false if it's stale.\n */\nexport function restoreCache(\n key: string,\n entry: CacheEntry,\n store: CacheStore,\n): boolean {\n _cache.set(key, entry);\n stores.set(key, store);\n\n if (entry.expiry) {\n scheduleExpiry(key, entry.expiry - timeNow());\n }\n\n notifySubscribers(key, entry.data);\n\n return !entry.stale || timeNow() < entry.stale;\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string | null} key Cache key to utilize. If null, no mutation occurs.\n * @param {ResponseData} newData - The new data to be cached.\n * @param {MutationSettings|undefined} settings - Mutation settings.\n */\nexport async function mutate<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n key: string | null,\n newData: ResponseData,\n settings?: MutationSettings,\n): Promise | null> {\n // If no key is provided, do nothing\n if (!key) {\n return null;\n }\n\n const entry = getCache(\n key,\n );\n\n if (!entry) {\n return null;\n }\n\n const updatedData = isObject(newData) ? sanitizeObject(newData) : newData;\n\n const updatedResponse = {\n ...entry.data,\n data: updatedData,\n };\n\n // The ETag belongs to the original data, so the changed data must not be revalidated with it\n const headers = updatedResponse.headers;\n\n if (headers && headers.etag) {\n updatedResponse.headers = { ...headers };\n delete updatedResponse.headers.etag;\n }\n\n const updatedEntry = {\n ...entry,\n data: updatedResponse,\n };\n\n _cache.set(key, updatedEntry);\n persistCache(key, stores.get(key));\n notifySubscribers(key, updatedResponse);\n\n if (settings && settings.refetch) {\n return await revalidate(key);\n }\n\n return null;\n}\n\n/**\n * Checks whether a request should bypass the cache, because of its cache buster or `cache: 'reload'`.\n *\n * @param {RequestConfig} requestConfig - The request configuration.\n * @returns {boolean} - True if the cache should be bypassed.\n */\nexport function isCacheBypassed(requestConfig: RequestConfig): boolean {\n const buster = requestConfig.cacheBuster || defaultConfig.cacheBuster;\n\n return (\n !!(buster && buster(requestConfig)) || requestConfig.cache === 'reload'\n );\n}\n\n/**\n * Retrieves a cached response if available and valid, otherwise returns null.\n *\n * @template ResponseData - The type of the response data.\n * @template RequestBody - The type of the request body.\n * @template QueryParams - The type of the query parameters.\n * @template PathParams - The type of the path parameters.\n * @param {string | null} cacheKey - The cache key to look up.\n * @param {number | undefined} cacheTime - The maximum time to cache entry.\n * @param {RequestConfig} requestConfig - The fetcher configuration.\n * @returns {FetchResponse | null} - The cached response or null.\n */\nexport function getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n cacheKey: string | null,\n cacheTime: number | undefined,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): FetchResponse | null {\n // If cache key or time is not provided, return null\n if (!cacheKey || cacheTime === undefined || cacheTime === null) {\n return null;\n }\n\n if (isCacheBypassed(requestConfig)) {\n return null;\n }\n\n // Retrieve the cached entry\n const entry = getCache(\n cacheKey,\n );\n\n if (!entry) {\n return null;\n }\n\n const isExpired = isCacheExpired(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n const data = entry.data;\n\n // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n // The placeholder stored while a request is in flight is not a response, so treat it as a miss\n return data && data.isFetching ? null : data;\n}\n\n/**\n * Sets or deletes the response cache based on cache settings and notifies subscribers.\n *\n * @param {FetchResponse} output - The response to cache.\n * @param {RequestConfig} requestConfig - The request configuration.\n * @param {boolean} [isError=false] - Whether the response is an error.\n */\nexport function handleResponseCache<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n output: FetchResponse,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n isError: boolean = false,\n): void {\n // It is string as it is called once request is made\n const cacheKey = requestConfig.cacheKey as string;\n\n if (cacheKey) {\n const cacheTime = requestConfig.cacheTime;\n const skipCache = requestConfig.skipCache;\n\n // Fast path: only set cache if cacheTime is positive and not skipping cache\n if (\n cacheTime &&\n (!isError || requestConfig.cacheErrors) &&\n !(skipCache && skipCache(output, requestConfig))\n ) {\n setCache(cacheKey, output, cacheTime, requestConfig.staleTime);\n\n // Error responses are only cached in memory\n if (!isError) {\n persistCache(cacheKey, requestConfig.cacheStore);\n }\n } else {\n const entry = getCache(cacheKey);\n\n // Don't let the in-flight placeholder outlive a request whose result isn't cached\n if (entry && entry.data && entry.data.isFetching) {\n deleteCache(cacheKey);\n }\n }\n\n notifySubscribers(cacheKey, output);\n removeInFlight(cacheKey);\n\n const prevCacheKey = requestConfig._prevKey;\n\n if (prevCacheKey) {\n removeInFlight(prevCacheKey);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { mutate } from './cache-manager';\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n FUNCTION,\n STRING,\n} from './constants';\nimport {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n ResponseError,\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n} from './types';\nimport { flattenData, isObject, processHeaders } from './utils';\n\n/**\n * Parses the response data based on the Content-Type header, or reads it as the given response type.\n *\n * @param response - The Response object to parse.\n * @param responseType - How to read the body regardless of its Content-Type, e.g. as a Blob, or `'stream'` to leave it unread.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse,\n responseType?: RequestConfig['responseType'],\n): Promise {\n // Bail early if response is null or undefined\n if (!response) {\n return null;\n }\n\n // Get the content-type header once\n const headers = (response as Response).headers;\n let contentType = headers && headers.get(CONTENT_TYPE);\n\n if (contentType) {\n // Lowercase and trim for consistent matching\n contentType = contentType.toLowerCase().trim();\n } else {\n contentType = '';\n }\n\n // Split for mime type without charset\n const mimeType = contentType.split(';', 1)[0];\n\n let data;\n\n try {\n if (responseType) {\n // The body is read as requested, or left unread as a stream to be read by the caller\n data =\n responseType === 'stream'\n ? response.body\n : await response[responseType]();\n } else if (\n mimeType.includes(APPLICATION_JSON) ||\n mimeType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (\n (mimeType.includes('multipart/form-data') || // Parse as FormData\n mimeType.includes(\n APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded', // Handle URL-encoded forms\n )) &&\n typeof response.formData === FUNCTION\n ) {\n data = await response.formData();\n } else if (/^(image|video|audio)\\/|octet-stream|pdf|zip/.test(mimeType)) {\n data = await response.arrayBuffer(); // Parse as ArrayBuffer for binary types\n } else {\n data = await response.text();\n\n if (typeof data === STRING) {\n const trimmed = data.trim();\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n data = JSON.parse(trimmed);\n } catch {\n // leave as text if parsing fails\n }\n }\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\n/**\n * Prepare response object with additional information.\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} config - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\nexport const prepareResponse = <\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n config: RequestConfig,\n error: ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null,\n): FetchResponse => {\n const defaultResponse = config.defaultResponse;\n const cacheKey = config.cacheKey;\n const mutatator = mutate.bind(null, cacheKey as string) as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >['mutate'];\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 ?? null,\n headers: null,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: false,\n isError: true,\n } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n const isNativeResponse =\n typeof Response === FUNCTION && response instanceof Response;\n\n let data = response.data;\n\n // Set the default response if the provided data is an empty object or array\n // Other objects, e.g. Blobs, buffers and streams, have no keys either, but aren't empty\n if (\n defaultResponse !== undefined &&\n (data === undefined ||\n data === null ||\n (/^\\[object (Object|Array)\\]$/.test(\n Object.prototype.toString.call(data),\n ) &&\n Object.keys(data).length === 0))\n ) {\n response.data = data = defaultResponse;\n }\n\n if (config.flattenResponse) {\n response.data = data = flattenData(data);\n }\n\n if (config.select) {\n response.data = data = config.select(data);\n }\n\n const headers = processHeaders(response.headers);\n\n // Native fetch Response extended by extra information\n if (isNativeResponse) {\n const output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > = {\n body: response.body,\n bodyUsed: response.bodyUsed,\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 // Convert methods to use arrow functions to preserve correct return types\n // Lazily construct Blob from ArrayBuffer\n blob: async () =>\n data instanceof ArrayBuffer ? new Blob([data]) : new Blob(),\n json: async () => data as ResponseData, // Return the already parsed JSON data\n text: async () => data as string, // Return the already parsed text data\n // The body was already read, so a copy of this response is returned instead of Response.clone()\n clone: () => ({ ...output }),\n arrayBuffer: async () =>\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0), // Return the ArrayBuffer directly\n formData: async () => (data instanceof FormData ? data : new FormData()), // Return the already parsed FormData\n bytes: async () =>\n new Uint8Array(data instanceof ArrayBuffer ? data : new ArrayBuffer(0)),\n // Enhance the response with extra information\n error,\n data,\n headers,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: response.ok && !error,\n isError: !!error,\n };\n\n return output;\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 (isObject(response)) {\n // Assigned one by one, as Object.assign() with an object literal is measurably slower here\n response.error = error;\n response.headers = headers;\n response.isFetching = false;\n response.mutate = mutatator;\n response.isSuccess = response.ok && !error;\n response.isError = !!error;\n }\n\n return response;\n};\n","import { applyInterceptors } from './interceptor-manager';\nimport type { FetchResponse, RetryConfig, RetryFunction } from './types';\nimport { delayInvocation, timeNow } from './utils';\nimport { generateCacheKey } from './cache-manager';\nimport { FUNCTION } from './constants';\n\nfunction getMsFromHttpDate(dateString: string): number | null {\n const ms = Date.parse(dateString) - timeNow();\n\n if (!isNaN(ms)) {\n return Math.max(0, Math.floor(ms));\n }\n return null;\n}\n\n/**\n * Calculates the number of milliseconds to wait before retrying a request,\n * based on the `Retry-After` HTTP header in the provided response.\n *\n * The function supports both numeric (seconds) and HTTP-date formats for the `Retry-After` header.\n * - If the header is a number, it is interpreted as seconds and converted to milliseconds.\n * - If the header is a date, the function calculates the difference between the date and the current time.\n *\n * @param extendedResponse - The response object containing headers, or `null`.\n * @returns The number of milliseconds to wait before retrying, or `null` if the header is not present or invalid.\n */\nexport function getRetryAfterMs(\n extendedResponse: FetchResponse | null,\n): number | null {\n if (!extendedResponse) {\n return null;\n }\n\n const headers = extendedResponse.headers || {};\n const retryAfter = headers['retry-after'];\n\n if (retryAfter) {\n // Try parsing as seconds\n const seconds = Number(retryAfter);\n\n if (!isNaN(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n const ms = getMsFromHttpDate(retryAfter);\n\n if (ms !== null) {\n return ms;\n }\n }\n\n // Headers are already in lowercase\n const RATELIMIT_RESET = 'ratelimit-reset';\n\n // Unix timestamp when the rate limit window resets (relative to current time)\n // Fallback to checking 'ratelimit-reset-after' OR 'x-ratelimit-reset-after' headers\n const rateLimitResetAfter =\n headers[RATELIMIT_RESET + '-after'] ||\n headers['x-' + RATELIMIT_RESET + '-after'];\n\n if (rateLimitResetAfter) {\n const seconds = Number(rateLimitResetAfter);\n\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n }\n\n // ISO 8601 datetime when the rate limit resets\n // Fallback to checking 'ratelimit-reset-at' 'x-ratelimit-reset-at' headers\n const rateLimitResetAt =\n headers[RATELIMIT_RESET + '-at'] || headers['x-' + RATELIMIT_RESET + '-at'];\n\n if (rateLimitResetAt) {\n return getMsFromHttpDate(rateLimitResetAt);\n }\n\n return null;\n}\n\n/**\n * Executes a request function with retry logic according to the provided configuration.\n *\n * The function attempts the request up to the specified number of retries, applying delay and backoff strategies.\n * Retries can be triggered based on response status codes, custom logic, or the presence of a `Retry-After` header.\n * Optionally, an `onRetry` interceptor can be invoked before each retry attempt.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param requestFn - The function that performs the request. Receives `isStaleRevalidation` and `attempt` as arguments.\n * @param config - The retry configuration, including retry count, delay, backoff, retry conditions, and hooks.\n * @returns A promise resolving to the fetch response, or rejecting if all retries are exhausted.\n * @throws Error if the maximum number of retries is exceeded or a non-retriable error occurs.\n */\nexport async function withRetry<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation: boolean,\n attempt: number,\n ) => Promise<\n FetchResponse\n >,\n config: RetryConfig,\n): Promise> {\n const {\n retries = 0,\n delay = 0,\n backoff = 1,\n maxDelay,\n retryOn = [],\n shouldRetry,\n jitter,\n methods,\n } = config;\n\n let attempt = 0;\n let waitTime = delay;\n const maxRetries = retries > 0 ? retries : 0;\n let output: FetchResponse;\n\n while (attempt <= maxRetries) {\n // Subsequent attempts will have output defined, but the first attempt may not.\n // Let's apply onRetry interceptor and regenerate cache key if ot really changes.\n if (attempt > 0 && output!) {\n const cfg = output.config;\n const onRetry = cfg.onRetry;\n\n if (onRetry) {\n await applyInterceptors(onRetry, output, attempt);\n\n // If the key was automatically generated, we need to regenerate it as config may change.\n // We don't detect whether config changed for performance reasons.\n if (cfg._isAutoKey) {\n cfg._prevKey = cfg.cacheKey as string;\n cfg.cacheKey = generateCacheKey(cfg, false);\n }\n }\n }\n\n // Performance optimization: Call the request function with the current attempt number\n // If this is the first attempt, we pass `isStaleRevalidation` as `false`,\n // otherwise we pass `true` to indicate that this is a stale revalidation (no cache hit).\n output = await requestFn(attempt > 0, attempt);\n const error = output.error;\n\n // Stop unless a failed response should be retried according to the retry settings,\n // or a successful one according to shouldRetry\n if (\n error\n ? await getShouldStopRetrying(\n output,\n attempt,\n maxRetries,\n shouldRetry,\n retryOn,\n methods,\n )\n : !(\n shouldRetry &&\n attempt < maxRetries &&\n (await shouldRetry(output, attempt))\n )\n ) {\n break;\n }\n\n // The delay before the next retry, randomized with jitter unless the server asks for one below\n let retryDelay = withJitter(waitTime, jitter);\n\n // Handle rate limiting if the error status is 429 (Too Many Requests) or 503 (Service Unavailable)\n if (error && (error.status === 429 || error.status === 503)) {\n // Try to extract the \"Retry-After\" value from the response headers\n const retryAfterMs = getRetryAfterMs(output);\n\n // If a valid retry-after value is found, override the wait time before next retry\n // Cap it with maxDelay so that a server can't make the client wait indefinitely\n if (retryAfterMs !== null) {\n retryDelay = waitTime = Math.min(\n retryAfterMs,\n maxDelay || retryAfterMs,\n );\n }\n }\n\n await delayInvocation(retryDelay);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n }\n\n return output!;\n}\n\n/**\n * Determines whether to stop retrying based on the error, current attempt count, and retry configuration.\n *\n * This function checks:\n * - If the maximum number of retries has been reached.\n * - If the request was aborted, e.g. with its signal or by a newer request. Aborted requests are never retried.\n * - If a custom `shouldRetry` callback is provided, its result is used to decide.\n * - If no custom logic is provided, falls back to checking if the error status is included in the `retryOn` list,\n * and the request method in the `methods` list, if any.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param output - The response object containing the error and request configuration.\n * @param attempt - The current retry attempt number.\n * @param maxRetries - The maximum number of retry attempts allowed.\n * @param shouldRetry - Optional custom function to determine if a retry should occur.\n * @param retryOn - Optional list of HTTP status codes that should trigger a retry.\n * @param methods - Optional list of request methods that are retried on the `retryOn` statuses. All methods are retried without it.\n * @returns A promise resolving to `true` if retrying should stop, or `false` to continue retrying.\n */\nexport async function getShouldStopRetrying<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n output: FetchResponse,\n attempt: number,\n maxRetries: number,\n shouldRetry?: RetryFunction<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n retryOn: number[] = [],\n methods?: string[],\n): Promise {\n // Safety first: always respect max retries\n // We check retries provided regardless of the shouldRetry being provided so to avoid infinite loops.\n // It is a fail-safe so to prevent excessive retry attempts even if custom retry logic suggests a retry.\n if (attempt === maxRetries) {\n return true;\n }\n\n // Aborted requests are never retried, as e.g. a retry of one cancelled by a newer request would cancel the newer one\n if (output.error?.isCancelled) {\n return true;\n }\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n\n if (result !== null) {\n return !result;\n }\n }\n\n return !(\n (retryOn || []).includes(output.error?.status ?? 0) &&\n (!methods ||\n methods.some((method) => method.toUpperCase() === output.config.method))\n );\n}\n\n/**\n * Randomizes a retry delay with jitter, so that clients that failed at the same time, e.g. during an outage, don't retry all at once.\n *\n * @param delay - The delay computed from the `delay`, `backoff` and `maxDelay` settings, in milliseconds.\n * @param jitter - `true` for a random delay between 0 and the computed one (\"full jitter\"), or a function that returns the delay to use.\n * @returns The delay to wait before the retry, in milliseconds.\n */\nfunction withJitter(delay: number, jitter: RetryConfig['jitter']): number {\n return typeof jitter === FUNCTION\n ? (jitter as (delay: number) => number)(delay)\n : jitter\n ? Math.random() * delay\n : delay;\n}\n","import type { RequestConfig, FetchResponse } from './types';\nimport { delayInvocation, isOffline, isPageHidden } from './utils';\n\n/**\n * Executes a request function with polling, stopping when shouldStopPolling returns true,\n * pollingInterval is not set, or maxAttempts is reached.\n * Polling pauses while the page is hidden or the browser is offline, unless allowed by refreshWhenHidden or refreshWhenOffline.\n *\n * @template Output The type of the output returned by the request function.\n * @param requestFn - The function that performs a single request (with retries).\n * @param pollingInterval - Interval in ms between polling attempts.\n * @param shouldStopPolling - Function to determine if polling should stop.\n * @param maxAttempts - Maximum number of polling attempts, default: 0 (unlimited).\n * @param pollingDelay - Delay in ms before each polling attempt, default: 0.\n * @param refreshWhenHidden - Whether to keep polling while the page is hidden, default: false.\n * @param refreshWhenOffline - Whether to keep polling while the browser is offline, default: false.\n * @param signal - The signal passed to the request. Polling stops once it is aborted.\n * @returns The final output from the last request.\n */\nexport async function withPolling<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation?: boolean,\n attempt?: number,\n ) => Promise<\n FetchResponse\n >,\n pollingInterval?: RequestConfig['pollingInterval'],\n shouldStopPolling?: RequestConfig['shouldStopPolling'],\n maxAttempts = 0,\n pollingDelay = 0,\n refreshWhenHidden = false,\n refreshWhenOffline = false,\n signal?: AbortSignal,\n): Promise> {\n if (!pollingInterval) {\n return requestFn();\n }\n\n let pollingAttempt = 0;\n let output: FetchResponse;\n\n while (maxAttempts === 0 || pollingAttempt < maxAttempts) {\n if (pollingDelay > 0) {\n await delayInvocation(pollingDelay, signal);\n }\n\n output = await requestFn();\n\n pollingAttempt++;\n\n if (\n (maxAttempts > 0 && pollingAttempt >= maxAttempts) ||\n !pollingInterval ||\n (shouldStopPolling && shouldStopPolling(output, pollingAttempt))\n ) {\n break;\n }\n\n // Wait for the next attempt, and keep waiting while polling is paused\n do {\n await delayInvocation(pollingInterval, signal);\n\n // Aborting the signal of the request stops polling\n if (signal && signal.aborted) {\n return output;\n }\n } while (\n (!refreshWhenHidden && isPageHidden()) ||\n (!refreshWhenOffline && isOffline())\n );\n }\n\n return output!;\n}\n","import { ABORT_ERROR, UNDEFINED } from './constants';\nimport type { RequestConfig, UploadProgress } from './types';\nimport { createAbortError } from './utils';\n\n// Responses with these statuses can't have a body\nconst NULL_BODY_STATUSES = [204, 205, 304];\n\n// Headers that browsers don't let requests set. fetch() skips them silently, while\n// XMLHttpRequest logs errors for them, so they are skipped before sending.\nconst FORBIDDEN_HEADERS =\n /^(accept-charset|accept-encoding|connection|content-length|cookie2?|date|dnt|expect|host|keep-alive|origin|referer|set-cookie|te|trailer|transfer-encoding|upgrade|via)$|^(proxy-|sec-|access-control-request-)/;\n\n// ReadableStream is missing in some environments, e.g. React Native\nconst isStream = (body: unknown): body is ReadableStream =>\n typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream;\n\nexport const toProgress = (loaded: number, total?: number): UploadProgress => ({\n loaded,\n total,\n progress: total ? loaded / total : undefined,\n});\n\n/**\n * Sends a request and reports the upload progress of its body to `onUploadProgress`.\n * Browsers and React Native don't report the upload progress of fetch(), so XMLHttpRequest is used there.\n * Elsewhere, e.g. in Node.js, the body is streamed with fetch() and counted while it is sent.\n *\n * @param {string} url - The request URL.\n * @param {RequestConfig} config - The request configuration, with a body and `onUploadProgress`.\n * @returns {Promise} - The response.\n */\nexport function fetchWithUploadProgress(\n url: string,\n config: RequestConfig,\n): Promise {\n const body = config.body as BodyInit;\n\n return typeof XMLHttpRequest !== UNDEFINED && !isStream(body)\n ? sendWithXhr(url, config, body)\n : sendStreamed(url, config, body);\n}\n\nfunction sendWithXhr(\n url: string,\n config: RequestConfig,\n body: BodyInit,\n): Promise {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n // fetchf() always sets the signal, as it handles timeouts and cancellation with it\n const signal = config.signal!;\n const abort = () => xhr.abort();\n\n const settle = (fn: () => void) => {\n signal.removeEventListener('abort', abort);\n\n try {\n fn();\n } catch (error) {\n reject(error);\n }\n };\n\n xhr.open(config.method as string, url);\n xhr.responseType = 'blob';\n xhr.withCredentials = config.credentials === 'include';\n\n new Headers(config.headers).forEach(\n (value, name) =>\n FORBIDDEN_HEADERS.test(name) || xhr.setRequestHeader(name, value),\n );\n\n xhr.upload.onprogress = (event) =>\n config.onUploadProgress!(\n toProgress(\n event.loaded,\n event.lengthComputable ? event.total : undefined,\n ),\n );\n\n xhr.onload = () =>\n settle(() => {\n const headers = new Headers();\n\n for (const line of xhr.getAllResponseHeaders().split(/\\r?\\n/)) {\n const index = line.indexOf(':');\n\n if (index > 0) {\n headers.append(line.slice(0, index), line.slice(index + 1).trim());\n }\n }\n\n const response = new Response(\n NULL_BODY_STATUSES.includes(xhr.status) ? null : xhr.response,\n { status: xhr.status, statusText: xhr.statusText, headers },\n );\n\n // Like fetch(), the response tells its final URL, e.g. after redirects\n Object.defineProperty(response, 'url', { value: xhr.responseURL });\n\n resolve(response);\n });\n\n xhr.onerror = () =>\n settle(() => reject(new TypeError('Network request failed')));\n\n // Like fetch(), aborted requests reject with the reason of the abort signal\n const onAbort = () =>\n settle(() =>\n reject(\n signal.reason ||\n createAbortError('The request was aborted', ABORT_ERROR),\n ),\n );\n\n xhr.onabort = onAbort;\n\n if (signal.aborted) {\n return onAbort();\n }\n\n signal.addEventListener('abort', abort);\n\n xhr.send(body as XMLHttpRequestBodyInit);\n });\n}\n\nasync function sendStreamed(\n url: string,\n config: RequestConfig,\n body: BodyInit,\n): Promise {\n const headers = new Headers(config.headers);\n let stream = body as ReadableStream;\n let total: number | undefined;\n\n if (!isStream(body)) {\n // Serialize the body like fetch() would, to know its size and content type\n const blob = body instanceof Blob ? body : await new Response(body).blob();\n\n total = blob.size;\n stream = blob.stream();\n\n if (blob.type && !headers.has('content-type')) {\n headers.set('content-type', blob.type);\n }\n }\n\n let loaded = 0;\n\n return fetch(url, {\n ...config,\n headers,\n body: stream.pipeThrough(\n new TransformStream({\n transform(chunk, controller) {\n loaded += chunk.byteLength;\n config.onUploadProgress!(toProgress(loaded, total));\n controller.enqueue(chunk);\n },\n }),\n ),\n // Required by fetch() to send a stream\n duplex: 'half',\n } as RequestInit);\n}\n","import { FUNCTION } from './constants';\nimport type { DownloadProgress } from './types';\nimport { toProgress } from './upload-progress';\n\n/**\n * Reports the download progress of a response body to `onDownloadProgress` while the body is read.\n * The body is counted as it arrives, so the progress follows the download.\n *\n * @param {T} response - The response. Other than native responses with a body, e.g. responses of HEAD requests or custom fetchers, are returned as they are.\n * @param {Function} [onDownloadProgress] - The function called with the progress. Without it, the response is returned as it is.\n * @returns {T} - A copy of the response, whose body is counted while it's read.\n */\nexport function withDownloadProgress(\n response: T,\n onDownloadProgress?: (progress: DownloadProgress) => void,\n): T {\n // Response is missing in some environments, and response bodies e.g. in React Native\n if (\n !onDownloadProgress ||\n typeof Response !== FUNCTION ||\n !(response instanceof Response) ||\n !response.body\n ) {\n return response;\n }\n\n const headers = response.headers;\n // Content-Length is the size of the compressed body, so the size of a compressed one is unknown\n const total = headers.has('content-encoding')\n ? undefined\n : Number(headers.get('content-length')) || undefined;\n let loaded = 0;\n\n const counted = new Response(\n response.body.pipeThrough(\n new TransformStream({\n transform(chunk, controller) {\n loaded += chunk.byteLength;\n // Browsers may hide the Content-Encoding header of cross-origin responses, so the progress is capped at 1\n onDownloadProgress(\n toProgress(loaded, total && Math.max(total, loaded)),\n );\n controller.enqueue(chunk);\n },\n }),\n ),\n response,\n );\n\n // Like the original response, the copy tells its final URL, whether it was redirected and its type\n for (const key of ['url', 'redirected', 'type'] as const) {\n Object.defineProperty(counted, key, { value: response[key] });\n }\n\n return counted as T;\n}\n","import type { ResponseError } from './errors/response-error';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n} from './types/request-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { handleResponseCache } from './cache-manager';\nimport { ABORT_ERROR, REJECT } from './constants';\nimport {\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n HeadersObject,\n} from './types';\nimport { processHeaders } from './utils';\n\n/**\n * Handles final processing for both success and error responses\n * Applies error interceptors, caching, notifications, and error strategy\n */\nexport async function withErrorHandling<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n isStaleRevalidation: boolean,\n requestFn: (\n isStaleRevalidation: boolean,\n ) => Promise<\n FetchResponse\n >,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): Promise> {\n const output = await requestFn(isStaleRevalidation);\n const error = output.error;\n\n if (!error) {\n // SUCCESS PATH\n handleResponseCache(output, requestConfig);\n\n return output;\n }\n\n // ERROR PATH\n\n if (requestConfig.onError) {\n await applyInterceptors(requestConfig.onError, error);\n }\n\n // Timeouts and request cancellations using AbortController do not throw any errors unless rejectCancelled is true.\n // Only handle the error if the request was not cancelled, or if it was cancelled and rejectCancelled is true.\n const isCancelled = error.isCancelled;\n\n const logger = requestConfig.logger;\n\n if (!isCancelled && logger && logger.warn) {\n logger.warn('FETCH ERROR', redactError(error as ResponseError));\n }\n\n // The defaultResponse strategy returns the default response in place of the error data.\n // The original data stays available through error.response.\n if (requestConfig.strategy === 'defaultResponse') {\n output.data = (requestConfig.defaultResponse ?? null) as typeof output.data;\n }\n\n // Handle cache and notifications FIRST (before strategy)\n handleResponseCache(output, requestConfig, true);\n\n // handle error strategy as the last part\n const shouldHandleError = !isCancelled || requestConfig.rejectCancelled;\n\n if (shouldHandleError) {\n const strategy = requestConfig.strategy;\n // Reject the promise\n if (strategy === REJECT) {\n throw error;\n }\n\n // Hang the promise\n if (strategy === 'silent') {\n await new Promise(() => null);\n }\n }\n\n return output;\n}\n\n// Credential headers that must not end up in logs\nconst SENSITIVE_HEADERS = [\n 'authorization',\n 'proxy-authorization',\n 'cookie',\n 'x-api-key',\n];\n\n/**\n * Creates a copy of the error for logging, with credential headers masked and the request body removed.\n * The error itself is left untouched.\n */\nfunction redactError(error: ResponseError): ResponseError {\n // Cache keys are dropped too, as they can contain short request bodies\n const config = {\n ...error.config,\n body: undefined,\n data: undefined,\n cacheKey: undefined,\n _prevKey: undefined,\n headers: processHeaders(error.config.headers as HeadersObject),\n };\n\n for (const name of SENSITIVE_HEADERS) {\n if (config.headers[name]) {\n config.headers[name] = '[REDACTED]';\n }\n }\n\n const copy = Object.assign(new Error(error.message), error, {\n config,\n request: config,\n response: error.response && { ...error.response, config },\n });\n\n copy.name = error.name;\n copy.stack = error.stack;\n\n return copy;\n}\n\nexport function enhanceError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): void {\n error.status = error.status || (response && response.status) || 0;\n error.statusText =\n error.statusText || (response && response.statusText) || '';\n error.config = error.request = requestConfig;\n error.response = response;\n error.isCancelled = error.name === ABORT_ERROR;\n}\n","import type {\n DefaultResponse,\n RequestConfig,\n FetchResponse,\n HeadersObject,\n} from './types/request-handler';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n} from './types/api-handler';\nimport type { StoredResponse } from './types/cache-manager';\nimport { applyInterceptors } from './interceptor-manager';\nimport { ResponseError } from './errors/response-error';\nimport { isObject, noop, processHeaders } from './utils';\nimport {\n markInFlight,\n setInFlightPromise,\n getInFlightPromise,\n} from './inflight-manager';\nimport { parseResponseData, prepareResponse } from './response-parser';\nimport {\n generateCacheKey,\n getCacheData,\n getCachedResponse,\n getStoredCache,\n isCacheBypassed,\n restoreCache,\n setCache,\n} from './cache-manager';\nimport { withRetry } from './retry-handler';\nimport { withPolling } from './polling-handler';\nimport { fetchWithUploadProgress } from './upload-progress';\nimport { withDownloadProgress } from './download-progress';\nimport { notifySubscribers } from './pubsub-manager';\nimport { addRevalidator } from './revalidator-manager';\nimport { enhanceError, withErrorHandling } from './error-handler';\nimport { FUNCTION, GET, HEAD } from './constants';\nimport { buildConfig } from './config-handler';\n\nconst inFlightResponse = Object.freeze({\n isFetching: true,\n});\n\n/**\n * Sends an HTTP request to the specified URL using the provided configuration and returns a typed response.\n *\n * @typeParam ResponseData - The expected shape of the response data. Defaults to `DefaultResponse`.\n * @typeParam RequestBody - The type of the request payload/body. Defaults to `DefaultPayload`.\n * @typeParam QueryParams - The type of the query parameters. Defaults to `DefaultParams`.\n * @typeParam PathParams - The type of the path parameters. Defaults to `DefaultUrlParams`.\n *\n * @param url - The endpoint URL to which the request will be sent.\n * @param config - Optional configuration object for the request, including headers, method, body, query, and path parameters.\n *\n * @returns A promise that resolves to a `FetchResponse` containing the typed response data and request metadata.\n *\n * @example\n * ```typescript\n * const { data } = await fetchf('/api/user', { method: 'GET' });\n * console.log(data);\n * ```\n */\nexport async function fetchf<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n): Promise> {\n // Ultra-fast early cache check if cacheKey is provided as a string\n // For workloads dominated by repeated requests, this string caching optimization\n // can potentially support millions of requests per second with minimal CPU overhead\n if (reqConfig && typeof reqConfig.cacheKey === 'string') {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(reqConfig.cacheKey, reqConfig.cacheTime, reqConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n const fetcherConfig = buildConfig<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(url, reqConfig);\n\n const {\n timeout,\n cancellable,\n cacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n refetchOnFocus,\n refetchOnReconnect,\n pollingInterval = 0,\n } = fetcherConfig;\n const isCacheEnabled = cacheTime !== undefined || staleTime !== undefined;\n const method = fetcherConfig.method;\n\n // Cached responses of GET and HEAD requests are revalidated with their ETag.\n // Custom fetchers may not handle 304 responses, so they only send it when it's enabled for them.\n const isETagEnabled =\n isCacheEnabled &&\n (method === GET || method === HEAD) &&\n (fetcherConfig.etag ?? !fetcherConfig.fetcher);\n\n const needsCacheKey = !!(\n cacheKey ||\n timeout ||\n dedupeTime ||\n isCacheEnabled ||\n cancellable ||\n refetchOnFocus ||\n refetchOnReconnect\n );\n\n let _cacheKey: string | null = null;\n\n // Generate cache key if required\n if (needsCacheKey) {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n // The initial data, which is used as the first response instead of sending the request\n let initialResponse: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n // Cache handling logic\n if (_cacheKey && isCacheEnabled) {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(_cacheKey, cacheTime, fetcherConfig);\n\n if (cached) {\n return cached;\n }\n\n // Restore the response from the cache store, e.g. one saved during a previous page load\n if (fetcherConfig.cacheStore) {\n const stored = await getStoredCache(_cacheKey, fetcherConfig);\n const restored =\n stored &&\n toResponse(\n stored.data,\n _cacheKey,\n fetcherConfig,\n );\n\n // A stale response is shown until the request below revalidates it\n if (\n restored &&\n restoreCache(\n _cacheKey,\n { ...stored, data: restored },\n fetcherConfig.cacheStore,\n )\n ) {\n return restored;\n }\n }\n\n // While there's no cached response, the initial data, e.g. data rendered on the server, is cached as the response\n if (\n fetcherConfig.initialData !== undefined &&\n !getCacheData(_cacheKey) &&\n !isCacheBypassed(fetcherConfig)\n ) {\n initialResponse = toResponse(\n {\n data: fetcherConfig.initialData,\n status: 200,\n statusText: '',\n headers: {},\n },\n _cacheKey,\n fetcherConfig,\n );\n }\n }\n\n // Deduplication logic\n if (_cacheKey && dedupeTime) {\n const inflight = getInFlightPromise<\n FetchResponse\n >(_cacheKey, dedupeTime);\n\n if (inflight) {\n return inflight;\n }\n }\n\n const retryConfig = fetcherConfig.retry || {};\n const { retries = 0, resetTimeout } = retryConfig;\n\n // The signal passed to the request. Each attempt replaces it in the config with a signal of its own.\n const userSignal = fetcherConfig.signal;\n\n // The actual request logic as a function (one poll attempt, with retries)\n const doRequestOnce = async (isStaleRevalidation: boolean, attempt = 0) => {\n // The cached response to revalidate. It's read before the cache is marked as fetching below.\n const cached =\n isETagEnabled &&\n getCacheData(\n _cacheKey,\n );\n\n // If cache key is specified, we will handle optimistic updates\n // and mark the request as in-flight, so to catch \"fetching\" state.\n // This is useful for Optimistic UI updates (e.g., showing loading spinners).\n if (!attempt) {\n // The initial data is only used once, as the first response\n if (initialResponse) {\n const response = initialResponse;\n\n initialResponse = null;\n\n return response;\n }\n\n if (_cacheKey && !isStaleRevalidation) {\n if (staleTime) {\n const existingCache = getCachedResponse(\n _cacheKey,\n cacheTime,\n fetcherConfig,\n );\n\n // Don't notify subscribers when cache exists\n // Let them continue showing stale data during background revalidation\n if (!existingCache) {\n setCache(_cacheKey, inFlightResponse, cacheTime, staleTime);\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n } else {\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n }\n\n // Attach cache key so that it can be reused in interceptors or in the final response\n fetcherConfig.cacheKey = _cacheKey;\n }\n\n const url = fetcherConfig.url as string;\n\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = markInFlight(\n _cacheKey,\n url,\n timeout,\n dedupeTime || 0,\n !!cancellable,\n // Enable timeout either by default or when retries & resetTimeout are enabled\n !!(timeout && (!attempt || resetTimeout)),\n );\n\n // Do not create a shallow copy to maintain idempotency here.\n // This ensures the original object is mutated by interceptors whenever needed, including retry logic.\n const requestConfig = fetcherConfig;\n\n requestConfig.signal = controller.signal;\n\n // The request is aborted along with the signal passed to it, which may have been aborted already\n const abort = () => controller.abort(userSignal!.reason);\n\n if (userSignal) {\n if (userSignal.aborted) {\n abort();\n } else {\n userSignal.addEventListener('abort', abort);\n }\n }\n\n let output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n let response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n try {\n if (fetcherConfig.onRequest) {\n // Zero-allocation yield to microtask queue so the outer fetchf() can call setInFlightPromise()\n // before onRequest interceptors run. This ensures that if onRequest triggers\n // another fetchf() with the same cacheKey, getInFlightPromise() finds item[4].\n // On retries (attempt > 0), setInFlightPromise() was already called during the first attempt.\n // The promise stored in item[4] is the outer doRequestPromise which covers all retries.\n // So the race only matters on the very first attempt when the outer scope hasn't had a chance to call setInFlightPromise() yet.\n if (_cacheKey && dedupeTime && !attempt) {\n await null;\n }\n\n await applyInterceptors(fetcherConfig.onRequest, requestConfig);\n }\n\n // Custom fetcher\n const fn = fetcherConfig.fetcher;\n const init = withETag(requestConfig, cached);\n\n response = (fn\n ? await fn(\n url,\n init,\n )\n : // Uploads with onUploadProgress are sent in a way that reports their progress\n await (requestConfig.onUploadProgress && requestConfig.body\n ? fetchWithUploadProgress(url, requestConfig)\n : fetch(url, init as RequestInit))) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Reports the download progress while the body is read\n response = withDownloadProgress(\n response,\n requestConfig.onDownloadProgress,\n );\n\n // Custom fetcher may return a raw data object instead of a Response instance\n if (isObject(response)) {\n // The server answered that the cached response is still valid, so it's reused instead of being sent again.\n // Like other cached responses, it has been parsed and transformed already.\n if (init !== requestConfig && response.status === 304) {\n return cached as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n // Case 1: Native Response instance\n if (typeof Response === FUNCTION && response instanceof Response) {\n response.data = requestConfig.parser\n ? await requestConfig.parser(response)\n : await parseResponseData(response, requestConfig.responseType);\n } else if (fn) {\n // Case 2: Custom fetcher that returns a response object\n if (!('data' in response && 'body' in response)) {\n // Case 3: Raw data, wrap it\n response = { data: response } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n }\n\n // Attach config and data to the response\n // This is useful for custom fetchers that do not return a Response instance\n // and for interceptors that may need to access the request config\n response.config = requestConfig;\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n // This is the pattern for fetch responses as per spec, but custom fetchers may not follow it so we check for `ok` property\n if (response.ok !== undefined && !response.ok) {\n throw new ResponseError(\n requestConfig.method +\n ' to ' +\n url +\n ' failed! Status: ' +\n (response.status || null),\n requestConfig,\n response,\n );\n }\n }\n\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig);\n\n const onResponse = fetcherConfig.onResponse;\n\n if (onResponse) {\n await applyInterceptors(onResponse, output);\n }\n } catch (_error) {\n const error = _error as ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Append additional information to Network, CORS or any other fetch() errors\n enhanceError(\n error,\n response,\n requestConfig,\n );\n\n // Prepare Extended Response\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig, error);\n } finally {\n if (userSignal) {\n userSignal.removeEventListener('abort', abort);\n }\n }\n\n return output;\n };\n\n // Inline and minimize function wrappers for performance\n // When retries are enabled, forward isStaleRevalidation so the first attempt\n // of a background SWR revalidation doesn't incorrectly mark the request as in-flight\n const baseRequest =\n retries > 0\n ? (isStaleRevalidation: boolean) =>\n withRetry(\n (_, attempt) => doRequestOnce(isStaleRevalidation, attempt),\n retryConfig,\n )\n : doRequestOnce;\n\n const { onLoadingSlow, loadingTimeout } = fetcherConfig;\n\n // Calls onLoadingSlow once a request, including its retries, is still pending after loadingTimeout.\n // Background revalidations don't show a loading state, so they are never considered slow.\n const request =\n onLoadingSlow && loadingTimeout\n ? async (isStaleRevalidation: boolean) => {\n if (isStaleRevalidation) {\n return baseRequest(isStaleRevalidation);\n }\n\n const timer = setTimeout(\n () => applyInterceptors(onLoadingSlow, fetcherConfig).catch(noop),\n loadingTimeout,\n );\n\n try {\n return await baseRequest(isStaleRevalidation);\n } finally {\n clearTimeout(timer);\n }\n }\n : baseRequest;\n\n const requestWithErrorHandling = (isStaleRevalidation = false) =>\n withErrorHandling(\n isStaleRevalidation,\n request,\n fetcherConfig,\n );\n\n // Avoid unnecessary function wrapping if polling is not enabled\n const doRequestPromise = pollingInterval\n ? withPolling(\n requestWithErrorHandling,\n pollingInterval,\n fetcherConfig.shouldStopPolling,\n fetcherConfig.maxPollingAttempts,\n fetcherConfig.pollingDelay,\n fetcherConfig.refreshWhenHidden,\n fetcherConfig.refreshWhenOffline,\n userSignal,\n )\n : requestWithErrorHandling();\n\n // If deduplication is enabled, store the in-flight promise immediately\n if (_cacheKey) {\n if (dedupeTime) {\n setInFlightPromise(_cacheKey, doRequestPromise);\n }\n\n // Only register revalidator when revalidation features are actually requested\n if (staleTime || refetchOnFocus || refetchOnReconnect) {\n addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\n fetcherConfig.focusThrottleInterval,\n );\n }\n }\n\n return doRequestPromise;\n}\n\n/**\n * Recreates a response from its copy in a cache store.\n * The data was transformed before it was stored, so it isn't transformed again.\n *\n * @param stored - The stored copy of the response.\n * @param cacheKey - The cache key of the request.\n * @param config - The request configuration.\n * @returns The response, or null if the stored copy is invalid, e.g. has an unknown status.\n */\nfunction toResponse(\n stored: StoredResponse,\n cacheKey: string,\n config: RequestConfig,\n): FetchResponse | null {\n try {\n // Without the Fetch API (e.g. with a custom fetcher in tests), a plain response object is used\n const response = (typeof Response === FUNCTION\n ? new Response(null, stored)\n : {\n ok: true,\n status: stored.status,\n statusText: stored.statusText,\n headers: stored.headers,\n }) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n response.data = stored.data as typeof response.data;\n config.cacheKey = cacheKey;\n\n const output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, {\n ...config,\n select: undefined,\n flattenResponse: false,\n defaultResponse: undefined,\n });\n\n output.config = config;\n\n return output;\n } catch {\n return null;\n }\n}\n\n/**\n * Asks the server whether a cached response is still valid, by sending its ETag in the If-None-Match header.\n * Then the server can answer 304 Not Modified instead of sending the response again.\n * Requests with an If-None-Match header of their own are sent as they are.\n *\n * @param config - The request configuration.\n * @param cached - The cached response of the request, if any.\n * @returns A copy of the configuration with the If-None-Match header, or the configuration itself if the cached response has no ETag.\n */\nfunction withETag(\n config: RequestConfig,\n cached: FetchResponse | null | false,\n): RequestConfig {\n const etag = cached && !cached.error && cached.headers && cached.headers.etag;\n const headers = etag && processHeaders(config.headers as HeadersObject);\n\n return headers && !headers['if-none-match']\n ? { ...config, headers: { ...headers, 'if-none-match': etag } }\n : config;\n}\n","import type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n RequestConfigUrlRequired,\n} from './types/api-handler';\nimport { fetchf } from '.';\nimport { mergeConfigs } from './config-handler';\nimport { hasOwn } from './utils';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if passed as \"fetcher\".\n * @see https://github.com/MattCCC/fetchff#configuration\n *\n * @param {Object} config - Configuration object for the API fetcher (see link above for full options).\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {string} [config.baseURL] - The base URL for the API.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\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 EndpointTypes extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n async function handleNonImplemented(endpointName: string): Promise {\n console.error('Add ' + endpointName + \" to 'endpoints'.\");\n\n return null;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\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 endpointName - The name of the API endpoint to call.\n * @param requestConfig - Additional configuration for the request.\n * @returns A promise that resolves with the response from the API provider.\n */\n async request(endpointName, requestConfig = {}) {\n // Use global and per-endpoint settings\n // Only own properties are endpoints, not ones inherited like \"constructor\"\n const endpointConfig = hasOwn(endpoints, endpointName as string)\n ? endpoints[endpointName]\n : undefined;\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // URL parsers ignore leading control characters and spaces, drop tabs and newlines,\n // and treat backslashes like slashes, so check the URL the way it will be resolved\n const resolvedUrl = url\n .replace(/[\\t\\n\\r]/g, '')\n // eslint-disable-next-line no-control-regex -- matching control characters is the point\n .replace(/^[\\x00-\\x20]+/, '');\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (/^[/\\\\]{2}/.test(resolvedUrl)) {\n throw new Error('Protocol-relative URLs not allowed.');\n }\n\n // Prevent potential Server-Side Request Forgery attack and leakage of credentials when same instance is used for external requests\n // Any scheme counts here, as e.g. \"http:\\\\host\" or \"http:host\" can also point to another host\n const mergedConfig = /^[a-z][a-z\\d+\\-.]*:/i.test(resolvedUrl)\n ? // Merge endpoints configs for absolute URLs only if urls match\n endpointConfig && endpointConfig.url === url\n ? mergeConfigs(_endpointConfig, requestConfig)\n : requestConfig\n : mergeConfigs(mergeConfigs(config, _endpointConfig), requestConfig);\n\n // We prevent potential Server-Side Request Forgery attack and leakage of credentials as the same instance is not used for external requests\n // Retrigger fetch to ensure completely new instance of handler being triggered for external URLs\n return fetchf(url, mergedConfig);\n },\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 | symbol) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Symbols (e.g. inspection hooks) are never endpoints, and returning a function\n // for \"then\" would make the instance a thenable that never settles when awaited\n if (typeof prop === 'symbol' || prop === 'then') {\n return undefined;\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (hasOwn(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"]} \ No newline at end of file diff --git a/dist/browser/index.mjs b/dist/browser/index.mjs index 2b25e5a..2e199a3 100644 --- a/dist/browser/index.mjs +++ b/dist/browser/index.mjs @@ -1,3 +1,3 @@ -var Pt=Object.defineProperty;var ht=(e,t,r)=>t in e?Pt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var q=(e,t,r)=>ht(e,typeof t!="symbol"?t+"":t,r);var N="application/",X=N+"json",Ne="charset=utf-8",B="Content-Type",E="undefined",Z="object",T="string",b="function",ie="AbortError",He="TimeoutError",H="GET",Me="HEAD",ue="reject",le=2147483647;var Le=10,A=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);function M(e){return e instanceof URLSearchParams}function y(e){return e!==null&&typeof e===Z}function w(e){let t=A(e,"__proto__"),r=A(e,"constructor"),a=A(e,"prototype");if(!t&&!r&&!a)return e;let n={};for(let s of Object.keys(e))s!=="__proto__"&&s!=="constructor"&&s!=="prototype"&&(n[s]=e[s]);return n}function je(e){let t=Object.create(null);return Object.keys(e).sort().forEach(r=>t[r]=e[r]),t}function Ue(e,t){return t?e+(e.includes("?")?"&":"?")+t:e}function Ke(e,t){if(!t)return e;if(M(t)){let c=t.toString();return Ue(e,c)}let r=[],a=encodeURIComponent,n=(c,u)=>{u=typeof u===b?u():u,u=u===null||u===void 0?"":u,r[r.length]=a(c)+"="+a(u);},s=(c,u,m=0)=>{if(m>=Le)return r;let l,d,h;if(c)if(Array.isArray(u))for(l=0,d=u.length;l{if(A(r,n)){let s=r[n];if(s!=null){let o=encodeURIComponent(String(s));if(o==="."||o==="..")throw new Error('Path params "." and ".." not allowed.');return o}}return a})}function ze(e){return /^[a-z][a-z\d+\-.]*:\/\//i.test(e)}var R=()=>Date.now(),U=()=>{};function V(e){let t=typeof e;return e==null?false:t===T||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==E&&typeof globalThis.Buffer!==E&&globalThis.Buffer.isBuffer(e)||e instanceof Date||M(e)?false:!!(y(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===b))}var L=e=>new Promise(t=>setTimeout(t,Math.min(e,le),true));function Ee(e,t=0){return t>=Le?e:e&&y(e)&&typeof e.data!==E?Ee(e.data,t+1):e}function x(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else for(let r in e)A(e,r)&&r!=="__proto__"&&(t[r.toLowerCase()]=e[r]);return t}function Je(){return typeof window!==E&&typeof window.addEventListener===b}function ce(e,t){if(typeof DOMException!==E)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var be=()=>{let e=typeof navigator!==E&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function O(e,t,...r){if(!e)return;let a=n=>n&&y(t)&&y(n)&&Object.assign(t,w(n));if(typeof e===b)a(await e(t,...r));else if(Array.isArray(e))for(let n of e)a(await n(t,...r));}var fe=class extends Error{constructor(r,a,n){super(r);q(this,"request",a);q(this,"response",n);q(this,"status");q(this,"statusText");q(this,"config");q(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var me=class extends fe{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ye=600,de=1e3,xe=Array(ye).fill(0).map(()=>[]),F=new Map,pe=0,Te=0,C=null,Ye=([e,t])=>{F.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(U);}catch(r){}},v=(e,t,r)=>{j(e);let a=r/de+(C&&R()!==Te?1:0);if(r=ye||r%de!==0){F.set(e,[setTimeout(Ye.bind(null,[e,t]),Math.min(r,le))]);return}let n=(pe+a)%ye;xe[n].push([e,t]),F.set(e,n),C||(Te=R(),C=setInterval(()=>{pe=(pe+1)%ye,Te=R();let s=xe[pe];for(let o=0;o{let t=F.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=xe[t];for(let a=0;a{We(e,ce(t+" aborted due to timeout",He));},r),u}async function We(e,t=null){if(e){let r=K.get(e);r&&(t&&r[0].abort(t),Re(e));}}function Re(e){j(e),K.delete(e);}function Xe(e,t){let r=K.get(e);r&&(r[4]=t);}function we(e,t){if(!e)return null;let r=K.get(e);return r&&r[4]&&!r[3]&&R()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(U);});}async function Pe(e,t=false){if(!e)return null;let r=J.get(e);if(r){r[1]=R();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function Dt(e){et(e);let t=e==="focus"?5:6;J.forEach((r,a)=>{r[t]&&Et(a);});}function Ce(e){if(z.has(e))return;let t=$e.bind(null,e,true),r=Ve.get(e);if(r){let a=r(t);z.set(e,a);return}Je()&&(window.addEventListener(e,t),z.set(e,()=>window.removeEventListener(e,t)));}function et(e){let t=z.get(e);t&&(t(),z.delete(e));}function tt(e,t,r,a,n,s,o){let i=J.get(e);i?(i[0]=t,i[1]=R(),i[2]=Ze,i[3]=a,i[4]=n,i[5]=s,i[6]=o):J.set(e,[t,R(),Ze,a,n,s,o]),s&&Ce("focus"),o&&Ce("online"),a&&v("s:"+e,Pe.bind(null,e,true),a*1e3);}function Et(e){J.delete(e),j("s:"+e);}var $=new Map;function bt(e,t){let r=$.get(e);r||$.set(e,r=new Set),r.add(t);}function Tt(e,t){let r=$.get(e);r&&(r.delete(t),r.size===0&&$.delete(e));}function Y(e,t){let r=$.get(e);if(r)if(r.size===1){let a=r.values().next().value;a(t);}else r.forEach(a=>a(t));}function xt(e,t){return e?(bt(e,t),()=>{Tt(e,t);}):U}var Ae=(be()?60:30)*1e3,S={strategy:ue,timeout:Ae,headers:{Accept:X+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:Ae/30,maxDelay:Ae,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function wt(e){let t=w(e);return G({retry:S.retry,headers:S.headers},t,S)}function Ct(){return {...S}}function qe(e,t){let r=G(S,t?w(t):{});return At(e,r)}function At(e,t){var m;let r=t.method;r=r?r.toUpperCase():H;let a;r!==H&&r!==Me&&(a=(m=t.body)!=null?m:t.data,a&&typeof a!==T&&V(a)&&(a=JSON.stringify(a))),It(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=ke(e,t.urlPathParams),o=Ke(s,t.params),c=ze(e)?"":t.baseURL||t.apiUrl||"",u=c&&o&&!c.endsWith("/")&&!/^[/?#]/.test(o)?"/":"";return t.url=c+u+o,t.method=r,t.credentials=n,t.body=a,t}function It(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==E&&t instanceof Blob||typeof File!==E&&t instanceof File||typeof ReadableStream!==E&&t instanceof ReadableStream)return;let r;if(M(t))r=N+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=N+"octet-stream";else if(V(t))r=X+";"+Ne;else return;e instanceof Headers?e.has(B)||e.set(B,r):y(e)&&!Array.isArray(e)&&!x(e)[B.toLowerCase()]&&(e[B]=r);}function G(e,t,r={}){return Object.assign(r,e,t),rt("retry",e,t,r),rt("headers",e,t,r),Ie("onRequest",e,t,r),Ie("onResponse",e,t,r),Ie("onError",e,t,r),r}function Ie(e,t,r,a){let n=t[e],s=r[e];if(!n&&!s)return;if(!n){a[e]=s;return}if(!s){a[e]=n;return}let o=Array.isArray(n)?n:[n],i=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?i.concat(o):o.concat(i);}function rt(e,t,r,a){let n=t[e],s=r[e];if(s)if(e==="headers"){let o=n instanceof Headers||s instanceof Headers,i=o?x(n):{...n},c=o?x(s):w(s);for(let u of Object.keys(c)){let m=u.toLowerCase();for(let l in i)l.toLowerCase()===m&&delete i[l];i[u]=c[u];}a[e]=i;}else a[e]={...n,...w(s)};else s===void 0&&y(n)&&!(n instanceof Headers)&&(a[e]={...n});}var he=new Map,I="|",Be=64,qt=/[^\w\-_|/:@.?=&~%#]/g,Bt=/[^\w\-_|/:@.?=&~%#]/,Ot=new Set(["accept","accept-language","accept-encoding","authorization","content-type","referer","origin","user-agent","cookie","x-api-key","x-requested-with","x-client-id","x-tenant-id","x-user-id","x-app-version","x-feature-flag","x-device-id","x-platform","x-session-id","x-locale"]);function te(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===T?r:r(e);let{url:a="",method:n=H,headers:s=null,body:o=null,credentials:i="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=x(s):l=s;let d=Object.keys(l),h=d.length;h>1&&d.sort();let f="";for(let D=0;D{u+=d+"="+(typeof l===T?l:"F"+st(l))+"&";}),u.length>Be&&(u=k(u));else if(y(o)&&!V(o))u="B"+st(o);else {let l=y(o)?JSON.stringify(je(o)):String(o);u=l.length>Be?k(l):l;}let m=n+I+a+I+i+I+c+I+u;return nt(m)}var at=new WeakMap,Ft=0;function st(e){let t=at.get(e);return t||at.set(e,t=++Ft),t}function nt(e){return Bt.test(e)?e.replace(qt,"")+I+k(e):e}function ot(e){return e.expiry?R()>e.expiry:false}function re(e){return he.get(e)}function ge(e,t,r,a){if(r===0){ee(e);return}let n=R(),s=r?r*1e3:0,o=a?a*1e3:0;he.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&v("c:"+e,()=>{ee(e,true);},s);}function ee(e,t=false){if(t){let r=re(e);if(!r||!ot(r))return}he.delete(e);}async function Oe(e,t,r){if(!e)return null;let a=re(e);if(!a)return null;let n=y(t)?w(t):t,s={...a.data,data:n},o={...a,data:s};return he.set(e,o),Y(e,s),r&&r.refetch?await Pe(e):null}function ae(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||S.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=re(e);if(!n)return null;if(ot(n))return ee(e),null;let o=n.data;return o&&o.isFetching?null:o}function Fe(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;if(n&&(!r||t.cacheErrors)&&!(s&&s(e,t)))ge(a,e,n,t.staleTime);else {let i=re(a);i&&i.data&&i.data.isFetching&&ee(a);}Y(a,e),Re(a);let o=t._prevKey;o&&Re(o);}}async function it(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(B);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(X)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(N+"x-www-form-urlencoded"))&&typeof e.formData===b)a=await e.formData();else if(/^(image|video|audio)\/|octet-stream|pdf|zip/.test(r))a=await e.arrayBuffer();else if(a=await e.text(),typeof a===T){let s=a.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{a=JSON.parse(s);}catch(o){}}}catch(s){a=null;}return a}var ve=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Oe.bind(null,n);if(!e)return {ok:false,error:r,data:a!=null?a:null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===b&&e instanceof Response,i=e.data;a!==void 0&&(i==null||typeof i===Z&&Object.keys(i).length===0)&&(e.data=i=a),t.flattenResponse&&(e.data=i=Ee(i)),t.select&&(e.data=i=t.select(i));let c=x(e.headers);if(o){let u={body:e.body,bodyUsed:e.bodyUsed,ok:e.ok,redirected:e.redirected,type:e.type,url:e.url,status:e.status,statusText:e.statusText,blob:()=>Promise.resolve(i instanceof ArrayBuffer?new Blob([i]):new Blob),json:()=>Promise.resolve(i),text:()=>Promise.resolve(i),clone:()=>({...u}),arrayBuffer:()=>Promise.resolve(i instanceof ArrayBuffer?i:new ArrayBuffer(0)),formData:()=>Promise.resolve(i instanceof FormData?i:new FormData),bytes:()=>Promise.resolve(new Uint8Array(i instanceof ArrayBuffer?i:new ArrayBuffer(0))),error:r,data:i,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r};return u}return y(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e};function ut(e){let t=Date.parse(e)-R();return isNaN(t)?null:Math.max(0,Math.floor(t))}function vt(e){if(!e)return null;let t=e.headers||{},r=t["retry-after"];if(r){let o=Number(r);if(!isNaN(o)&&o>=0)return o*1e3;let i=ut(r);if(i!==null)return i}let a="ratelimit-reset",n=t[a+"-after"]||t["x-"+a+"-after"];if(n){let o=Number(n);if(!isNaN(o))return o*1e3}let s=t[a+"-at"]||t["x-"+a+"-at"];return s?ut(s):null}async function lt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:i}=t,c=0,u=a,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await O(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=te(f,false)));}l=await e(c>0,c);let d=l.error;if(!d){if(i&&c0&&await L(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await L(t);return o}async function ft(e,t,r){var i,c;let a=await t(e),n=a.error;if(!n)return Fe(a,r),a;r.onError&&await O(r.onError,n);let s=n.isCancelled;if(!s&&((i=r.logger)!=null&&i.warn)&&r.logger.warn("FETCH ERROR",_t(n)),r.strategy==="defaultResponse"&&(a.data=(c=r.defaultResponse)!=null?c:null),Fe(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ue)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}var Qt=["authorization","proxy-authorization","cookie","x-api-key"];function _t(e){let t={...e.config,body:void 0,data:void 0,cacheKey:void 0,_prevKey:void 0,headers:x(e.config.headers)};for(let a of Qt)t.headers[a]&&(t.headers[a]="[REDACTED]");let r=Object.assign(new Error(e.message),e,{config:t,request:t,response:e.response&&{...e.response,config:t}});return r.name=e.name,r.stack=e.stack,r}function mt(e,t,r){e.status=e.status||(t==null?void 0:t.status)||0,e.statusText=e.statusText||(t==null?void 0:t.statusText)||"",e.config=e.request=r,e.response=t,e.isCancelled=e.name===ie;}var Se=Object.freeze({isFetching:true});async function De(e,t=null){if(t&&typeof t.cacheKey=="string"){let P=ae(t.cacheKey,t.cacheTime,t);if(P)return P}let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:i,staleTime:c,refetchOnFocus:u,refetchOnReconnect:m,pollingInterval:l=0}=r,d=i!==void 0||c!==void 0,h=!!(s||a||o||d||n||u||m),f=null;if(h&&(f=te(r)),f&&d){let P=ae(f,i,r);if(P)return P}if(f&&o){let P=we(f,o);if(P)return P}let D=r.retry||{},{retries:dt=0,resetTimeout:pt}=D,Qe=async(P,ne=0)=>{ne||(f&&!P&&(c?ae(f,i,r)||(ge(f,Se,i,c),Y(f,Se)):Y(f,Se)),r.cacheKey=f);let Q=r.url,Rt=Ge(f,Q,a,o||0,!!n,!!(a&&(!ne||pt))),g=r;g.signal=Rt.signal;let oe,p=null;try{r.onRequest&&(f&&o&&!ne&&await null,await O(r.onRequest,g));let _=r.fetcher;if(p=_?await _(Q,g):await fetch(Q,g),y(p)&&(typeof Response===b&&p instanceof Response?p.data=g.parser?await g.parser(p):await it(p):_&&("data"in p&&"body"in p||(p={data:p})),p.config=g,p.ok!==void 0&&!p.ok))throw new me(g.method+" to "+Q+" failed! Status: "+(p.status||null),g,p);oe=ve(p,g);let W=r.onResponse;W&&await O(W,oe);}catch(_){let W=_;mt(W,p,g),oe=ve(p,g,W);}return oe},yt=dt>0?P=>lt((ne,Q)=>Qe(P,Q),D):Qe,se=(P=false)=>ft(P,yt,r),_e=l?ct(se,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):se();return f&&(o&&Xe(f,_e),(c||u||m)&&tt(f,se,void 0,c,se,!!u,!!m)),_e}function Nt(e){let t=e.endpoints;function r(n){return console.error("Add "+n+" to 'endpoints'."),Promise.resolve(null)}let a={config:e,endpoints:t,async request(n,s={}){let o=A(t,n)?t[n]:void 0,i=o||{url:String(n)},c=i.url,u=c.replace(/[\t\n\r]/g,"").replace(/^[\x00-\x20]+/,"");if(/^[/\\]{2}/.test(u))throw new Error("Protocol-relative URLs not allowed.");let m=/^[a-z][a-z\d+\-.]*:/i.test(u)?(o==null?void 0:o.url)===c?G(i,s):s:G(G(e,i),s);return De(c,m)}};return new Proxy(a,{get(n,s){if(s in a)return a[s];if(!(typeof s=="symbol"||s==="then"))return A(t,s)?a.request.bind(null,s):r.bind(null,s)}})} -export{We as abortRequest,v as addTimeout,qe as buildConfig,ce as createAbortError,Nt as createApiFetcher,ee as deleteCache,De as fetchf,De as fetchff,te as generateCacheKey,re as getCache,ae as getCachedResponse,Ct as getDefaultConfig,we as getInFlightPromise,be as isSlowConnection,Oe as mutate,Dt as removeRevalidators,Pe as revalidate,$e as revalidateAll,ge as setCache,wt as setDefaultConfig,gt as setEventProvider,xt as subscribe};//# sourceMappingURL=index.mjs.map +var z="application/",te=z+"json",et="charset=utf-8",_="Content-Type",D="undefined",Ie="object",x="string",b="function",k="AbortError",tt="TimeoutError",O="GET",re="HEAD",pe="reject",ye=2147483647;var st=10,S=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);function J(e){return e instanceof URLSearchParams}function g(e){return e!==null&&typeof e===Ie}function B(e){let t=S(e,"__proto__"),r=S(e,"constructor"),s=S(e,"prototype");if(!t&&!r&&!s)return e;let n={};for(let a of Object.keys(e))a!=="__proto__"&&a!=="constructor"&&a!=="prototype"&&(n[a]=e[a]);return n}function at(e){let t=Object.create(null);return Object.keys(e).sort().forEach(r=>t[r]=e[r]),t}function rt(e,t){return t?e+(e.includes("?")?"&":"?")+t:e}function nt(e,t){if(!t)return e;if(J(t)){let u=t.toString();return rt(e,u)}let r=[],s=encodeURIComponent,n=(u,c)=>{c=typeof c===b?c():c,c=c==null?"":c,r[r.length]=s(u)+"="+s(c);},a=(u,c,f=0)=>{if(f>=st)return r;let l,p,m;if(u)if(Array.isArray(c))for(l=0,p=c.length;l{let o=n||a;if(S(r,o)){let i=r[o];if(i!=null){let u=encodeURIComponent(String(i));if(u==="."||u==="..")throw new Error('Path params "." and ".." not allowed.');return u}}return s})}function it(e){return /^[a-z][a-z\d+\-.]*:\/\//i.test(e)}var h=()=>Date.now(),C=()=>{};function se(e){let t=typeof e;return e==null?false:t===x||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==D&&typeof globalThis.Buffer!==D&&globalThis.Buffer.isBuffer(e)||e instanceof Date||J(e)?false:!!(g(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===b))}var ae=(e,t)=>new Promise(r=>{let s=()=>{clearTimeout(n),t&&t.removeEventListener("abort",s),r(true);},n=setTimeout(s,Math.min(e,ye));t&&(t.aborted?s():t.addEventListener("abort",s));});function ve(e,t=0){return t>=st?e:e&&g(e)&&typeof e.data!==D?ve(e.data,t+1):e}function E(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,s)=>{t[s.toLowerCase()]=r;});else for(let r in e)S(e,r)&&r!=="__proto__"&&(t[r.toLowerCase()]=e[r]);return t}function ut(){return typeof window!==D&&typeof window.addEventListener===b}function W(e,t){if(typeof DOMException!==D)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Se=()=>{let e=typeof navigator!==D&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)},ct=()=>typeof document!==D&&document.visibilityState==="hidden",lt=()=>typeof navigator!==D&&navigator.onLine===false;async function F(e,t,...r){if(!e)return;let s=n=>n&&g(t)&&g(n)&&Object.assign(t,B(n));if(typeof e===b)s(await e(t,...r));else if(Array.isArray(e))for(let n of e)s(await n(t,...r));}var Re=class extends Error{constructor(t,r,s){super(t),this.request=r,this.response=s,this.status=s?s.status:0,this.statusText=s?s.statusText:"",this.config=r,this.isCancelled=false,this.name="FetchError";}};var he=class extends Re{constructor(t,r,s){super(t,r,s),this.name="ResponseError";}};var be=600,Pe=1e3,Qe=Array(be).fill(0).map(()=>[]),U=new Map,ge=0,Fe=0,A=null,ft=([e,t])=>{U.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(C);}catch(r){}},M=(e,t,r)=>{Y(e);let s=r/Pe+(A&&h()!==Fe?1:0);if(r=be||r%Pe!==0){U.set(e,[setTimeout(ft.bind(null,[e,t]),Math.min(r,ye))]);return}let n=(ge+s)%be;Qe[n].push([e,t]),U.set(e,n),A||(Fe=h(),A=setInterval(()=>{ge=(ge+1)%be,Fe=h();let a=Qe[ge];for(let o=0;o{let t=U.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Qe[t];for(let s=0;s{mt(e,W(t+" aborted due to timeout",tt));},r),c}async function mt(e,t=null){if(e){let r=G.get(e);r&&(t&&r[0].abort(t),De(e));}}function De(e){Y(e),G.delete(e);}function pt(e,t){let r=G.get(e);r&&(r[4]=t);}function He(e,t){if(!e)return null;let r=G.get(e);return r&&r[4]&&!r[3]&&h()-r[2]{if(!a[s]||r&&n-a[1]{r[t]&&Kt(s);});}function Ne(e){if(V.has(e))return;let t=Rt.bind(null,e,true,e==="focus"),r=yt.get(e);if(r){let s=r(t);V.set(e,s);return}ut()&&(window.addEventListener(e,t),V.set(e,()=>window.removeEventListener(e,t)));}function ht(e){let t=V.get(e);t&&(t(),V.delete(e));}function Pt(e,t,r,s,n,a,o,i){let u=Z.get(e)||[];u[0]=t,u[1]=h(),u[2]=Mt,u[3]=s,u[4]=n,u[5]=a,u[6]=o,u[7]=i,Z.set(e,u),a&&Ne("focus"),o&&Ne("online"),s&&M("s:"+e,Ee.bind(null,e,true),s*1e3);}function Kt(e){Z.delete(e),Y("s:"+e);}var ne=new Map;function zt(e,t){let r=ne.get(e);r||ne.set(e,r=new Set),r.add(t);}function kt(e,t){let r=ne.get(e);r&&(r.delete(t),r.size===0&&ne.delete(e));}function L(e,t){let r=ne.get(e);if(r)if(r.size===1){let s=r.values().next().value;s(t);}else r.forEach(s=>s(t));}function Jt(e,t){return e?(zt(e,t),()=>{kt(e,t);}):C}var Te=(Se()?60:30)*1e3,j={strategy:pe,timeout:Te,loadingTimeout:Te/10,focusThrottleInterval:5e3,headers:{Accept:te+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:Te/30,maxDelay:Te,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504],methods:[O,re,"PUT","DELETE","OPTIONS","TRACE"]}};function Wt(e){let t=B(e);return $({retry:j.retry,headers:j.headers},t,j)}function Yt(){return {...j}}function _e(e,t){let r=$(j,t?B(t):{});return Gt(e,r)}function Gt(e,t){var f;let r=t.method;r=r?r.toUpperCase():O;let s;r!==O&&r!==re&&(s=(f=t.body)!=null?f:t.data,s&&typeof s!==x&&se(s)&&(s=JSON.stringify(s))),Xt(t.headers,s);let n=t.withCredentials?"include":t.credentials,a=ot(e,t.urlPathParams),o=nt(a,t.params),u=it(e)?"":t.baseURL||t.apiUrl||"",c=u&&o&&!u.endsWith("/")&&!/^[/?#]/.test(o)?"/":"";return t.url=u+c+o,t.method=r,t.credentials=n,t.body=s,t}function Xt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==D&&t instanceof Blob||typeof ReadableStream!==D&&t instanceof ReadableStream)return;let r;if(J(t))r=z+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=z+"octet-stream";else if(se(t))r=te+";"+et;else return;e instanceof Headers?e.has(_)||e.set(_,r):g(e)&&!Array.isArray(e)&&!E(e)[_.toLowerCase()]&&(e[_]=r);}var Vt=["onRequest","onResponse","onError","onLoadingSlow"];function $(e,t,r={}){Object.assign(r,e,t),gt("retry",e,t,r),gt("headers",e,t,r);for(let s of Vt)Zt(s,e,t,r);return r}function Zt(e,t,r,s){let n=t[e],a=r[e];n&&a?s[e]=e==="onResponse"?[].concat(a,n):[].concat(n,a):(n||a)&&(s[e]=n||a);}function gt(e,t,r,s){let n=t[e],a=r[e];if(a)if(e==="headers"){let o=n instanceof Headers||a instanceof Headers,i=o?E(n):{...n},u=o?E(a):B(a);for(let c of Object.keys(u)){let f=c.toLowerCase();for(let l in i)l.toLowerCase()===f&&delete i[l];i[c]=u[c];}s[e]=i;}else s[e]={...n,...B(a)};else a===void 0&&g(n)&&!(n instanceof Headers)&&(s[e]={...n});}var Q=new Map,ie=new Map,oe="|",Ue=64,$t=/[^\w\-_|/:@.?=&~%#]/g,er=/[^\w\-_|/:@.?=&~%#]/,tr=/^(accept(-language|-encoding)?|authorization|content-type|referer|origin|user-agent|cookie|x-(api-key|requested-with|client-id|tenant-id|user-id|app-version|feature-flag|device-id|platform|session-id|locale))$/i;function ue(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===x?r:r(e);let{url:s="",method:n=O,headers:a=null,body:o=null,credentials:i="same-origin"}=e,u="";if(a){let l;a instanceof Headers?l=E(a):l=a;let p=Object.keys(l),m=p.length;m>1&&p.sort();let q="";for(let T=0;T{f+=p+"="+(typeof l===x?l:"F"+Dt(l))+"&";}),f.length>Ue&&(f=X(f));else if(g(o)&&!se(o))f="B"+Dt(o);else {let l=g(o)?JSON.stringify(at(o)):String(o);f=l.length>Ue?X(l):l;}return Et(c+oe+f)}var bt=new WeakMap,rr=0;function Dt(e){let t=bt.get(e);return t||bt.set(e,t=++rr),t}function Et(e){return er.test(e)?e.replace($t,"")+oe+X(e):e}function Me(e){return e.expiry?h()>e.expiry:false}function Le(e){if(!e)return null;let t=Q.get(e);return t?t.data:null}function ce(e){return Q.get(e)}function we(e,t,r,s){if(r===0){le(e);return}let n=h(),a=r?r*1e3:0,o=s?s*1e3:0;Q.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+a}),a>0&&Tt(e,a);}function Tt(e,t){M("c:"+e,()=>le(e,true),t);}function le(e,t=false){if(t){let s=ce(e);if(!s||!Me(s))return}Q.delete(e);let r=ie.get(e);r&&(ie.delete(e),je(()=>r.delete(e)));}function je(e){try{Promise.resolve(e()).catch(C);}catch(t){}}function wt(e,t){let r=Q.get(e);if(t&&r){let{data:s,status:n,statusText:a,headers:o}=r.data;ie.set(e,t),je(()=>t.set(e,{...r,data:{data:s,status:n,statusText:a,headers:o}}));}}async function xt(e,t){let r=t.cacheStore;if(!r||xe(t))return null;let s;try{s=await r.get(e);}catch(n){return null}return !s||Q.has(e)?null:Me(s)?(je(()=>r.delete(e)),null):s}function Ct(e,t,r){return Q.set(e,t),ie.set(e,r),t.expiry&&Tt(e,t.expiry-h()),L(e,t.data),!t.stale||h(){let s=t.defaultResponse,n=t.cacheKey,a=Ke.bind(null,n);if(!e)return {ok:false,error:r,data:s!=null?s:null,headers:null,config:t,mutate:a,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===b&&e instanceof Response,i=e.data;s!==void 0&&(i==null||/^\[object (Object|Array)\]$/.test(Object.prototype.toString.call(i))&&Object.keys(i).length===0)&&(e.data=i=s),t.flattenResponse&&(e.data=i=ve(i)),t.select&&(e.data=i=t.select(i));let u=E(e.headers);if(o){let c={body:e.body,bodyUsed:e.bodyUsed,ok:e.ok,redirected:e.redirected,type:e.type,url:e.url,status:e.status,statusText:e.statusText,blob:async()=>i instanceof ArrayBuffer?new Blob([i]):new Blob,json:async()=>i,text:async()=>i,clone:()=>({...c}),arrayBuffer:async()=>i instanceof ArrayBuffer?i:new ArrayBuffer(0),formData:async()=>i instanceof FormData?i:new FormData,bytes:async()=>new Uint8Array(i instanceof ArrayBuffer?i:new ArrayBuffer(0)),error:r,data:i,headers:u,config:t,mutate:a,isFetching:false,isSuccess:e.ok&&!r,isError:!!r};return c}return g(e)&&(e.error=r,e.headers=u,e.isFetching=false,e.mutate=a,e.isSuccess=e.ok&&!r,e.isError=!!r),e};function Ot(e){let t=Date.parse(e)-h();return isNaN(t)?null:Math.max(0,Math.floor(t))}function sr(e){if(!e)return null;let t=e.headers||{},r=t["retry-after"];if(r){let o=Number(r);if(!isNaN(o)&&o>=0)return o*1e3;let i=Ot(r);if(i!==null)return i}let s="ratelimit-reset",n=t[s+"-after"]||t["x-"+s+"-after"];if(n){let o=Number(n);if(!isNaN(o))return o*1e3}let a=t[s+"-at"]||t["x-"+s+"-at"];return a?Ot(a):null}async function Bt(e,t){let{retries:r=0,delay:s=0,backoff:n=1,maxDelay:a,retryOn:o=[],shouldRetry:i,jitter:u,methods:c}=t,f=0,l=s,p=r>0?r:0,m;for(;f<=p;){if(f>0&&m){let d=m.config,H=d.onRetry;H&&(await F(H,m,f),d._isAutoKey&&(d._prevKey=d.cacheKey,d.cacheKey=ue(d,false)));}m=await e(f>0,f);let q=m.error;if(q?await ar(m,f,p,i,o,c):!(i&&fc.toUpperCase()===e.config.method)))}function nr(e,t){return typeof t===b?t(e):t?Math.random()*e:e}async function At(e,t,r,s=0,n=0,a=false,o=false,i){if(!t)return e();let u=0,c;for(;(s===0||u0&&await ae(n,i),c=await e(),u++,!(s>0&&u>=s||!t||r&&r(c,u)));)do if(await ae(t,i),i&&i.aborted)return c;while(!a&&ct()||!o&<());return c}var or=[204,205,304],ir=/^(accept-charset|accept-encoding|connection|content-length|cookie2?|date|dnt|expect|host|keep-alive|origin|referer|set-cookie|te|trailer|transfer-encoding|upgrade|via)$|^(proxy-|sec-|access-control-request-)/,It=e=>typeof ReadableStream!==D&&e instanceof ReadableStream,qe=(e,t)=>({loaded:e,total:t,progress:t?e/t:void 0});function vt(e,t){let r=t.body;return typeof XMLHttpRequest!==D&&!It(r)?ur(e,t,r):cr(e,t,r)}function ur(e,t,r){return new Promise((s,n)=>{let a=new XMLHttpRequest,o=t.signal,i=()=>a.abort(),u=f=>{o.removeEventListener("abort",i);try{f();}catch(l){n(l);}};a.open(t.method,e),a.responseType="blob",a.withCredentials=t.credentials==="include",new Headers(t.headers).forEach((f,l)=>ir.test(l)||a.setRequestHeader(l,f)),a.upload.onprogress=f=>t.onUploadProgress(qe(f.loaded,f.lengthComputable?f.total:void 0)),a.onload=()=>u(()=>{let f=new Headers;for(let p of a.getAllResponseHeaders().split(/\r?\n/)){let m=p.indexOf(":");m>0&&f.append(p.slice(0,m),p.slice(m+1).trim());}let l=new Response(or.includes(a.status)?null:a.response,{status:a.status,statusText:a.statusText,headers:f});Object.defineProperty(l,"url",{value:a.responseURL}),s(l);}),a.onerror=()=>u(()=>n(new TypeError("Network request failed")));let c=()=>u(()=>n(o.reason||W("The request was aborted",k)));if(a.onabort=c,o.aborted)return c();o.addEventListener("abort",i),a.send(r);})}async function cr(e,t,r){let s=new Headers(t.headers),n=r,a;if(!It(r)){let i=r instanceof Blob?r:await new Response(r).blob();a=i.size,n=i.stream(),i.type&&!s.has("content-type")&&s.set("content-type",i.type);}let o=0;return fetch(e,{...t,headers:s,body:n.pipeThrough(new TransformStream({transform(i,u){o+=i.byteLength,t.onUploadProgress(qe(o,a)),u.enqueue(i);}})),duplex:"half"})}function St(e,t){if(!t||typeof Response!==b||!(e instanceof Response)||!e.body)return e;let r=e.headers,s=r.has("content-encoding")?void 0:Number(r.get("content-length"))||void 0,n=0,a=new Response(e.body.pipeThrough(new TransformStream({transform(o,i){n+=o.byteLength,t(qe(n,s&&Math.max(s,n))),i.enqueue(o);}})),e);for(let o of ["url","redirected","type"])Object.defineProperty(a,o,{value:e[o]});return a}async function Ft(e,t,r){var u;let s=await t(e),n=s.error;if(!n)return ze(s,r),s;r.onError&&await F(r.onError,n);let a=n.isCancelled,o=r.logger;if(!a&&o&&o.warn&&o.warn("FETCH ERROR",fr(n)),r.strategy==="defaultResponse"&&(s.data=(u=r.defaultResponse)!=null?u:null),ze(s,r,true),!a||r.rejectCancelled){let c=r.strategy;if(c===pe)throw n;c==="silent"&&await new Promise(()=>null);}return s}var lr=["authorization","proxy-authorization","cookie","x-api-key"];function fr(e){let t={...e.config,body:void 0,data:void 0,cacheKey:void 0,_prevKey:void 0,headers:E(e.config.headers)};for(let s of lr)t.headers[s]&&(t.headers[s]="[REDACTED]");let r=Object.assign(new Error(e.message),e,{config:t,request:t,response:e.response&&{...e.response,config:t}});return r.name=e.name,r.stack=e.stack,r}function Qt(e,t,r){e.status=e.status||t&&t.status||0,e.statusText=e.statusText||t&&t.statusText||"",e.config=e.request=r,e.response=t,e.isCancelled=e.name===k;}var ke=Object.freeze({isFetching:true});async function Oe(e,t=null){var Ve;if(t&&typeof t.cacheKey=="string"){let R=fe(t.cacheKey,t.cacheTime,t);if(R)return R}let r=_e(e,t),{timeout:s,cancellable:n,cacheKey:a,dedupeTime:o,cacheTime:i,staleTime:u,refetchOnFocus:c,refetchOnReconnect:f,pollingInterval:l=0}=r,p=i!==void 0||u!==void 0,m=r.method,q=p&&(m===O||m===re)&&((Ve=r.etag)!=null?Ve:!r.fetcher),T=!!(a||s||o||p||n||c||f),d=null;T&&(d=ue(r));let H=null;if(d&&p){let R=fe(d,i,r);if(R)return R;if(r.cacheStore){let w=await xt(d,r),I=w&&Ht(w.data,d,r);if(I&&Ct(d,{...w,data:I},r.cacheStore))return I}r.initialData!==void 0&&!Le(d)&&!xe(r)&&(H=Ht({data:r.initialData,status:200,statusText:"",headers:{}},d,r));}if(d&&o){let R=He(d,o);if(R)return R}let Je=r.retry||{},{retries:Nt=0,resetTimeout:_t}=Je,N=r.signal,We=async(R,w=0)=>{let I=q&&Le(d);if(!w){if(H){let v=H;return H=null,v}d&&!R&&(u?fe(d,i,r)||(we(d,ke,i,u),L(d,ke)):L(d,ke)),r.cacheKey=d;}let ee=r.url,Ze=dt(d,ee,s,o||0,!!n,!!(s&&(!w||_t))),P=r;P.signal=Ze.signal;let Ae=()=>Ze.abort(N.reason);N&&(N.aborted?Ae():N.addEventListener("abort",Ae));let me,y=null;try{r.onRequest&&(d&&o&&!w&&await null,await F(r.onRequest,P));let v=r.fetcher,K=dr(P,I);if(y=v?await v(ee,K):await(P.onUploadProgress&&P.body?vt(ee,P):fetch(ee,K)),y=St(y,P.onDownloadProgress),g(y)){if(K!==P&&y.status===304)return I;if(typeof Response===b&&y instanceof Response?y.data=P.parser?await P.parser(y):await qt(y,P.responseType):v&&("data"in y&&"body"in y||(y={data:y})),y.config=P,y.ok!==void 0&&!y.ok)throw new he(P.method+" to "+ee+" failed! Status: "+(y.status||null),P,y)}me=Ce(y,P);let $e=r.onResponse;$e&&await F($e,me);}catch(v){let K=v;Qt(K,y,P),me=Ce(y,P,K);}finally{N&&N.removeEventListener("abort",Ae);}return me},Be=Nt>0?R=>Bt((w,I)=>We(R,I),Je):We,{onLoadingSlow:Ye,loadingTimeout:Ge}=r,Ut=Ye&&Ge?async R=>{if(R)return Be(R);let w=setTimeout(()=>F(Ye,r).catch(C),Ge);try{return await Be(R)}finally{clearTimeout(w);}}:Be,de=(R=false)=>Ft(R,Ut,r),Xe=l?At(de,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay,r.refreshWhenHidden,r.refreshWhenOffline,N):de();return d&&(o&&pt(d,Xe),(u||c||f)&&Pt(d,de,void 0,u,de,!!c,!!f,r.focusThrottleInterval)),Xe}function Ht(e,t,r){try{let s=typeof Response===b?new Response(null,e):{ok:!0,status:e.status,statusText:e.statusText,headers:e.headers};s.data=e.data,r.cacheKey=t;let n=Ce(s,{...r,select:void 0,flattenResponse:!1,defaultResponse:void 0});return n.config=r,n}catch(s){return null}}function dr(e,t){let r=t&&!t.error&&t.headers&&t.headers.etag,s=r&&E(e.headers);return s&&!s["if-none-match"]?{...e,headers:{...s,"if-none-match":r}}:e}function mr(e){let t=e.endpoints;async function r(n){return console.error("Add "+n+" to 'endpoints'."),null}let s={config:e,endpoints:t,async request(n,a={}){let o=S(t,n)?t[n]:void 0,i=o||{url:String(n)},u=i.url,c=u.replace(/[\t\n\r]/g,"").replace(/^[\x00-\x20]+/,"");if(/^[/\\]{2}/.test(c))throw new Error("Protocol-relative URLs not allowed.");let f=/^[a-z][a-z\d+\-.]*:/i.test(c)?o&&o.url===u?$(i,a):a:$($(e,i),a);return Oe(u,f)}};return new Proxy(s,{get(n,a){if(a in s)return s[a];if(!(typeof a=="symbol"||a==="then"))return S(t,a)?s.request.bind(null,a):r.bind(null,a)}})} +export{mt as abortRequest,M as addTimeout,_e as buildConfig,W as createAbortError,mr as createApiFetcher,le as deleteCache,Oe as fetchf,Oe as fetchff,ue as generateCacheKey,ce as getCache,fe as getCachedResponse,Yt as getDefaultConfig,He as getInFlightPromise,Se as isSlowConnection,Ke as mutate,jt as removeRevalidators,Ee as revalidate,Rt as revalidateAll,we as setCache,Wt as setDefaultConfig,Lt as setEventProvider,Jt as subscribe};//# sourceMappingURL=index.mjs.map //# 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 1e6b047..dc38332 100644 --- a/dist/browser/index.mjs.map +++ b/dist/browser/index.mjs.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/constants.ts","../../src/utils.ts","../../src/interceptor-manager.ts","../../src/errors/fetch-error.ts","../../src/errors/response-error.ts","../../src/timeout-wheel.ts","../../src/inflight-manager.ts","../../src/hash.ts","../../src/revalidator-manager.ts","../../src/pubsub-manager.ts","../../src/config-handler.ts","../../src/cache-manager.ts","../../src/response-parser.ts","../../src/retry-handler.ts","../../src/polling-handler.ts","../../src/error-handler.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"names":["APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CHARSET_UTF_8","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","FUNCTION","ABORT_ERROR","TIMEOUT_ERROR","GET","HEAD","REJECT","MAX_DELAY_MS","MAX_DEPTH","hasOwn","o","k","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","key","sortObject","sortedObj","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","v","buildParams","prefix","depth","i","len","replaceUrlPathParams","urlPathParams","match","encoded","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","merge","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","wheel","keyMap","position","lastTick","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","customEventProviders","setEventProvider","type","provider","removeEventHandler","addEventHandler","revalidateAll","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeRevalidator","event","handler","customProvider","cleanup","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","existing","listeners","addListener","fn","set","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","merged","buildFetcherConfig","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","separator","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","isInstance","overrides","lowerKey","existingKey","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","keys","cacheStr","sanitizeCacheKey","bodyString","getObjectId","objectIds","lastObjectId","id","isCacheExpired","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","handleResponseCache","output","isError","skipCache","prevCacheKey","parseResponseData","contentType","mimeType","trimmed","_error","prepareResponse","defaultResponse","mutatator","isNativeResponse","getMsFromHttpDate","dateString","getRetryAfterMs","extendedResponse","retryAfter","RATELIMIT_RESET","rateLimitResetAfter","rateLimitResetAt","withRetry","requestFn","retries","delay","backoff","maxDelay","retryOn","shouldRetry","attempt","waitTime","maxRetries","cfg","onRetry","getShouldStopRetrying","retryAfterMs","_b","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","redactError","strategy","SENSITIVE_HEADERS","copy","enhanceError","inFlightResponse","fetchf","cached","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","resolvedUrl","mergedConfig","_target","prop"],"mappings":"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","file":"index.mjs","sourcesContent":["export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CHARSET_UTF_8 = 'charset=utf-8';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\nexport const FUNCTION = 'function';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n\nexport const REJECT = 'reject';\n\n// Larger timer delays overflow and fire immediately in browsers and Node.js (~24.8 days)\nexport const MAX_DELAY_MS = 2147483647;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, MAX_DELAY_MS, OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\n// Prevent stack overflow with recursion depth limit\nconst MAX_DEPTH = 10;\n\nexport const hasOwn = (o: any, k: string) =>\n Object.prototype.hasOwnProperty.call(o, k);\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 (hasOwn(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function checks for dangerous properties like '__proto__', 'constructor',\n * and 'prototype'. If none are present, the object is returned as-is (zero-copy fast path).\n * Otherwise, a shallow copy is created with the dangerous properties removed.\n *\n * @param obj - The object to sanitize\n * @returns A safe object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const hasProto = hasOwn(obj, '__proto__');\n const hasCtor = hasOwn(obj, 'constructor');\n const hasPrototype = hasOwn(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n // Copy key by key, as a spread compiled to assignments would let \"__proto__\" set the prototype\n const safeObj = {} as Record;\n\n for (const key of Object.keys(obj)) {\n if (key !== '__proto__' && key !== 'constructor' && key !== 'prototype') {\n safeObj[key] = obj[key];\n }\n }\n\n return safeObj as T;\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 // Without a prototype, a \"__proto__\" key is kept as a regular property instead of setting the prototype\n const sortedObj = Object.create(null) as Record;\n\n Object.keys(obj)\n .sort()\n .forEach((k) => (sortedObj[k] = obj[k]));\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 + (baseUrl.includes('?') ? '&' : '?') + 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, depth = 0) => {\n // Stop recursion if maximum depth is reached\n if (depth >= MAX_DEPTH) {\n return s;\n }\n\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 depth + 1,\n );\n }\n } else if (isObject(obj)) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key], depth + 1);\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], depth + 1);\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 // This is for compatibility with server frameworks that expect the literal notation\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 || url.indexOf(':') === -1) {\n return url;\n }\n\n // Use a single RegExp and avoid unnecessary casts and function calls\n // Precompute keys for faster lookup\n const params = urlPathParams as DefaultUrlParams;\n\n // Use a replacer function that avoids extra work\n return url.replace(/:([a-zA-Z0-9_]+)/g, (match, key) => {\n // Use hasOwnProperty for strict key existence check\n if (hasOwn(params, key)) {\n const value = params[key];\n\n // Only replace if value is not undefined or null\n if (value !== undefined && value !== null) {\n const encoded = encodeURIComponent(String(value));\n\n // These can't be encoded, and URL parsers would move the request to another path\n if (encoded === '.' || encoded === '..') {\n throw new Error('Path params \".\" and \"..\" not allowed.');\n }\n\n return encoded;\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL starts with a scheme (e.g., \"http://\", \"https://\").\n * A \"://\" appearing later, e.g. in a query string, does not make the URL absolute.\n *\n * @param url - The URL string to check.\n * @returns `true` if the URL is absolute, otherwise `false`.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n}\n\nexport const timeNow = () => Date.now();\n\nexport const noop = () => {};\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 (value === 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 (\n typeof globalThis !== UNDEFINED &&\n typeof globalThis.Buffer !== UNDEFINED &&\n globalThis.Buffer.isBuffer(value)\n ) {\n return false;\n }\n\n if (value instanceof Date || isSearchParams(value)) {\n return false;\n }\n\n if (isObject(value)) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` (plain object)\n if (proto === Object.prototype) {\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 const delayInvocation = (ms: number): Promise =>\n new Promise((resolve) =>\n setTimeout(resolve, Math.min(ms, MAX_DELAY_MS), true),\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, depth = 0): any {\n if (depth >= MAX_DEPTH) {\n return data;\n }\n\n if (data && isObject(data) && typeof data.data !== UNDEFINED) {\n return flattenData(data.data, depth + 1);\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 // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key.toLowerCase()] = value;\n });\n } else {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n // Assigning \"__proto__\" would set the prototype of the result\n if (hasOwn(headers, key) && key !== '__proto__') {\n headersObject[key.toLowerCase()] = headers[key];\n }\n }\n }\n\n return headersObject;\n}\n\n/**\n * Determines if the current environment is a browser.\n *\n * @returns {boolean} - True if running in a browser environment, false otherwise.\n */\nexport function isBrowser(): boolean {\n // For node and some mobile frameworks like React Native, `add/removeEventListener` doesn't exist on window!\n return (\n typeof window !== UNDEFINED && typeof window.addEventListener === FUNCTION\n );\n}\n\n/**\n * Creates an abort/timeout error compatible with all JS runtimes.\n * Falls back to a plain Error with the correct `name` when DOMException is unavailable (e.g. React Native).\n *\n * @param {string} message - The error message.\n * @param {string} name - The error name (e.g. 'AbortError', 'TimeoutError').\n * @returns {DOMException | Error} - An error object with the specified name.\n */\nexport function createAbortError(\n message: string,\n name: string,\n): DOMException | Error {\n if (typeof DOMException !== UNDEFINED) {\n return new DOMException(message, name);\n }\n\n const error = new Error(message);\n error.name = name;\n\n return error;\n}\n\n/**\n * Detects if the user is on a slow network connection\n * @returns {boolean} True if connection is slow, false otherwise or if detection unavailable\n */\nexport const isSlowConnection = (): boolean => {\n const conn = typeof navigator !== UNDEFINED && (navigator as any).connection;\n\n return conn && ['slow-2g', '2g', '3g'].includes(conn.effectiveType);\n};\n","import { FUNCTION } from './constants';\nimport type { InterceptorFunction } from './types/interceptor-manager';\nimport { isObject, sanitizeObject } from './utils';\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 Args - Type of additional arguments.\n * @template I - Type of interceptors.\n *\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n * @param {T} data - The data object to process.\n * @param {...Args} args - Additional arguments to pass to interceptors.\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptors<\n T extends object,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Args extends any[] = any[],\n I = InterceptorFunction | InterceptorFunction[],\n>(interceptors: I | undefined, data: T, ...args: Args): Promise {\n if (!interceptors) {\n return;\n }\n\n const merge = (v: unknown) =>\n v &&\n isObject(data) &&\n isObject(v) &&\n Object.assign(data, sanitizeObject(v));\n\n if (typeof interceptors === FUNCTION) {\n merge(await (interceptors as InterceptorFunction)(data, ...args));\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n merge(await interceptor(data, ...args));\n }\n }\n}\n","import type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\n/**\n * This is a base error class\n */\nexport class FetchError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends Error {\n status: number;\n statusText: string;\n config: RequestConfig;\n isCancelled: boolean;\n\n constructor(\n message: string,\n public request: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n public response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message);\n\n this.name = 'FetchError';\n this.status = response ? response.status : 0;\n this.statusText = response ? response.statusText : '';\n this.config = request;\n this.isCancelled = false;\n }\n}\n","import { FetchError } from './fetch-error';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\nexport class ResponseError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends FetchError {\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message, request, response);\n\n this.name = 'ResponseError';\n }\n}\n","/**\n * @module timeout-wheel\n * @description\n * Ultra-minimal timing wheel implementation optimized for max performance & many requests.\n * For most of the cases it's 4-100x faster than setTimeout and setInterval alone.\n * Provides efficient scheduling and cancellation of timeouts using a circular array.\n *\n * Position 0 → 1 → 2 → ... → 599 → 0 → 1 → 2 ...\n * Time: 0s 1s 2s 599s 600s 601s 602s\n *\n * The timing wheel consists of 600 slots (one per second for 10 min).\n * Each slot contains a list of timeout items, each associated with a unique key and callback.\n * Timeouts are scheduled by placing them in the appropriate slot based on the delay in seconds.\n * The wheel advances every second, executing and removing callbacks as their timeouts expire.\n * Defaults to setTimeout if the delay doesn't fit in the wheel (~10 minutes) or is not divisible by 1000.\n *\n * @remarks\n * - Designed for minimal footprint and simplicity.\n * - Only supports second-level granularity (minimum timeout: 1 second).\n * - Timeouts never fire early, but may fire up to 1 second late.\n * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { MAX_DELAY_MS } from './constants';\nimport { noop, timeNow } from './utils';\n\ntype TimeoutCallback = () => unknown | Promise;\ntype TimeoutItem = [string, TimeoutCallback]; // [key, callback]\n\nconst WHEEL_SIZE = 600; // 600 slots for 10 min (1 slot per second)\nconst SECOND = 1000; // 1 second in milliseconds\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\nlet lastTick = 0; // Time when the wheel last advanced (or started)\nlet timer: NodeJS.Timeout | null = null;\n\nconst handleCallback = ([key, callback]: TimeoutItem): void => {\n keyMap.delete(key);\n\n try {\n const result = callback();\n if (result && result instanceof Promise) {\n // Silently ignore async errors to prevent wheel from stopping\n result.catch(noop);\n }\n } catch {\n // Ignore callback errors to prevent wheel from stopping\n }\n};\n\nexport const addTimeout = (\n key: string,\n cb: TimeoutCallback,\n ms: number,\n): void => {\n removeTimeout(key);\n\n // A running wheel is already part-way through its current second, so the timeout\n // waits one more slot to never fire early. A new wheel starts its first second now.\n const seconds = ms / SECOND + (timer && timeNow() !== lastTick ? 1 : 0);\n\n // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || seconds >= WHEEL_SIZE || ms % SECOND !== 0) {\n keyMap.set(key, [\n setTimeout(\n handleCallback.bind(null, [key, cb]),\n Math.min(ms, MAX_DELAY_MS),\n ),\n ]); // Store timeout ID instead of slot\n\n return;\n }\n\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n lastTick = timeNow();\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n lastTick = timeNow();\n const slot = wheel[position];\n\n // Use slot.length directly (not cached) so mid-iteration mutations\n // from callbacks (e.g. removeTimeout) are handled correctly\n for (let i = 0; i < slot.length; i++) {\n handleCallback(slot[i]);\n }\n\n slot.length = 0; // Reuse array, avoid GC allocation\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }, SECOND);\n }\n};\n\nexport const removeTimeout = (key: string): void => {\n const slotOrTimeout = keyMap.get(key);\n\n if (slotOrTimeout !== undefined) {\n // It's a Timeout object from setTimeout\n if (Array.isArray(slotOrTimeout)) {\n clearTimeout(slotOrTimeout[0]);\n } else {\n const slotArr = wheel[slotOrTimeout];\n\n for (let i = 0; i < slotArr.length; i++) {\n if (slotArr[i][0] === key) {\n slotArr.splice(i, 1);\n break;\n }\n }\n }\n\n keyMap.delete(key);\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }\n};\n\nexport const clearAllTimeouts = () => {\n // Clear native setTimeout timeouts first!\n keyMap.forEach((value) => {\n if (Array.isArray(value)) {\n clearTimeout(value[0]);\n }\n });\n\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n\n keyMap.clear();\n\n for (let i = 0; i < WHEEL_SIZE; i++) {\n wheel[i].length = 0;\n }\n\n position = 0;\n};\n","/**\n * @module inflight-manager\n *\n * Manages in-flight asynchronous requests using unique keys to enable deduplication and cancellation.\n *\n * Provides utilities for:\n * - Deduplication of requests within a configurable time window (`dedupeTime`)\n * - Timeout management and automatic request abortion\n * - AbortController lifecycle and cancellation logic\n * - Concurrency control and request state tracking\n * - In-flight promise deduplication to prevent duplicate network calls\n *\n * @remarks\n * - Requests with the same key within the deduplication interval share the same AbortController and in-flight promise.\n * - Supports cancellation of previous requests when a new one with the same key is issued, if `isCancellable` is enabled.\n * - Timeout logic ensures requests are aborted after a specified duration, if enabled.\n * - Internal queue state is managed via a Map, keyed by request identifier.\n * - Polled requests are also marked as \"in-flight\" to prevent duplicate requests.\n */\n\nimport { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { createAbortError, timeNow } from './utils';\n\nexport type InFlightItem = [\n AbortController, // AbortController for the request\n boolean, // Whether timeout is enabled for the request\n number, // Timestamp when the request was marked in-flight\n boolean, // isCancellable - whether the request can be cancelled\n Promise | null, // Optional in-flight promise for deduplication\n];\n\nconst inFlight: Map = 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 {string | null} key - Unique key for the request (e.g. cache key).\n * @param {string} url - The request URL (for error messages/timeouts).\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 {AbortController} - A promise that resolves to an AbortController.\n */\nexport function markInFlight(\n key: string | null,\n url: string,\n timeout: number | undefined,\n dedupeTime: number,\n isCancellable: boolean,\n isTimeoutEnabled: boolean,\n): AbortController {\n if (!key) {\n return new AbortController();\n }\n\n const now = timeNow();\n const item = inFlight.get(key);\n let prevPromise: Promise | null = null;\n\n // Previous request is in-flight, check if we can reuse it\n if (item) {\n const prevController = item[0];\n const prevIsCancellable = item[3];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (\n !prevIsCancellable &&\n now - item[2] < dedupeTime &&\n !prevController.signal.aborted\n ) {\n return prevController;\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 (prevIsCancellable) {\n prevController.abort(\n createAbortError('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n removeTimeout(key);\n prevPromise = item[4];\n }\n\n const controller = new AbortController();\n\n inFlight.set(key, [\n controller,\n isTimeoutEnabled,\n now,\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n createAbortError(url + ' aborted due to timeout', TIMEOUT_ERROR),\n );\n },\n timeout as number,\n );\n }\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param key - Unique key for the request.\n * @param {boolean} error - Optional error to abort the request with. If null, the request is simply removed but no abort sent.\n * @returns {Promise} - A promise that resolves when the request is aborted and removed.\n */\nexport async function abortRequest(\n key: string | null,\n error: DOMException | Error | null | string = null,\n): Promise {\n // If the key is not in the queue, there's nothing to remove\n if (key) {\n const item = inFlight.get(key);\n\n if (item) {\n // If the request is not yet aborted, abort it with the provided error\n if (error) {\n const controller = item[0];\n controller.abort(error);\n }\n\n removeInFlight(key);\n }\n }\n}\n\n/**\n * Removes a request from the in-flight queue without aborting or clearing timeout.\n *\n * @param key - Unique key for the request.\n */\nexport function removeInFlight(key: string | null): void {\n removeTimeout(key!);\n inFlight.delete(key!);\n}\n\n/**\n * Gets the AbortController for a request key.\n *\n * @param key - Unique key for the request.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n key: string,\n): Promise {\n const item = inFlight.get(key);\n\n return item?.[0];\n}\n\n/**\n * Adds helpers for in-flight promise deduplication.\n *\n * @param key - Unique key for the request.\n * @param promise - The promise to store.\n */\nexport function setInFlightPromise(\n key: string,\n promise: Promise,\n): void {\n const item = inFlight.get(key);\n if (item) {\n // store the promise at index 4 — item is already the Map's reference, no need to re-set\n item[4] = promise;\n }\n}\n\n/**\n * Retrieves the in-flight promise for a request key if it exists and is within the dedupeTime interval.\n *\n * @param key - Unique key for the request.\n * @param dedupeTime - Deduplication time in milliseconds.\n * @returns {Promise | null} - The in-flight promise or null.\n */\nexport function getInFlightPromise(\n key: string | null,\n dedupeTime: number,\n): Promise | null {\n if (!key) {\n return null;\n }\n\n const prevReq = inFlight.get(key);\n\n if (\n prevReq &&\n // If the request is in-flight and has a promise\n prevReq[4] &&\n // If the request is cancellable, we will not reuse it\n !prevReq[3] &&\n // If the request is within the dedupeTime\n timeNow() - prevReq[2] < dedupeTime &&\n // If one request is cancelled, ALL deduped requests get cancelled\n !prevReq[0].signal.aborted\n ) {\n return prevReq[4] as Promise;\n }\n\n return null;\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","/**\n * @module revalidator-manager\n *\n * Provides utilities for managing cache revalidation functions, including:\n * - Registering and unregistering revalidators for specific cache keys.\n * - Triggering revalidation for a given key.\n * - Enabling or disabling automatic revalidation on window focus and if user comes back online for specific keys.\n * - Attaching and removing global focus and online event handlers to trigger revalidation.\n *\n * Revalidators are functions that can be registered to revalidate cache entries when needed.\n * They are typically used to refresh data in the cache when the window gains focus or when specific actions occur.\n * @performance O(1) lookup by key makes it blazing fast to register, unregister, and revalidate cache entries.\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n * @remarks\n * - Designed to be used in various environments (Deno, Node.js, Bun, Browser, etc.) to ensure cache consistency and freshness.\n */\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { FetchResponse } from './types';\nimport { isBrowser, noop, timeNow } from './utils';\n\nexport type RevalidatorFn = (\n isStaleRevalidation?: boolean,\n) => Promise;\n\ntype EventType = 'focus' | 'online';\n\ntype RevalidatorEntry = [\n RevalidatorFn, // main revalidator\n number, // lastUsed\n number, // ttl\n number?, // staleTime\n RevalidatorFn?, // bgRevalidator\n boolean?, // refetchOnFocus\n boolean?, // refetchOnReconnect\n];\n\nconst DEFAULT_TTL = 3 * 60 * 1000; // Default TTL of 3 minutes\nconst revalidators = new Map();\n\n/**\n * Stores cleanup functions for active event handlers (browser or custom providers).\n * Each entry removes the corresponding event listener when called.\n * @remarks\n * - Improves performance by reducing the number of event listeners.\n * - Enables efficient O(1) lookup and management of event handlers for revalidation.\n */\nconst eventHandlers = new Map void>();\n\n/** Subscribe to an event and return a cleanup function */\nexport type EventProvider = (handler: () => void) => () => void;\n\nconst customEventProviders = new Map();\n\n/**\n * Registers a custom event provider for 'focus' or 'online' events.\n * Useful for non-browser environments like React Native.\n *\n * @param type - The event type ('focus' or 'online').\n * @param provider - A function that subscribes to the event and returns a cleanup function.\n */\nexport function setEventProvider(\n type: EventType,\n provider: EventProvider,\n): void {\n customEventProviders.set(type, provider);\n\n // Re-register if already active\n if (eventHandlers.has(type)) {\n removeEventHandler(type);\n addEventHandler(type);\n }\n}\n\n/**\n * Triggers revalidation for all registered entries based on the given event type.\n * For example, if it's a 'focus' event, it will revalidate entries that have the `refetchOnFocus` flag set.\n * Updates the timestamp and invokes the revalidator function for each applicable entry.\n *\n * @param type - The type of event that caused the revalidation (e.g., 'focus' or 'online').\n * @param isStaleRevalidation - If `true`, uses background revalidator and doesn't mark as in-flight.\n */\nexport function revalidateAll(\n type: EventType,\n isStaleRevalidation: boolean = true,\n) {\n const flagIndex = type === 'focus' ? 5 : 6;\n const now = timeNow();\n\n revalidators.forEach((entry) => {\n if (!entry[flagIndex]) {\n return;\n }\n\n entry[1] = now;\n\n // If it's a stale revalidation, use the background revalidator function\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n if (revalidator) {\n Promise.resolve(revalidator(isStaleRevalidation)).catch(noop);\n }\n });\n}\n\n/**\n * Revalidates an entry by executing the registered revalidation function.\n *\n * @param key The unique identifier for the cache entry to revalidate. If `null`, no revalidation occurs.\n * @param isStaleRevalidation - If `true`, it does not mark revalidated requests as in-flight.\n * @returns A promise that resolves to the result of the revalidator function, or\n * `null` if no key or revalidator is found, or a `FetchResponse` if applicable.\n */\nexport async function revalidate(\n key: string | null,\n isStaleRevalidation: boolean = false,\n): Promise {\n // If no key is provided, no revalidation occurs\n if (!key) {\n return null;\n }\n\n const entry = revalidators.get(key);\n\n if (entry) {\n // Update only the lastUsed timestamp without resetting the whole array\n entry[1] = timeNow();\n\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n // If no revalidator function is registered, return null\n if (revalidator) {\n return await revalidator(isStaleRevalidation);\n }\n }\n\n // If no revalidator is registered for the key, return null\n return null;\n}\n\n/**\n * Removes all revalidators associated with the specified event type.\n *\n * @param type - The event type whose revalidators should be removed.\n */\nexport function removeRevalidators(type: EventType) {\n removeEventHandler(type);\n\n const flagIndex = type === 'focus' ? 5 : 6;\n\n // Clear all revalidators with this flag\n revalidators.forEach((entry, key) => {\n if (entry[flagIndex]) {\n removeRevalidator(key);\n }\n });\n}\n\n/**\n * Registers a generic revalidation event handler for the specified event type.\n * Supports browser window events and custom event providers (e.g. for React Native).\n * Ensures the handler is only added once.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'online').\n */\nfunction addEventHandler(event: EventType) {\n if (eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n // Priority 1: Custom event provider (works in any environment including React Native)\n const customProvider = customEventProviders.get(event);\n\n if (customProvider) {\n const cleanup = customProvider(handler);\n\n eventHandlers.set(event, cleanup);\n\n return;\n }\n\n // Priority 2: Browser window events\n if (isBrowser()) {\n window.addEventListener(event, handler);\n\n eventHandlers.set(event, () => window.removeEventListener(event, handler));\n }\n}\n\n/**\n * Removes the event handler for the specified event type.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n const cleanup = eventHandlers.get(event);\n\n if (cleanup) {\n cleanup();\n eventHandlers.delete(event);\n }\n}\n\n/**\n * Registers a revalidation functions for a specific cache key.\n *\n * @param {string} key Cache key to utilize\n * @param {RevalidatorFn} revalidatorFn Main revalidation function (marks in-flight requests)\n * @param {number} [ttl] Time to live in milliseconds (default: 3 minutes)\n * @param {number} [staleTime] Time (in seconds) after which the cache entry is considered stale\n * @param {RevalidatorFn} [bgRevalidatorFn] For stale revalidation (does not mark in-flight requests)\n * @param {boolean} [refetchOnFocus] Whether to revalidate on window focus\n * @param {boolean} [refetchOnReconnect] Whether to revalidate on network reconnect\n */\nexport function addRevalidator(\n key: string,\n revalidatorFn: RevalidatorFn, // Main revalidation function (marks in-flight requests)\n ttl?: number,\n staleTime?: number,\n bgRevalidatorFn?: RevalidatorFn, // For stale revalidation (does not mark in-flight requests)\n refetchOnFocus?: boolean,\n refetchOnReconnect?: boolean,\n) {\n const existing = revalidators.get(key);\n\n if (existing) {\n // Update in-place to avoid allocating a new tuple array\n existing[0] = revalidatorFn;\n existing[1] = timeNow();\n existing[2] = ttl ?? DEFAULT_TTL;\n existing[3] = staleTime;\n existing[4] = bgRevalidatorFn;\n existing[5] = refetchOnFocus;\n existing[6] = refetchOnReconnect;\n } else {\n revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\n ]);\n }\n\n if (refetchOnFocus) {\n addEventHandler('focus');\n }\n\n if (refetchOnReconnect) {\n addEventHandler('online');\n }\n\n if (staleTime) {\n addTimeout('s:' + key, revalidate.bind(null, key, true), staleTime * 1000);\n }\n}\n\nexport function removeRevalidator(key: string) {\n revalidators.delete(key);\n\n // Clean up stale timer\n removeTimeout('s:' + key);\n}\n\n/**\n * Periodically cleans up expired revalidators from the registry.\n * Removes any revalidator whose TTL has expired.\n *\n * @param {number} intervalMs How often to run cleanup (default: 3 minutes)\n * @returns {() => void} A function to stop the periodic cleanup\n */\nexport function startRevalidatorCleanup(\n intervalMs: number = DEFAULT_TTL,\n): () => void {\n const intervalId = setInterval(() => {\n const now = timeNow();\n\n revalidators.forEach(\n ([, lastUsed, ttl, , , refetchOnFocus, refetchOnReconnect], key) => {\n // Skip focus-only or reconnect-only revalidators to keep them alive\n if (refetchOnFocus || refetchOnReconnect) {\n return;\n }\n\n if (ttl > 0 && now - lastUsed > ttl) {\n removeRevalidator(key);\n }\n },\n );\n }, intervalMs);\n\n return () => clearInterval(intervalId);\n}\n","/**\n * Manages a set of listeners (subscribers) for arbitrary string keys, allowing cross-context or cross-component\n * cache updates and synchronization. Provides functions to add, remove, and notify listeners, as well as a\n * convenient subscribe/unsubscribe API.\n *\n * @template T - The type of the response object passed to listeners.\n *\n * @remarks\n * - Listeners are grouped by a string key, which typically represents a cache key or resource identifier.\n * - When `notifySubscribers` is called for a key, all listeners registered for that key are invoked with the provided response.\n * - The `subscribe` function returns an unsubscribe function for convenient cleanup.\n *\n * @example\n * ```ts\n * const unsubscribe = subscribe('user:123', (response) => {\n * // handle updated data\n * });\n * // Later, to stop listening:\n * unsubscribe();\n * ```\n */\n\nimport { noop } from './utils';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Listener = (response: T) => void;\n\nconst listeners = new Map>();\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n let set = listeners.get(key);\n\n if (!set) {\n listeners.set(key, (set = new Set()));\n }\n\n set.add(fn);\n}\n\nexport function removeListener(key: string, fn: Listener) {\n const set = listeners.get(key);\n\n if (set) {\n set.delete(fn);\n\n // If the set is empty, remove the key from the listeners map\n if (set.size === 0) {\n listeners.delete(key);\n }\n }\n}\n\nexport function notifySubscribers(key: string, response: T) {\n const fns = listeners.get(key);\n\n if (fns) {\n if (fns.size === 1) {\n // If there's only one listener, call it directly\n const fn = fns.values().next().value;\n fn!(response);\n } else {\n fns.forEach((fn) => fn(response));\n }\n }\n}\n\nexport function subscribe(key: string | null, fn: (response: T) => void) {\n if (!key) {\n // No op if no key is provided\n return noop;\n }\n\n addListener(key, fn);\n\n // Return an unsubscribe function\n return () => {\n removeListener(key, fn);\n };\n}\n","import { processHeaders } from './utils';\nimport {\n GET,\n APPLICATION_JSON,\n HEAD,\n STRING,\n CHARSET_UTF_8,\n CONTENT_TYPE,\n REJECT,\n UNDEFINED,\n APPLICATION_CONTENT_TYPE,\n} from './constants';\nimport type {\n HeadersObject,\n Method,\n RequestConfig,\n} from './types/request-handler';\nimport {\n replaceUrlPathParams,\n appendQueryParams,\n isSearchParams,\n isJSONSerializable,\n isSlowConnection,\n isAbsoluteUrl,\n sanitizeObject,\n isObject,\n} from './utils';\n\nconst defaultTimeoutMs = (isSlowConnection() ? 60 : 30) * 1000;\n\nexport const defaultConfig: RequestConfig = {\n strategy: REJECT,\n timeout: defaultTimeoutMs, // 30 seconds (60 on slow connections)\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n },\n retry: {\n delay: defaultTimeoutMs / 30, // 1 second (2 on slow connections)\n maxDelay: defaultTimeoutMs, // 30 seconds (60 on slow connections)\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 * Overwrites the default configuration with the provided custom configuration.\n *\n * @param {Partial} customConfig - The custom configuration to merge into the default config.\n * @returns {Partial} - The updated default configuration object.\n */\nexport function setDefaultConfig(\n customConfig: Partial,\n): Partial {\n const sanitized = sanitizeObject(customConfig);\n\n // Merge nested retry and headers settings into the current defaults instead of replacing them\n return mergeConfigs(\n { retry: defaultConfig.retry, headers: defaultConfig.headers },\n sanitized,\n defaultConfig,\n );\n}\n\n/**\n * Returns a shallow copy of the current default configuration.\n *\n * @returns {RequestConfig} - The current default configuration.\n */\nexport function getDefaultConfig(): RequestConfig {\n return { ...defaultConfig };\n}\n\n/**\n * Build request configuration from defaults and overrides.\n * This function merges the default configuration with the provided request configuration,\n * @param {string} url - Request url\n * @param {RequestConfig | null | undefined} reqConfig - Request configuration\n * @return {RequestConfig} - Merged request configuration\n */\nexport function buildConfig(\n url: string,\n reqConfig?: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null,\n): RequestConfig {\n // Merging gives the request its own copies of nested objects like headers, so that\n // mutations (e.g. by interceptors) never leak into the global defaults\n const merged = mergeConfigs(\n defaultConfig,\n reqConfig ? sanitizeObject(reqConfig) : {},\n );\n\n return buildFetcherConfig(url, merged);\n}\n\n/**\n * Builds the fetcher configuration by setting the method, body, headers, and URL.\n * It also handles query parameters and path parameters. This fn mutates the passed `requestConfig` object.\n * @param {string} url - The endpoint URL to which the request will be sent.\n * @param {RequestConfig} requestConfig - The request configuration object containing method, body, headers, and other options.\n * @return {RequestConfig} - The modified request configuration object with the URL, method, body, and headers set appropriately.\n **/\nexport function buildFetcherConfig(\n url: string,\n requestConfig: RequestConfig,\n): RequestConfig {\n let method = requestConfig.method as Method;\n method = method ? (method.toUpperCase() as Method) : GET;\n\n let body: RequestConfig['data'] | undefined;\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (method !== GET && method !== HEAD) {\n body = requestConfig.body ?? requestConfig.data;\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (body && typeof body !== STRING && isJSONSerializable(body)) {\n body = JSON.stringify(body);\n }\n }\n\n setContentTypeIfNeeded(requestConfig.headers, body);\n\n // Native fetch compatible settings\n const credentials = requestConfig.withCredentials\n ? 'include'\n : requestConfig.credentials;\n\n // The explicitly passed query params\n const dynamicUrl = replaceUrlPathParams(url, requestConfig.urlPathParams);\n const urlPath = appendQueryParams(dynamicUrl, requestConfig.params);\n const isFullUrl = isAbsoluteUrl(url);\n const baseURL = isFullUrl\n ? ''\n : requestConfig.baseURL || requestConfig.apiUrl || '';\n\n // Join as a path, as plain concatenation could extend the host of the baseURL,\n // e.g. \"https://api.example.com\" + \".evil.com\" would point to another host\n const separator =\n baseURL && urlPath && !baseURL.endsWith('/') && !/^[/?#]/.test(urlPath)\n ? '/'\n : '';\n\n requestConfig.url = baseURL + separator + urlPath;\n requestConfig.method = method;\n requestConfig.credentials = credentials;\n requestConfig.body = body;\n\n return requestConfig;\n}\n\n/**\n * Ensures the `Content-Type` header is set to `application/json; charset=utf-8`\n * if it is not already present and the request method and body meet specific conditions.\n *\n * @param headers - The headers object to modify. Can be an instance of `Headers`\n * or a plain object conforming to `HeadersInit`.\n * @param body - The optional body of the request. If no body is provided and the\n * method is 'GET' or 'HEAD', the function exits without modifying headers.\n */\nfunction setContentTypeIfNeeded(\n headers?: HeadersInit | HeadersObject,\n body?: unknown,\n): void {\n // If no headers are provided, or if the body is not set and the method is PUT or DELETE, do nothing\n if (!headers || !body) {\n return;\n }\n\n // Types that should not have Content-Type set (browser handles these)\n if (\n body instanceof FormData || // Browser automatically sets multipart/form-data with boundary\n (typeof Blob !== UNDEFINED && body instanceof Blob) || // Blob/File already have their own MIME types, don't override\n (typeof File !== UNDEFINED && body instanceof File) ||\n (typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream) // Stream type should be determined by the stream source\n ) {\n return;\n }\n\n let contentTypeValue: string;\n\n if (isSearchParams(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded';\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'octet-stream';\n } else if (isJSONSerializable(body)) {\n contentTypeValue = APPLICATION_JSON + ';' + CHARSET_UTF_8;\n } else {\n // Do not set Content-Type if content is not recognizable\n return;\n }\n\n if (headers instanceof Headers) {\n if (!headers.has(CONTENT_TYPE)) {\n headers.set(CONTENT_TYPE, contentTypeValue);\n }\n } else if (\n isObject(headers) &&\n !Array.isArray(headers) &&\n // Header names are case-insensitive, so check the normalized (lowercase) headers\n !processHeaders(headers as HeadersObject)[CONTENT_TYPE.toLowerCase()]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\n/**\n * Merges two request configurations, applying overrides from the second config to the first.\n * Handles special merging for nested properties like 'retry' and 'headers' (deep merge),\n * and concatenates interceptor arrays for 'onRequest', 'onResponse', and 'onError'.\n * If a target config is provided, it mutates that object; otherwise, creates a new one.\n *\n * @param {RequestConfig} baseConfig - The base configuration object to merge from.\n * @param {RequestConfig} overrideConfig - The override configuration object to apply on top of the base.\n * @param {RequestConfig} [targetConfig={}] - Optional target configuration object to merge into (mutated in place).\n * @returns {RequestConfig} The merged configuration object.\n *\n * @example\n * const base = { timeout: 5000, headers: { 'Accept': 'application/json' } };\n * const override = { timeout: 10000, headers: { 'Authorization': 'Bearer token' } };\n * const merged = mergeConfigs(base, override);\n * // Result: { timeout: 10000, headers: { Accept: 'application/json', Authorization: 'Bearer token' } }\n */\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig = {},\n): RequestConfig {\n Object.assign(targetConfig, baseConfig, overrideConfig);\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', baseConfig, overrideConfig, targetConfig);\n mergeConfig('headers', baseConfig, overrideConfig, targetConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', baseConfig, overrideConfig, targetConfig);\n mergeInterceptors('onResponse', baseConfig, overrideConfig, targetConfig);\n mergeInterceptors('onError', baseConfig, overrideConfig, targetConfig);\n\n return targetConfig;\n}\n\n/**\n * Efficiently merges interceptor functions from base and new configs\n */\nfunction mergeInterceptors<\n K extends 'onRequest' | 'onResponse' | 'onError' | 'onRetry',\n>(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const baseInterceptor = baseConfig[property];\n const newInterceptor = overrideConfig[property];\n\n if (!baseInterceptor && !newInterceptor) {\n return;\n }\n\n if (!baseInterceptor) {\n targetConfig[property] = newInterceptor;\n return;\n }\n\n if (!newInterceptor) {\n targetConfig[property] = baseInterceptor;\n return;\n }\n\n const baseArr = Array.isArray(baseInterceptor)\n ? baseInterceptor\n : [baseInterceptor];\n const newArr = Array.isArray(newInterceptor)\n ? newInterceptor\n : [newInterceptor];\n\n // This is the only LIFO interceptor, so we apply it after the response is prepared\n targetConfig[property] =\n property === 'onResponse' ? newArr.concat(baseArr) : baseArr.concat(newArr);\n}\n\n/**\n * Merges the specified property from the base configuration and the override configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and override configurations. Must be a key of RequestConfig.\n * @param {RequestConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestConfig} overrideConfig - The override configuration object that contains user-specific settings to merge.\n * @param {RequestConfig} targetConfig - The configuration object that will receive the merged properties.\n */\nexport function mergeConfig(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n if (override) {\n if (property === 'headers') {\n // Handle Headers instances which don't expose entries as own enumerable properties\n const isInstance =\n (base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers;\n const merged: HeadersObject = isInstance\n ? processHeaders(base)\n : { ...(base as HeadersObject) };\n const overrides: HeadersObject = isInstance\n ? processHeaders(override)\n : sanitizeObject(override as HeadersObject);\n\n // Header names are case-insensitive, so replace existing entries instead of duplicating them\n for (const key of Object.keys(overrides)) {\n const lowerKey = key.toLowerCase();\n\n for (const existingKey in merged) {\n if (existingKey.toLowerCase() === lowerKey) {\n delete merged[existingKey];\n }\n }\n\n merged[key] = overrides[key];\n }\n\n targetConfig[property] = merged as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...sanitizeObject(override as Record),\n } as RequestConfig[K];\n }\n } else if (\n override === undefined &&\n isObject(base) &&\n !((base as Headers | HeadersObject) instanceof Headers)\n ) {\n // Copy so that mutating the merged config never changes the base config\n targetConfig[property] = { ...base } as RequestConfig[K];\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport type {\n CacheKeyFunction,\n DefaultResponse,\n FetchResponse,\n MutationSettings,\n RequestConfig,\n} from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, STRING } from './constants';\nimport {\n isJSONSerializable,\n isObject,\n isSearchParams,\n sanitizeObject,\n sortObject,\n timeNow,\n} from './utils';\nimport { revalidate } from './revalidator-manager';\nimport { notifySubscribers } from './pubsub-manager';\nimport type { DefaultPayload, DefaultParams, DefaultUrlParams } from './types';\nimport { removeInFlight } from './inflight-manager';\nimport { addTimeout } from './timeout-wheel';\nimport { defaultConfig } from './config-handler';\nimport { processHeaders } from './utils';\n\nexport const IMMEDIATE_DISCARD_CACHE_TIME = 0; // Use it for cache entries that need to be persistent until unused by components or manually deleted\n\nconst _cache = new Map>();\nconst DELIMITER = '|';\nconst MIN_LENGTH_TO_HASH = 64;\nconst CACHE_KEY_SANITIZE_PATTERN = /[^\\w\\-_|/:@.?=&~%#]/g;\nconst CACHE_KEY_NEEDS_SANITIZE = /[^\\w\\-_|/:@.?=&~%#]/; // Non-global for fast test\n\n/**\n * Headers that may affect HTTP response content and should be included in cache key generation.\n * All header names must be lowercase to match normalized request headers.\n */\nconst CACHE_KEY_HEADER_WHITELIST = new Set([\n // Content negotiation\n 'accept', // Affects response format (e.g. JSON, HTML)\n 'accept-language', // Affects localization of the response\n 'accept-encoding', // Affects response compression (e.g. gzip, br)\n\n // Authentication\n 'authorization', // Affects access to protected resources\n\n // Request body metadata\n 'content-type', // Affects how the request body is interpreted\n\n // Optional headers\n 'referer', // May influence behavior in some APIs\n 'origin', // Relevant in CORS or tenant-specific APIs\n 'user-agent', // Included only for reason if server returns client-specific content\n\n // Cookies — only if server uses session-based responses\n 'cookie', // Can fragment cache heavily; use only if necessary\n\n // Custom headers that may affect response content\n 'x-api-key', // Token-based access, often affects authorization\n 'x-requested-with', // AJAX requests (used historically for distinguishing frontend calls)\n 'x-client-id', // Per-client/partner identity; often used in multi-tenant APIs\n 'x-tenant-id', // Multi-tenant segmentation; often changes response per tenant\n 'x-user-id', // Explicit user context (less common, but may exist)\n\n 'x-app-version', // Used for version-specific behavior (e.g. mobile apps)\n 'x-feature-flag', // Controls feature rollout behavior server-side\n 'x-device-id', // Used when response varies per device/app instance\n 'x-platform', // e.g. 'ios', 'android', 'web' — used in apps that serve different content\n\n 'x-session-id', // Only if backend uses it to affect the response directly (rare)\n 'x-locale', // Sometimes used in addition to or instead of `accept-language`\n]);\n\n/**\n * Generates a unique 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 {RequestConfig} config - 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 {RequestCredentials} [credentials=\"same-origin\"] - Whether to include credentials (include, same-origin, omit).\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @returns {string} - A unique cache key string based on the provided options.\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(\n config: RequestConfig,\n cacheKeyCheck = true,\n): string {\n // This is super fast. Effectively a no-op if cacheKey is\n // a string or a function that returns a string.\n const key = config.cacheKey;\n\n if (key && cacheKeyCheck) {\n return typeof key === STRING\n ? (key as string)\n : (key as CacheKeyFunction)(config);\n }\n\n const {\n url = '',\n method = GET,\n headers = null,\n body = null,\n credentials = 'same-origin',\n } = config;\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 let headersString = '';\n if (headers) {\n let obj: Record;\n\n if (headers instanceof Headers) {\n obj = processHeaders(headers);\n } else {\n obj = headers as Record;\n }\n\n // Filter headers to only include those that affect request identity\n // Include only headers that affect request identity, not execution behavior\n const keys = Object.keys(obj);\n const len = keys.length;\n\n // Sort keys manually for fastest deterministic output\n if (len > 1) {\n keys.sort();\n }\n\n let str = '';\n for (let i = 0; i < len; ++i) {\n if (CACHE_KEY_HEADER_WHITELIST.has(keys[i].toLowerCase())) {\n str += keys[i] + ':' + obj[keys[i]] + ';';\n }\n }\n\n headersString = hash(str);\n }\n\n // For GET requests, return early with shorter cache key\n if (method === GET) {\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString;\n\n return sanitizeCacheKey(cacheStr);\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING || isSearchParams(body)) {\n const str = String(body);\n\n bodyString = str.length < MIN_LENGTH_TO_HASH ? str : hash(str); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Files can't be read synchronously, so they are identified by their object\n bodyString +=\n key +\n '=' +\n (typeof value === STRING ? value : 'F' + getObjectId(value as File)) +\n '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (isObject(body) && !isJSONSerializable(body)) {\n // Blobs, buffers, streams etc. can't be read synchronously, so they are identified by their object.\n // Two different bodies never share a key, while the same body object is still deduplicated.\n bodyString = 'B' + getObjectId(body);\n } else {\n const o = isObject(body)\n ? JSON.stringify(sortObject(body))\n : String(body);\n\n bodyString = o.length > MIN_LENGTH_TO_HASH ? hash(o) : o;\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString +\n DELIMITER +\n bodyString;\n\n return sanitizeCacheKey(cacheStr);\n}\n\nconst objectIds = new WeakMap();\nlet lastObjectId = 0;\n\n/**\n * Returns a unique id for an object, e.g. a request body that can't be serialized.\n *\n * @param {object} obj - The object to identify.\n * @returns {number} - The id of the object.\n */\nfunction getObjectId(obj: object): number {\n let id = objectIds.get(obj);\n\n if (!id) {\n objectIds.set(obj, (id = ++lastObjectId));\n }\n\n return id;\n}\n\n/**\n * Prevents cache poisoning by removal of control chars and unusual characters.\n * When anything is removed, a hash of the original key is appended so that keys\n * differing only in the removed characters (e.g. `?a[]=1` and `?a=1`) don't collide.\n *\n * @param {string} cacheStr - The raw cache key.\n * @returns {string} - The sanitized cache key.\n */\nfunction sanitizeCacheKey(cacheStr: string): string {\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '') +\n DELIMITER +\n hash(cacheStr)\n : cacheStr;\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the expiry time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(entry: CacheEntry): boolean {\n // No expiry time means the entry never expires\n if (!entry.expiry) {\n return false;\n }\n\n return timeNow() > entry.expiry;\n}\n\n/**\n * Retrieves a cached response from the internal cache using the provided key.\n *\n * @param key - The unique key identifying the cached entry. If null, returns null.\n * @returns The cached {@link FetchResponse} if found, otherwise null.\n */\nexport function getCacheData<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n key: string | null,\n): FetchResponse | null {\n if (!key) {\n return null;\n }\n\n const entry = _cache.get(key);\n\n return entry ? entry.data : null;\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 * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string | null,\n):\n | CacheEntry<\n FetchResponse\n >\n | null\n | undefined {\n return _cache.get(key as string);\n}\n\n/**\n * Sets a new cache entry or updates an existing one, with optional TTL (time-to-live).\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {number} [ttl] - Optional TTL in seconds. If not provided, the cache entry will not expire.\n * @param {number} [staleTime] - Optional stale time in seconds. If provided, the cache entry will be considered stale after this time.\n */\nexport function setCache(\n key: string,\n data: T,\n ttl?: number,\n staleTime?: number,\n): void {\n if (ttl === 0) {\n deleteCache(key);\n return;\n }\n\n const time = timeNow();\n const ttlMs = ttl ? ttl * 1000 : 0;\n const staleTimeMs = staleTime ? staleTime * 1000 : 0; // Ensure default value for staleTime\n\n _cache.set(key, {\n data,\n time,\n stale: staleTimeMs > 0 ? time + staleTimeMs : undefined, // Use undefined if staleTime is not set\n expiry: ttl === -1 ? undefined : time + ttlMs,\n });\n\n if (ttlMs > 0) {\n addTimeout(\n 'c:' + key,\n () => {\n deleteCache(key, true);\n },\n ttlMs,\n );\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n * @param {boolean} [removeExpired=false] - If true, only deletes the cache entry if it is expired or stale.\n */\nexport function deleteCache(key: string, removeExpired: boolean = false): void {\n if (removeExpired) {\n const entry = getCache(key);\n\n // If the entry does not exist, or it is neither expired nor stale, do not delete\n if (!entry || !isCacheExpired(entry)) {\n return;\n }\n }\n\n _cache.delete(key);\n}\n\n/**\n * Prunes the cache by removing entries that have expired based on the provided cache time.\n */\nexport function pruneCache(): void {\n _cache.clear();\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string | null} key Cache key to utilize. If null, no mutation occurs.\n * @param {ResponseData} newData - The new data to be cached.\n * @param {MutationSettings|undefined} settings - Mutation settings.\n */\nexport async function mutate<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n key: string | null,\n newData: ResponseData,\n settings?: MutationSettings,\n): Promise | null> {\n // If no key is provided, do nothing\n if (!key) {\n return null;\n }\n\n const entry = getCache(\n key,\n );\n\n if (!entry) {\n return null;\n }\n\n const updatedData = isObject(newData) ? sanitizeObject(newData) : newData;\n\n const updatedResponse = {\n ...entry.data,\n data: updatedData,\n };\n\n const updatedEntry = {\n ...entry,\n data: updatedResponse,\n };\n\n _cache.set(key, updatedEntry);\n notifySubscribers(key, updatedResponse);\n\n if (settings && settings.refetch) {\n return await revalidate(key);\n }\n\n return null;\n}\n\n/**\n * Retrieves a cached response if available and valid, otherwise returns null.\n *\n * @template ResponseData - The type of the response data.\n * @template RequestBody - The type of the request body.\n * @template QueryParams - The type of the query parameters.\n * @template PathParams - The type of the path parameters.\n * @param {string | null} cacheKey - The cache key to look up.\n * @param {number | undefined} cacheTime - The maximum time to cache entry.\n * @param {RequestConfig} requestConfig - The fetcher configuration.\n * @returns {FetchResponse | null} - The cached response or null.\n */\nexport function getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n cacheKey: string | null,\n cacheTime: number | undefined,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): FetchResponse | null {\n // If cache key or time is not provided, return null\n if (!cacheKey || cacheTime === undefined || cacheTime === null) {\n return null;\n }\n\n // Check if cache should be bypassed\n const buster = requestConfig.cacheBuster || defaultConfig.cacheBuster;\n if (buster && buster(requestConfig)) {\n return null;\n }\n\n if (requestConfig.cache && requestConfig.cache === 'reload') {\n return null; // Skip cache lookup entirely\n }\n\n // Retrieve the cached entry\n const entry = getCache(\n cacheKey,\n );\n\n if (!entry) {\n return null;\n }\n\n const isExpired = isCacheExpired(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n const data = entry.data;\n\n // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n // The placeholder stored while a request is in flight is not a response, so treat it as a miss\n return data && data.isFetching ? null : data;\n}\n\n/**\n * Sets or deletes the response cache based on cache settings and notifies subscribers.\n *\n * @param {FetchResponse} output - The response to cache.\n * @param {RequestConfig} requestConfig - The request configuration.\n * @param {boolean} [isError=false] - Whether the response is an error.\n */\nexport function handleResponseCache<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n output: FetchResponse,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n isError: boolean = false,\n): void {\n // It is string as it is called once request is made\n const cacheKey = requestConfig.cacheKey as string;\n\n if (cacheKey) {\n const cacheTime = requestConfig.cacheTime;\n const skipCache = requestConfig.skipCache;\n\n // Fast path: only set cache if cacheTime is positive and not skipping cache\n if (\n cacheTime &&\n (!isError || requestConfig.cacheErrors) &&\n !(skipCache && skipCache(output, requestConfig))\n ) {\n setCache(cacheKey, output, cacheTime, requestConfig.staleTime);\n } else {\n const entry = getCache(cacheKey);\n\n // Don't let the in-flight placeholder outlive a request whose result isn't cached\n if (entry && entry.data && entry.data.isFetching) {\n deleteCache(cacheKey);\n }\n }\n\n notifySubscribers(cacheKey, output);\n removeInFlight(cacheKey);\n\n const prevCacheKey = requestConfig._prevKey;\n\n if (prevCacheKey) {\n removeInFlight(prevCacheKey);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { mutate } from './cache-manager';\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n FUNCTION,\n OBJECT,\n STRING,\n} from './constants';\nimport {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n ResponseError,\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n} from './types';\nimport { flattenData, isObject, processHeaders } from './utils';\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 ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse,\n): Promise {\n // Bail early if response is null or undefined\n if (!response) {\n return null;\n }\n\n // Get the content-type header once\n let contentType = (response as Response).headers?.get(CONTENT_TYPE);\n\n if (contentType) {\n // Lowercase and trim for consistent matching\n contentType = contentType.toLowerCase().trim();\n } else {\n contentType = '';\n }\n\n // Split for mime type without charset\n const mimeType = contentType.split(';', 1)[0];\n\n let data;\n\n try {\n if (mimeType.includes(APPLICATION_JSON) || mimeType.includes('+json')) {\n data = await response.json(); // Parse JSON response\n } else if (\n (mimeType.includes('multipart/form-data') || // Parse as FormData\n mimeType.includes(\n APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded', // Handle URL-encoded forms\n )) &&\n typeof response.formData === FUNCTION\n ) {\n data = await response.formData();\n } else if (/^(image|video|audio)\\/|octet-stream|pdf|zip/.test(mimeType)) {\n data = await response.arrayBuffer(); // Parse as ArrayBuffer for binary types\n } else {\n data = await response.text();\n\n if (typeof data === STRING) {\n const trimmed = data.trim();\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n data = JSON.parse(trimmed);\n } catch {\n // leave as text if parsing fails\n }\n }\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\n/**\n * Prepare response object with additional information.\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} config - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\nexport const prepareResponse = <\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n config: RequestConfig,\n error: ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null,\n): FetchResponse => {\n const defaultResponse = config.defaultResponse;\n const cacheKey = config.cacheKey;\n const mutatator = mutate.bind(null, cacheKey as string) as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >['mutate'];\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 ?? null,\n headers: null,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: false,\n isError: true,\n } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n const isNativeResponse =\n typeof Response === FUNCTION && response instanceof Response;\n\n let data = response.data;\n\n // Set the default response if the provided data is an empty object\n if (\n defaultResponse !== undefined &&\n (data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0))\n ) {\n response.data = data = defaultResponse;\n }\n\n if (config.flattenResponse) {\n response.data = data = flattenData(data);\n }\n\n if (config.select) {\n response.data = data = config.select(data);\n }\n\n const headers = processHeaders(response.headers);\n\n // Native fetch Response extended by extra information\n if (isNativeResponse) {\n const output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > = {\n body: response.body,\n bodyUsed: response.bodyUsed,\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 // Convert methods to use arrow functions to preserve correct return types\n blob: () =>\n Promise.resolve(\n data instanceof ArrayBuffer ? new Blob([data]) : new Blob(),\n ), // Lazily construct Blob from ArrayBuffer\n json: () => Promise.resolve(data as ResponseData), // Return the already parsed JSON data\n text: () => Promise.resolve(data as string), // Return the already parsed text data\n // The body was already read, so a copy of this response is returned instead of Response.clone()\n clone: () => ({ ...output }),\n arrayBuffer: () =>\n Promise.resolve(\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0),\n ), // Return the ArrayBuffer directly\n formData: () =>\n Promise.resolve(data instanceof FormData ? data : new FormData()), // Return the already parsed FormData\n bytes: () =>\n Promise.resolve(\n new Uint8Array(\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0),\n ),\n ),\n // Enhance the response with extra information\n error,\n data,\n headers,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: response.ok && !error,\n isError: !!error,\n };\n\n return output;\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 (isObject(response)) {\n response.error = error;\n response.headers = headers;\n response.isFetching = false;\n response.mutate = mutatator;\n response.isSuccess = response.ok && !error;\n response.isError = !!error;\n }\n\n return response;\n};\n","import { applyInterceptors } from './interceptor-manager';\nimport type { FetchResponse, RetryConfig, RetryFunction } from './types';\nimport { delayInvocation, timeNow } from './utils';\nimport { generateCacheKey } from './cache-manager';\n\nfunction getMsFromHttpDate(dateString: string): number | null {\n const ms = Date.parse(dateString) - timeNow();\n\n if (!isNaN(ms)) {\n return Math.max(0, Math.floor(ms));\n }\n return null;\n}\n\n/**\n * Calculates the number of milliseconds to wait before retrying a request,\n * based on the `Retry-After` HTTP header in the provided response.\n *\n * The function supports both numeric (seconds) and HTTP-date formats for the `Retry-After` header.\n * - If the header is a number, it is interpreted as seconds and converted to milliseconds.\n * - If the header is a date, the function calculates the difference between the date and the current time.\n *\n * @param extendedResponse - The response object containing headers, or `null`.\n * @returns The number of milliseconds to wait before retrying, or `null` if the header is not present or invalid.\n */\nexport function getRetryAfterMs(\n extendedResponse: FetchResponse | null,\n): number | null {\n if (!extendedResponse) {\n return null;\n }\n\n const headers = extendedResponse.headers || {};\n const retryAfter = headers['retry-after'];\n\n if (retryAfter) {\n // Try parsing as seconds\n const seconds = Number(retryAfter);\n\n if (!isNaN(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n const ms = getMsFromHttpDate(retryAfter);\n\n if (ms !== null) {\n return ms;\n }\n }\n\n // Headers are already in lowercase\n const RATELIMIT_RESET = 'ratelimit-reset';\n\n // Unix timestamp when the rate limit window resets (relative to current time)\n // Fallback to checking 'ratelimit-reset-after' OR 'x-ratelimit-reset-after' headers\n const rateLimitResetAfter =\n headers[RATELIMIT_RESET + '-after'] ||\n headers['x-' + RATELIMIT_RESET + '-after'];\n\n if (rateLimitResetAfter) {\n const seconds = Number(rateLimitResetAfter);\n\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n }\n\n // ISO 8601 datetime when the rate limit resets\n // Fallback to checking 'ratelimit-reset-at' 'x-ratelimit-reset-at' headers\n const rateLimitResetAt =\n headers[RATELIMIT_RESET + '-at'] || headers['x-' + RATELIMIT_RESET + '-at'];\n\n if (rateLimitResetAt) {\n return getMsFromHttpDate(rateLimitResetAt);\n }\n\n return null;\n}\n\n/**\n * Executes a request function with retry logic according to the provided configuration.\n *\n * The function attempts the request up to the specified number of retries, applying delay and backoff strategies.\n * Retries can be triggered based on response status codes, custom logic, or the presence of a `Retry-After` header.\n * Optionally, an `onRetry` interceptor can be invoked before each retry attempt.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param requestFn - The function that performs the request. Receives `isStaleRevalidation` and `attempt` as arguments.\n * @param config - The retry configuration, including retry count, delay, backoff, retry conditions, and hooks.\n * @returns A promise resolving to the fetch response, or rejecting if all retries are exhausted.\n * @throws Error if the maximum number of retries is exceeded or a non-retriable error occurs.\n */\nexport async function withRetry<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation: boolean,\n attempt: number,\n ) => Promise<\n FetchResponse\n >,\n config: RetryConfig,\n): Promise> {\n const {\n retries = 0,\n delay = 0,\n backoff = 1,\n maxDelay,\n retryOn = [],\n shouldRetry,\n } = config;\n\n let attempt = 0;\n let waitTime = delay;\n const maxRetries = retries > 0 ? retries : 0;\n let output: FetchResponse;\n\n while (attempt <= maxRetries) {\n // Subsequent attempts will have output defined, but the first attempt may not.\n // Let's apply onRetry interceptor and regenerate cache key if ot really changes.\n if (attempt > 0 && output!) {\n const cfg = output.config;\n const onRetry = cfg.onRetry;\n\n if (onRetry) {\n await applyInterceptors(onRetry, output, attempt);\n\n // If the key was automatically generated, we need to regenerate it as config may change.\n // We don't detect whether config changed for performance reasons.\n if (cfg._isAutoKey) {\n cfg._prevKey = cfg.cacheKey as string;\n cfg.cacheKey = generateCacheKey(cfg, false);\n }\n }\n }\n\n // Performance optimization: Call the request function with the current attempt number\n // If this is the first attempt, we pass `isStaleRevalidation` as `false`,\n // otherwise we pass `true` to indicate that this is a stale revalidation (no cache hit).\n output = await requestFn(attempt > 0, attempt);\n const error = output.error;\n\n // Check if we should retry based on successful response\n if (!error) {\n if (shouldRetry && attempt < maxRetries) {\n const shouldRetryResult = await shouldRetry(output, attempt);\n\n if (shouldRetryResult) {\n await delayInvocation(waitTime);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n continue;\n }\n }\n\n break;\n }\n\n // Determine if we should stop retrying\n const shouldStopRetrying = await getShouldStopRetrying(\n output,\n attempt,\n maxRetries,\n shouldRetry,\n retryOn,\n );\n\n if (shouldStopRetrying) {\n break;\n }\n\n // If we should not stop retrying, continue to the next attempt\n // Handle rate limiting if the error status is 429 (Too Many Requests) or 503 (Service Unavailable)\n if (error.status === 429 || error.status === 503) {\n // Try to extract the \"Retry-After\" value from the response headers\n const retryAfterMs = getRetryAfterMs(output);\n\n // If a valid retry-after value is found, override the wait time before next retry\n // Cap it with maxDelay so that a server can't make the client wait indefinitely\n if (retryAfterMs !== null) {\n waitTime = Math.min(retryAfterMs, maxDelay || retryAfterMs);\n }\n }\n\n await delayInvocation(waitTime);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n }\n\n return output!;\n}\n\n/**\n * Determines whether to stop retrying based on the error, current attempt count, and retry configuration.\n *\n * This function checks:\n * - If the maximum number of retries has been reached.\n * - If a custom `shouldRetry` callback is provided, its result is used to decide.\n * - If no custom logic is provided, falls back to checking if the error status is included in the `retryOn` list.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param output - The response object containing the error and request configuration.\n * @param attempt - The current retry attempt number.\n * @param maxRetries - The maximum number of retry attempts allowed.\n * @param shouldRetry - Optional custom function to determine if a retry should occur.\n * @param retryOn - Optional list of HTTP status codes that should trigger a retry.\n * @returns A promise resolving to `true` if retrying should stop, or `false` to continue retrying.\n */\nexport async function getShouldStopRetrying<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n output: FetchResponse,\n attempt: number,\n maxRetries: number,\n shouldRetry?: RetryFunction<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n retryOn: number[] = [],\n): Promise {\n // Safety first: always respect max retries\n // We check retries provided regardless of the shouldRetry being provided so to avoid infinite loops.\n // It is a fail-safe so to prevent excessive retry attempts even if custom retry logic suggests a retry.\n if (attempt === maxRetries) {\n return true;\n }\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n\n if (result !== null) {\n return !result;\n }\n }\n\n return !(retryOn || []).includes(output.error?.status ?? 0);\n}\n","import type { RequestConfig, FetchResponse } from './types';\nimport { delayInvocation } from './utils';\n\n/**\n * Executes a request function with polling, stopping when shouldStopPolling returns true,\n * pollingInterval is not set, or maxAttempts is reached.\n *\n * @template Output The type of the output returned by the request function.\n * @param requestFn - The function that performs a single request (with retries).\n * @param pollingInterval - Interval in ms between polling attempts.\n * @param shouldStopPolling - Function to determine if polling should stop.\n * @param maxAttempts - Maximum number of polling attempts, default: 0 (unlimited).\n * @param pollingDelay - Delay in ms before each polling attempt, default: 0.\n * @returns The final output from the last request.\n */\nexport async function withPolling<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation?: boolean,\n attempt?: number,\n ) => Promise<\n FetchResponse\n >,\n pollingInterval?: RequestConfig['pollingInterval'],\n shouldStopPolling?: RequestConfig['shouldStopPolling'],\n maxAttempts = 0,\n pollingDelay = 0,\n): Promise> {\n if (!pollingInterval) {\n return requestFn();\n }\n\n let pollingAttempt = 0;\n let output: FetchResponse;\n\n while (maxAttempts === 0 || pollingAttempt < maxAttempts) {\n if (pollingDelay > 0) {\n await delayInvocation(pollingDelay);\n }\n\n output = await requestFn();\n\n pollingAttempt++;\n\n if (\n (maxAttempts > 0 && pollingAttempt >= maxAttempts) ||\n !pollingInterval ||\n (shouldStopPolling && shouldStopPolling(output, pollingAttempt))\n ) {\n break;\n }\n\n await delayInvocation(pollingInterval);\n }\n\n return output!;\n}\n","import type { ResponseError } from './errors/response-error';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n} from './types/request-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { handleResponseCache } from './cache-manager';\nimport { ABORT_ERROR, REJECT } from './constants';\nimport {\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n HeadersObject,\n} from './types';\nimport { processHeaders } from './utils';\n\n/**\n * Handles final processing for both success and error responses\n * Applies error interceptors, caching, notifications, and error strategy\n */\nexport async function withErrorHandling<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n isStaleRevalidation: boolean,\n requestFn: (\n isStaleRevalidation: boolean,\n ) => Promise<\n FetchResponse\n >,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): Promise> {\n const output = await requestFn(isStaleRevalidation);\n const error = output.error;\n\n if (!error) {\n // SUCCESS PATH\n handleResponseCache(output, requestConfig);\n\n return output;\n }\n\n // ERROR PATH\n\n if (requestConfig.onError) {\n await applyInterceptors(requestConfig.onError, error);\n }\n\n // Timeouts and request cancellations using AbortController do not throw any errors unless rejectCancelled is true.\n // Only handle the error if the request was not cancelled, or if it was cancelled and rejectCancelled is true.\n const isCancelled = error.isCancelled;\n\n if (!isCancelled && requestConfig.logger?.warn) {\n requestConfig.logger.warn(\n 'FETCH ERROR',\n redactError(error as ResponseError),\n );\n }\n\n // The defaultResponse strategy returns the default response in place of the error data.\n // The original data stays available through error.response.\n if (requestConfig.strategy === 'defaultResponse') {\n output.data = (requestConfig.defaultResponse ?? null) as typeof output.data;\n }\n\n // Handle cache and notifications FIRST (before strategy)\n handleResponseCache(output, requestConfig, true);\n\n // handle error strategy as the last part\n const shouldHandleError = !isCancelled || requestConfig.rejectCancelled;\n\n if (shouldHandleError) {\n const strategy = requestConfig.strategy;\n // Reject the promise\n if (strategy === REJECT) {\n return Promise.reject(error);\n }\n\n // Hang the promise\n if (strategy === 'silent') {\n await new Promise(() => null);\n }\n }\n\n return output;\n}\n\n// Credential headers that must not end up in logs\nconst SENSITIVE_HEADERS = [\n 'authorization',\n 'proxy-authorization',\n 'cookie',\n 'x-api-key',\n];\n\n/**\n * Creates a copy of the error for logging, with credential headers masked and the request body removed.\n * The error itself is left untouched.\n */\nfunction redactError(error: ResponseError): ResponseError {\n // Cache keys are dropped too, as they can contain short request bodies\n const config = {\n ...error.config,\n body: undefined,\n data: undefined,\n cacheKey: undefined,\n _prevKey: undefined,\n headers: processHeaders(error.config.headers as HeadersObject),\n };\n\n for (const name of SENSITIVE_HEADERS) {\n if (config.headers[name]) {\n config.headers[name] = '[REDACTED]';\n }\n }\n\n const copy = Object.assign(new Error(error.message), error, {\n config,\n request: config,\n response: error.response && { ...error.response, config },\n });\n\n copy.name = error.name;\n copy.stack = error.stack;\n\n return copy;\n}\n\nexport function enhanceError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): void {\n error.status = error.status || response?.status || 0;\n error.statusText = error.statusText || response?.statusText || '';\n error.config = error.request = requestConfig;\n error.response = response;\n error.isCancelled = error.name === ABORT_ERROR;\n}\n","import type {\n DefaultResponse,\n RequestConfig,\n FetchResponse,\n} from './types/request-handler';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n} from './types/api-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { ResponseError } from './errors/response-error';\nimport { isObject } from './utils';\nimport {\n markInFlight,\n setInFlightPromise,\n getInFlightPromise,\n} from './inflight-manager';\nimport { parseResponseData, prepareResponse } from './response-parser';\nimport { generateCacheKey, getCachedResponse, setCache } from './cache-manager';\nimport { withRetry } from './retry-handler';\nimport { withPolling } from './polling-handler';\nimport { notifySubscribers } from './pubsub-manager';\nimport { addRevalidator } from './revalidator-manager';\nimport { enhanceError, withErrorHandling } from './error-handler';\nimport { FUNCTION } from './constants';\nimport { buildConfig } from './config-handler';\n\nconst inFlightResponse = Object.freeze({\n isFetching: true,\n});\n\n/**\n * Sends an HTTP request to the specified URL using the provided configuration and returns a typed response.\n *\n * @typeParam ResponseData - The expected shape of the response data. Defaults to `DefaultResponse`.\n * @typeParam RequestBody - The type of the request payload/body. Defaults to `DefaultPayload`.\n * @typeParam QueryParams - The type of the query parameters. Defaults to `DefaultParams`.\n * @typeParam PathParams - The type of the path parameters. Defaults to `DefaultUrlParams`.\n *\n * @param url - The endpoint URL to which the request will be sent.\n * @param config - Optional configuration object for the request, including headers, method, body, query, and path parameters.\n *\n * @returns A promise that resolves to a `FetchResponse` containing the typed response data and request metadata.\n *\n * @example\n * ```typescript\n * const { data } = await fetchf('/api/user', { method: 'GET' });\n * console.log(data);\n * ```\n */\nexport async function fetchf<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n): Promise> {\n // Ultra-fast early cache check if cacheKey is provided as a string\n // For workloads dominated by repeated requests, this string caching optimization\n // can potentially support millions of requests per second with minimal CPU overhead\n if (reqConfig && typeof reqConfig.cacheKey === 'string') {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(reqConfig.cacheKey, reqConfig.cacheTime, reqConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n const fetcherConfig = buildConfig<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(url, reqConfig);\n\n const {\n timeout,\n cancellable,\n cacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n refetchOnFocus,\n refetchOnReconnect,\n pollingInterval = 0,\n } = fetcherConfig;\n const isCacheEnabled = cacheTime !== undefined || staleTime !== undefined;\n\n const needsCacheKey = !!(\n cacheKey ||\n timeout ||\n dedupeTime ||\n isCacheEnabled ||\n cancellable ||\n refetchOnFocus ||\n refetchOnReconnect\n );\n\n let _cacheKey: string | null = null;\n\n // Generate cache key if required\n if (needsCacheKey) {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n // Cache handling logic\n if (_cacheKey && isCacheEnabled) {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(_cacheKey, cacheTime, fetcherConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n // Deduplication logic\n if (_cacheKey && dedupeTime) {\n const inflight = getInFlightPromise<\n FetchResponse\n >(_cacheKey, dedupeTime);\n\n if (inflight) {\n return inflight;\n }\n }\n\n const retryConfig = fetcherConfig.retry || {};\n const { retries = 0, resetTimeout } = retryConfig;\n\n // The actual request logic as a function (one poll attempt, with retries)\n const doRequestOnce = async (isStaleRevalidation: boolean, attempt = 0) => {\n // If cache key is specified, we will handle optimistic updates\n // and mark the request as in-flight, so to catch \"fetching\" state.\n // This is useful for Optimistic UI updates (e.g., showing loading spinners).\n if (!attempt) {\n if (_cacheKey && !isStaleRevalidation) {\n if (staleTime) {\n const existingCache = getCachedResponse(\n _cacheKey,\n cacheTime,\n fetcherConfig,\n );\n\n // Don't notify subscribers when cache exists\n // Let them continue showing stale data during background revalidation\n if (!existingCache) {\n setCache(_cacheKey, inFlightResponse, cacheTime, staleTime);\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n } else {\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n }\n\n // Attach cache key so that it can be reused in interceptors or in the final response\n fetcherConfig.cacheKey = _cacheKey;\n }\n\n const url = fetcherConfig.url as string;\n\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = markInFlight(\n _cacheKey,\n url,\n timeout,\n dedupeTime || 0,\n !!cancellable,\n // Enable timeout either by default or when retries & resetTimeout are enabled\n !!(timeout && (!attempt || resetTimeout)),\n );\n\n // Do not create a shallow copy to maintain idempotency here.\n // This ensures the original object is mutated by interceptors whenever needed, including retry logic.\n const requestConfig = fetcherConfig;\n\n requestConfig.signal = controller.signal;\n\n let output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n let response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n try {\n if (fetcherConfig.onRequest) {\n // Zero-allocation yield to microtask queue so the outer fetchf() can call setInFlightPromise()\n // before onRequest interceptors run. This ensures that if onRequest triggers\n // another fetchf() with the same cacheKey, getInFlightPromise() finds item[4].\n // On retries (attempt > 0), setInFlightPromise() was already called during the first attempt.\n // The promise stored in item[4] is the outer doRequestPromise which covers all retries.\n // So the race only matters on the very first attempt when the outer scope hasn't had a chance to call setInFlightPromise() yet.\n if (_cacheKey && dedupeTime && !attempt) {\n await null;\n }\n\n await applyInterceptors(fetcherConfig.onRequest, requestConfig);\n }\n\n // Custom fetcher\n const fn = fetcherConfig.fetcher;\n\n response = (fn\n ? await fn(\n url,\n requestConfig,\n )\n : await fetch(\n url,\n requestConfig as RequestInit,\n )) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Custom fetcher may return a raw data object instead of a Response instance\n if (isObject(response)) {\n // Case 1: Native Response instance\n if (typeof Response === FUNCTION && response instanceof Response) {\n response.data = requestConfig.parser\n ? await requestConfig.parser(response)\n : await parseResponseData(response);\n } else if (fn) {\n // Case 2: Custom fetcher that returns a response object\n if (!('data' in response && 'body' in response)) {\n // Case 3: Raw data, wrap it\n response = { data: response } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n }\n\n // Attach config and data to the response\n // This is useful for custom fetchers that do not return a Response instance\n // and for interceptors that may need to access the request config\n response.config = requestConfig;\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n // This is the pattern for fetch responses as per spec, but custom fetchers may not follow it so we check for `ok` property\n if (response.ok !== undefined && !response.ok) {\n throw new ResponseError(\n requestConfig.method +\n ' to ' +\n url +\n ' failed! Status: ' +\n (response.status || null),\n requestConfig,\n response,\n );\n }\n }\n\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig);\n\n const onResponse = fetcherConfig.onResponse;\n\n if (onResponse) {\n await applyInterceptors(onResponse, output);\n }\n } catch (_error) {\n const error = _error as ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Append additional information to Network, CORS or any other fetch() errors\n enhanceError(\n error,\n response,\n requestConfig,\n );\n\n // Prepare Extended Response\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig, error);\n }\n\n return output;\n };\n\n // Inline and minimize function wrappers for performance\n // When retries are enabled, forward isStaleRevalidation so the first attempt\n // of a background SWR revalidation doesn't incorrectly mark the request as in-flight\n const baseRequest =\n retries > 0\n ? (isStaleRevalidation: boolean) =>\n withRetry(\n (_, attempt) => doRequestOnce(isStaleRevalidation, attempt),\n retryConfig,\n )\n : doRequestOnce;\n\n const requestWithErrorHandling = (isStaleRevalidation = false) =>\n withErrorHandling(\n isStaleRevalidation,\n baseRequest,\n fetcherConfig,\n );\n\n // Avoid unnecessary function wrapping if polling is not enabled\n const doRequestPromise = pollingInterval\n ? withPolling(\n requestWithErrorHandling,\n pollingInterval,\n fetcherConfig.shouldStopPolling,\n fetcherConfig.maxPollingAttempts,\n fetcherConfig.pollingDelay,\n )\n : requestWithErrorHandling();\n\n // If deduplication is enabled, store the in-flight promise immediately\n if (_cacheKey) {\n if (dedupeTime) {\n setInFlightPromise(_cacheKey, doRequestPromise);\n }\n\n // Only register revalidator when revalidation features are actually requested\n if (staleTime || refetchOnFocus || refetchOnReconnect) {\n addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\n );\n }\n }\n\n return doRequestPromise;\n}\n","import type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n RequestConfigUrlRequired,\n} from './types/api-handler';\nimport { fetchf } from '.';\nimport { mergeConfigs } from './config-handler';\nimport { hasOwn } from './utils';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if passed as \"fetcher\".\n * @see https://github.com/MattCCC/fetchff#configuration\n *\n * @param {Object} config - Configuration object for the API fetcher (see link above for full options).\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {string} [config.baseURL] - The base URL for the API.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\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 EndpointTypes extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\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 const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\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 endpointName - The name of the API endpoint to call.\n * @param requestConfig - Additional configuration for the request.\n * @returns A promise that resolves with the response from the API provider.\n */\n async request(endpointName, requestConfig = {}) {\n // Use global and per-endpoint settings\n // Only own properties are endpoints, not ones inherited like \"constructor\"\n const endpointConfig = hasOwn(endpoints, endpointName as string)\n ? endpoints[endpointName]\n : undefined;\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // URL parsers ignore leading control characters and spaces, drop tabs and newlines,\n // and treat backslashes like slashes, so check the URL the way it will be resolved\n const resolvedUrl = url\n .replace(/[\\t\\n\\r]/g, '')\n // eslint-disable-next-line no-control-regex -- matching control characters is the point\n .replace(/^[\\x00-\\x20]+/, '');\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (/^[/\\\\]{2}/.test(resolvedUrl)) {\n throw new Error('Protocol-relative URLs not allowed.');\n }\n\n // Prevent potential Server-Side Request Forgery attack and leakage of credentials when same instance is used for external requests\n // Any scheme counts here, as e.g. \"http:\\\\host\" or \"http:host\" can also point to another host\n const mergedConfig = /^[a-z][a-z\\d+\\-.]*:/i.test(resolvedUrl)\n ? // Merge endpoints configs for absolute URLs only if urls match\n endpointConfig?.url === url\n ? mergeConfigs(_endpointConfig, requestConfig)\n : requestConfig\n : mergeConfigs(mergeConfigs(config, _endpointConfig), requestConfig);\n\n // We prevent potential Server-Side Request Forgery attack and leakage of credentials as the same instance is not used for external requests\n // Retrigger fetch to ensure completely new instance of handler being triggered for external URLs\n return fetchf(url, mergedConfig);\n },\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 | symbol) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Symbols (e.g. inspection hooks) are never endpoints, and returning a function\n // for \"then\" would make the instance a thenable that never settles when awaited\n if (typeof prop === 'symbol' || prop === 'then') {\n return undefined;\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (hasOwn(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"]} \ No newline at end of file +{"version":3,"sources":["../../src/constants.ts","../../src/utils.ts","../../src/interceptor-manager.ts","../../src/errors/fetch-error.ts","../../src/errors/response-error.ts","../../src/timeout-wheel.ts","../../src/inflight-manager.ts","../../src/hash.ts","../../src/revalidator-manager.ts","../../src/pubsub-manager.ts","../../src/config-handler.ts","../../src/cache-manager.ts","../../src/response-parser.ts","../../src/retry-handler.ts","../../src/polling-handler.ts","../../src/upload-progress.ts","../../src/download-progress.ts","../../src/error-handler.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"names":["APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CHARSET_UTF_8","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","FUNCTION","ABORT_ERROR","TIMEOUT_ERROR","GET","HEAD","REJECT","MAX_DELAY_MS","MAX_DEPTH","hasOwn","o","k","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","key","sortObject","sortedObj","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","v","buildParams","prefix","depth","i","len","replaceUrlPathParams","urlPathParams","match","colonKey","braceKey","encoded","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","signal","resolve","done","timer","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","isPageHidden","isOffline","applyInterceptors","interceptors","args","merge","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","wheel","keyMap","position","lastTick","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","customEventProviders","setEventProvider","type","provider","removeEventHandler","addEventHandler","revalidateAll","isStaleRevalidation","isThrottled","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeRevalidator","event","handler","customProvider","cleanup","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","focusThrottleInterval","listeners","addListener","fn","set","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","merged","buildFetcherConfig","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","separator","contentTypeValue","INTERCEPTORS","baseConfig","overrideConfig","targetConfig","mergeConfig","property","mergeInterceptors","baseInterceptor","newInterceptor","base","override","isInstance","overrides","lowerKey","existingKey","_cache","stores","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADERS","generateCacheKey","config","cacheKeyCheck","headersString","keys","cacheStr","sanitizeCacheKey","bodyString","getObjectId","objectIds","lastObjectId","id","isCacheExpired","getCacheData","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","scheduleExpiry","removeExpired","store","callStore","persistCache","status","statusText","getStoredCache","isCacheBypassed","restoreCache","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","buster","getCachedResponse","cacheKey","cacheTime","handleResponseCache","output","isError","skipCache","prevCacheKey","parseResponseData","responseType","contentType","mimeType","trimmed","_error","prepareResponse","defaultResponse","mutatator","isNativeResponse","getMsFromHttpDate","dateString","getRetryAfterMs","extendedResponse","retryAfter","RATELIMIT_RESET","rateLimitResetAfter","rateLimitResetAt","withRetry","requestFn","retries","delay","backoff","maxDelay","retryOn","shouldRetry","jitter","methods","attempt","waitTime","maxRetries","cfg","onRetry","getShouldStopRetrying","retryDelay","withJitter","retryAfterMs","_b","_c","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","refreshWhenHidden","refreshWhenOffline","pollingAttempt","NULL_BODY_STATUSES","FORBIDDEN_HEADERS","isStream","toProgress","loaded","total","fetchWithUploadProgress","sendWithXhr","sendStreamed","reject","xhr","abort","settle","line","index","onAbort","stream","blob","chunk","withDownloadProgress","onDownloadProgress","counted","withErrorHandling","isCancelled","logger","redactError","strategy","SENSITIVE_HEADERS","copy","enhanceError","inFlightResponse","fetchf","cached","fetcherConfig","cancellable","isCacheEnabled","isETagEnabled","needsCacheKey","_cacheKey","initialResponse","stored","restored","toResponse","inflight","retryConfig","resetTimeout","userSignal","doRequestOnce","init","withETag","onResponse","baseRequest","_","onLoadingSlow","loadingTimeout","requestWithErrorHandling","doRequestPromise","etag","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","resolvedUrl","mergedConfig","_target","prop"],"mappings":"AAAO,IAAMA,EAA2B,cAAA,CAE3BC,EAAAA,CAAmBD,CAAAA,CAA2B,MAAA,CAC9CE,GAAgB,eAAA,CAChBC,CAAAA,CAAe,cAAA,CAEfC,CAAAA,CAAY,YACZC,EAAAA,CAAS,QAAA,CACTC,EAAS,QAAA,CACTC,CAAAA,CAAW,WAEXC,CAAAA,CAAc,YAAA,CACdC,EAAAA,CAAgB,cAAA,CAEhBC,EAAM,KAAA,CACNC,EAAAA,CAAO,MAAA,CAEPC,EAAAA,CAAS,SAGTC,EAAAA,CAAe,UAAA,CCV5B,IAAMC,EAAAA,CAAY,GAELC,CAAAA,CAAS,CAACC,EAAQC,CAAAA,GAC7B,MAAA,CAAO,UAAU,cAAA,CAAe,IAAA,CAAKD,CAAAA,CAAGC,CAAC,EAEpC,SAASC,CAAAA,CAAeC,CAAAA,CAAwB,CACrD,OAAOA,CAAAA,YAAgB,eACzB,CAQO,SAASC,EAASC,CAAAA,CAA0C,CACjE,OAAOA,CAAAA,GAAU,IAAA,EAAQ,OAAOA,CAAAA,GAAUhB,EAC5C,CA+BO,SAASiB,EAA8CC,CAAAA,CAAW,CACvE,IAAMC,CAAAA,CAAWT,CAAAA,CAAOQ,EAAK,WAAW,CAAA,CAClCE,CAAAA,CAAUV,CAAAA,CAAOQ,EAAK,aAAa,CAAA,CACnCG,EAAeX,CAAAA,CAAOQ,CAAAA,CAAK,WAAW,CAAA,CAE5C,GAAI,CAACC,CAAAA,EAAY,CAACC,CAAAA,EAAW,CAACC,CAAAA,CAC5B,OAAOH,EAIT,IAAMI,CAAAA,CAAU,EAAC,CAEjB,QAAWC,CAAAA,IAAO,MAAA,CAAO,KAAKL,CAAG,CAAA,CAC3BK,IAAQ,WAAA,EAAeA,CAAAA,GAAQ,aAAA,EAAiBA,CAAAA,GAAQ,cAC1DD,CAAAA,CAAQC,CAAG,EAAIL,CAAAA,CAAIK,CAAG,GAI1B,OAAOD,CACT,CAWO,SAASE,GAAWN,CAAAA,CAAkC,CAE3D,IAAMO,CAAAA,CAAY,MAAA,CAAO,OAAO,IAAI,CAAA,CAEpC,OAAA,MAAA,CAAO,IAAA,CAAKP,CAAG,CAAA,CACZ,IAAA,EAAK,CACL,OAAA,CAASN,GAAOa,CAAAA,CAAUb,CAAC,CAAA,CAAIM,CAAAA,CAAIN,CAAC,CAAE,CAAA,CAElCa,CACT,CASA,SAASC,GAAuBC,CAAAA,CAAiBC,CAAAA,CAA6B,CAC5E,OAAKA,EAIED,CAAAA,EAAWA,CAAAA,CAAQ,SAAS,GAAG,CAAA,CAAI,IAAM,GAAA,CAAA,CAAOC,CAAAA,CAH9CD,CAIX,CASO,SAASE,EAAAA,CAAkBC,CAAAA,CAAaC,EAA6B,CAC1E,GAAI,CAACA,CAAAA,CACH,OAAOD,CAAAA,CAIT,GAAIjB,EAAekB,CAAM,CAAA,CAAG,CAC1B,IAAMC,EAAqBD,CAAAA,CAAO,QAAA,EAAS,CAE3C,OAAOL,GAAuBI,CAAAA,CAAKE,CAAkB,CACvD,CAGA,IAAMC,EAAc,EAAC,CACfC,CAAAA,CAAS,kBAAA,CACTC,EAAM,CAACvB,CAAAA,CAAWwB,CAAAA,GAAW,CACjCA,EAAI,OAAOA,CAAAA,GAAMlC,CAAAA,CAAWkC,CAAAA,GAAMA,CAAAA,CAClCA,CAAAA,CAAIA,GAAM,IAAA,CAA0B,EAAA,CAAKA,EACzCH,CAAAA,CAAEA,CAAAA,CAAE,MAAM,CAAA,CAAIC,EAAOtB,CAAC,CAAA,CAAI,GAAA,CAAMsB,CAAAA,CAAOE,CAAC,EAC1C,CAAA,CAEMC,CAAAA,CAAc,CAACC,EAAgBpB,CAAAA,CAAUqB,CAAAA,CAAQ,IAAM,CAE3D,GAAIA,GAAS9B,EAAAA,CACX,OAAOwB,CAAAA,CAGT,IAAIO,EAAWC,CAAAA,CAAalB,CAAAA,CAE5B,GAAIe,CAAAA,CACF,GAAI,MAAM,OAAA,CAAQpB,CAAG,CAAA,CACnB,IAAKsB,EAAI,CAAA,CAAGC,CAAAA,CAAMvB,EAAI,MAAA,CAAQsB,CAAAA,CAAIC,EAAKD,CAAAA,EAAAA,CACrCH,CAAAA,CACEC,CAAAA,CAAS,GAAA,EAAO,OAAOpB,CAAAA,CAAIsB,CAAC,CAAA,GAAMxC,EAAAA,EAAUkB,EAAIsB,CAAC,CAAA,CAAIA,CAAAA,CAAI,EAAA,CAAA,CAAM,IAC/DtB,CAAAA,CAAIsB,CAAC,EACLD,CAAAA,CAAQ,CACV,UAEOxB,CAAAA,CAASG,CAAG,CAAA,CACrB,IAAKK,KAAOL,CAAAA,CACVmB,CAAAA,CAAYC,EAAS,GAAA,CAAMf,CAAAA,CAAM,IAAKL,CAAAA,CAAIK,CAAG,CAAA,CAAGgB,CAAAA,CAAQ,CAAC,CAAA,CAAA,KAG3DJ,CAAAA,CAAIG,EAAQpB,CAAG,CAAA,CAAA,KAAA,GAER,MAAM,OAAA,CAAQA,CAAG,CAAA,CAC1B,IAAKsB,EAAI,CAAA,CAAGC,CAAAA,CAAMvB,CAAAA,CAAI,MAAA,CAAQsB,EAAIC,CAAAA,CAAKD,CAAAA,EAAAA,CACrCL,CAAAA,CAAIjB,CAAAA,CAAIsB,CAAC,CAAA,CAAE,IAAA,CAAMtB,EAAIsB,CAAC,CAAA,CAAE,KAAK,CAAA,CAAA,KAG/B,IAAKjB,CAAAA,IAAOL,CAAAA,CACVmB,EAAYd,CAAAA,CAAKL,CAAAA,CAAIK,CAAG,CAAA,CAAGgB,CAAAA,CAAQ,CAAC,CAAA,CAGxC,OAAON,CACT,CAAA,CAMMD,EAJmBK,CAAAA,CAAY,EAAA,CAAIN,CAAM,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,CAIb,OAAA,CAAQ,SAAA,CAAW,IAAI,EAEnE,OAAOL,EAAAA,CAAuBI,CAAAA,CAAKE,CAAkB,CACvD,CAWO,SAASU,EAAAA,CACdZ,CAAAA,CACAa,EACQ,CACR,GAAI,CAACA,CAAAA,EAAkBb,CAAAA,CAAI,QAAQ,GAAG,CAAA,GAAM,EAAA,EAAMA,CAAAA,CAAI,QAAQ,GAAG,CAAA,GAAM,EAAA,CACrE,OAAOA,EAKT,IAAMC,CAAAA,CAASY,CAAAA,CAGf,OAAOb,EAAI,OAAA,CAAQ,mBAAA,CAAqB,CAACc,CAAAA,CAAOC,CAAAA,CAAUC,IAAa,CACrE,IAAMvB,CAAAA,CAAMsB,CAAAA,EAAYC,EAGxB,GAAIpC,CAAAA,CAAOqB,CAAAA,CAAQR,CAAG,EAAG,CACvB,IAAMP,CAAAA,CAAQe,CAAAA,CAAOR,CAAG,CAAA,CAGxB,GAA2BP,GAAU,IAAA,CAAM,CACzC,IAAM+B,CAAAA,CAAU,kBAAA,CAAmB,MAAA,CAAO/B,CAAK,CAAC,CAAA,CAGhD,GAAI+B,IAAY,GAAA,EAAOA,CAAAA,GAAY,KACjC,MAAM,IAAI,KAAA,CAAM,uCAAuC,EAGzD,OAAOA,CACT,CACF,CAEA,OAAOH,CACT,CAAC,CACH,CAWO,SAASI,GAAclB,CAAAA,CAAsB,CAClD,OAAO,0BAAA,CAA2B,KAAKA,CAAG,CAC5C,CAEO,IAAMmB,EAAU,IAAM,IAAA,CAAK,KAAI,CAEzBC,CAAAA,CAAO,IAAM,CAAC,CAAA,CAcpB,SAASC,EAAAA,CAAmBnC,EAAqB,CACtD,IAAM,EAAI,OAAOA,CAAAA,CAEjB,OAA2BA,CAAAA,EAAU,IAAA,CAC5B,KAAA,CAGL,CAAA,GAAMf,GAAU,CAAA,GAAM,QAAA,EAAY,IAAM,SAAA,EAIxC,KAAA,CAAM,QAAQe,CAAK,CAAA,CACd,IAAA,CAIP,OAAO,aAAejB,CAAAA,EACtB,OAAO,UAAA,CAAW,MAAA,GAAWA,GAC7B,UAAA,CAAW,MAAA,CAAO,QAAA,CAASiB,CAAK,GAK9BA,CAAAA,YAAiB,IAAA,EAAQH,EAAeG,CAAK,CAAA,CACxC,MAGL,CAAA,EAAAD,CAAAA,CAASC,CAAK,CAAA,GACF,OAAO,cAAA,CAAeA,CAAK,IAG3B,MAAA,CAAO,SAAA,EAKjB,OAAOA,CAAAA,CAAM,MAAA,GAAWd,CAAAA,CAAAA,CAMhC,CASO,IAAMkD,EAAAA,CAAkB,CAC7BC,EACAC,CAAAA,GAEA,IAAI,QAASC,CAAAA,EAAY,CACvB,IAAMC,CAAAA,CAAO,IAAM,CACjB,YAAA,CAAaC,CAAK,CAAA,CACdH,GACFA,CAAAA,CAAO,mBAAA,CAAoB,OAAA,CAASE,CAAI,EAE1CD,CAAAA,CAAQ,IAAI,EACd,CAAA,CACME,CAAAA,CAAQ,WAAWD,CAAAA,CAAM,IAAA,CAAK,GAAA,CAAIH,CAAAA,CAAI7C,EAAY,CAAC,CAAA,CAErD8C,CAAAA,GACEA,CAAAA,CAAO,QACTE,CAAAA,EAAK,CAELF,CAAAA,CAAO,gBAAA,CAAiB,QAASE,CAAI,CAAA,EAG3C,CAAC,CAAA,CAWI,SAASE,GAAY5C,CAAAA,CAAWyB,CAAAA,CAAQ,CAAA,CAAQ,CACrD,OAAIA,CAAAA,EAAS9B,EAAAA,CACJK,CAAAA,CAGLA,CAAAA,EAAQC,EAASD,CAAI,CAAA,EAAK,OAAOA,CAAAA,CAAK,OAASf,CAAAA,CAC1C2D,EAAAA,CAAY5C,EAAK,IAAA,CAAMyB,CAAAA,CAAQ,CAAC,CAAA,CAGlCzB,CACT,CAYO,SAAS6C,EACdC,CAAAA,CACe,CACf,GAAI,CAACA,CAAAA,CACH,OAAO,EAAC,CAGV,IAAMC,CAAAA,CAA+B,EAAC,CAItC,GAAID,aAAmB,OAAA,CACrBA,CAAAA,CAAQ,QAAQ,CAAC5C,CAAAA,CAAOO,CAAAA,GAAQ,CAC9BsC,EAActC,CAAAA,CAAI,WAAA,EAAa,CAAA,CAAIP,EACrC,CAAC,CAAA,CAAA,KAGD,IAAA,IAAWO,CAAAA,IAAOqC,EAEZlD,CAAAA,CAAOkD,CAAAA,CAASrC,CAAG,CAAA,EAAKA,CAAAA,GAAQ,cAClCsC,CAAAA,CAActC,CAAAA,CAAI,WAAA,EAAa,EAAIqC,CAAAA,CAAQrC,CAAG,GAKpD,OAAOsC,CACT,CAOO,SAASC,EAAAA,EAAqB,CAEnC,OACE,OAAO,MAAA,GAAW/D,CAAAA,EAAa,OAAO,MAAA,CAAO,gBAAA,GAAqBG,CAEtE,CAUO,SAAS6D,CAAAA,CACdC,CAAAA,CACAC,EACsB,CACtB,GAAI,OAAO,YAAA,GAAiBlE,EAC1B,OAAO,IAAI,YAAA,CAAaiE,CAAAA,CAASC,CAAI,CAAA,CAGvC,IAAMC,EAAQ,IAAI,KAAA,CAAMF,CAAO,CAAA,CAC/B,OAAAE,CAAAA,CAAM,IAAA,CAAOD,EAENC,CACT,KAMaC,EAAAA,CAAmB,IAAe,CAC7C,IAAMC,CAAAA,CAAO,OAAO,SAAA,GAAcrE,GAAc,SAAA,CAAkB,UAAA,CAElE,OAAOqE,CAAAA,EAAQ,CAAC,UAAW,IAAA,CAAM,IAAI,CAAA,CAAE,QAAA,CAASA,EAAK,aAAa,CACpE,CAAA,CAMaC,EAAAA,CAAe,IAC1B,OAAO,QAAA,GAAatE,CAAAA,EAAa,QAAA,CAAS,kBAAoB,QAAA,CAMnDuE,EAAAA,CAAY,IACvB,OAAO,SAAA,GAAcvE,GAAa,SAAA,CAAU,MAAA,GAAW,MClbzD,eAAsBwE,EAKpBC,CAAAA,CAA6B1D,CAAAA,CAAAA,GAAY2D,CAAAA,CAA2B,CACpE,GAAI,CAACD,CAAAA,CACH,OAGF,IAAME,EAAStC,CAAAA,EACbA,CAAAA,EACArB,EAASD,CAAI,CAAA,EACbC,EAASqB,CAAC,CAAA,EACV,MAAA,CAAO,MAAA,CAAOtB,EAAMG,CAAAA,CAAemB,CAAC,CAAC,CAAA,CAEvC,GAAI,OAAOoC,CAAAA,GAAiBtE,CAAAA,CAC1BwE,CAAAA,CAAM,MAAOF,CAAAA,CAA8C1D,CAAAA,CAAM,GAAG2D,CAAI,CAAC,UAChE,KAAA,CAAM,OAAA,CAAQD,CAAY,CAAA,CACnC,QAAWG,CAAAA,IAAeH,CAAAA,CACxBE,EAAM,MAAMC,CAAAA,CAAY7D,EAAM,GAAG2D,CAAI,CAAC,EAG5C,CC5BO,IAAMG,EAAAA,CAAN,cAKG,KAAM,CAwBd,YACEZ,CAAAA,CACAa,CAAAA,CACAC,CAAAA,CAMA,CACA,MAAMd,CAAO,CAAA,CAEb,IAAA,CAAK,OAAA,CAAUa,EACf,IAAA,CAAK,QAAA,CAAWC,CAAAA,CAChB,IAAA,CAAK,OAASA,CAAAA,CAAWA,CAAAA,CAAS,OAAS,CAAA,CAC3C,IAAA,CAAK,WAAaA,CAAAA,CAAWA,CAAAA,CAAS,UAAA,CAAa,EAAA,CACnD,KAAK,MAAA,CAASD,CAAAA,CACd,KAAK,WAAA,CAAc,KAAA,CACnB,KAAK,IAAA,CAAO,aACd,CACF,CAAA,CCnDO,IAAME,EAAAA,CAAN,cAKGH,EAA+D,CACvE,WAAA,CACEZ,EACAa,CAAAA,CACAC,CAAAA,CAMA,CACA,KAAA,CAAMd,EAASa,CAAAA,CAASC,CAAQ,CAAA,CAEhC,IAAA,CAAK,KAAO,gBACd,CACF,CAAA,CCDA,IAAME,GAAa,GAAA,CACbC,EAAAA,CAAS,IACTC,EAAAA,CAAyB,KAAA,CAAMF,EAAU,CAAA,CAC5C,IAAA,CAAK,CAAC,CAAA,CACN,IAAI,IAAM,EAAE,CAAA,CAETG,CAAAA,CAAS,IAAI,GAAA,CACfC,EAAAA,CAAW,CAAA,CACXC,EAAAA,CAAW,EACX5B,CAAAA,CAA+B,IAAA,CAE7B6B,GAAiB,CAAC,CAAC/D,EAAKgE,CAAQ,CAAA,GAAyB,CAC7DJ,CAAAA,CAAO,OAAO5D,CAAG,CAAA,CAEjB,GAAI,CACF,IAAMiE,CAAAA,CAASD,CAAAA,EAAS,CACpBC,CAAAA,EAAUA,aAAkB,OAAA,EAE9BA,CAAAA,CAAO,MAAMtC,CAAI,EAErB,OAAQuC,CAAAA,CAAA,CAER,CACF,CAAA,CAEaC,EAAa,CACxBnE,CAAAA,CACAoE,CAAAA,CACAtC,CAAAA,GACS,CACTuC,CAAAA,CAAcrE,CAAG,CAAA,CAIjB,IAAMsE,EAAUxC,CAAAA,CAAK4B,EAAAA,EAAUxB,GAASR,CAAAA,EAAQ,GAAMoC,GAAW,CAAA,CAAI,CAAA,CAAA,CAGrE,GAAIhC,CAAAA,CAAK4B,IAAUY,CAAAA,EAAWb,EAAAA,EAAc3B,CAAAA,CAAK4B,EAAAA,GAAW,EAAG,CAC7DE,CAAAA,CAAO,GAAA,CAAI5D,CAAAA,CAAK,CACd,UAAA,CACE+D,EAAAA,CAAe,KAAK,IAAA,CAAM,CAAC/D,EAAKoE,CAAE,CAAC,CAAA,CACnC,IAAA,CAAK,IAAItC,CAAAA,CAAI7C,EAAY,CAC3B,CACF,CAAC,EAED,MACF,CAEA,IAAMsF,CAAAA,CAAAA,CAAQV,GAAWS,CAAAA,EAAWb,EAAAA,CAEpCE,GAAMY,CAAI,CAAA,CAAE,KAAK,CAACvE,CAAAA,CAAKoE,CAAE,CAAC,EAC1BR,CAAAA,CAAO,GAAA,CAAI5D,CAAAA,CAAKuE,CAAI,EAEfrC,CAAAA,GACH4B,EAAAA,CAAWpC,CAAAA,EAAQ,CACnBQ,EAAQ,WAAA,CAAY,IAAM,CACxB2B,EAAAA,CAAAA,CAAYA,EAAAA,CAAW,GAAKJ,EAAAA,CAC5BK,EAAAA,CAAWpC,CAAAA,EAAQ,CACnB,IAAM6C,CAAAA,CAAOZ,EAAAA,CAAME,EAAQ,CAAA,CAI3B,IAAA,IAAS5C,EAAI,CAAA,CAAGA,CAAAA,CAAIsD,CAAAA,CAAK,MAAA,CAAQtD,IAC/B8C,EAAAA,CAAeQ,CAAAA,CAAKtD,CAAC,CAAC,CAAA,CAGxBsD,EAAK,MAAA,CAAS,CAAA,CAEV,CAACX,CAAAA,CAAO,MAAQ1B,CAAAA,GAClB,aAAA,CAAcA,CAAK,CAAA,CACnBA,EAAQ,IAAA,EAEZ,CAAA,CAAGwB,EAAM,CAAA,EAEb,EAEaW,CAAAA,CAAiBrE,CAAAA,EAAsB,CAClD,IAAMwE,CAAAA,CAAgBZ,EAAO,GAAA,CAAI5D,CAAG,CAAA,CAEpC,GAAIwE,IAAkB,MAAA,CAAW,CAE/B,GAAI,KAAA,CAAM,OAAA,CAAQA,CAAa,CAAA,CAC7B,YAAA,CAAaA,CAAAA,CAAc,CAAC,CAAC,CAAA,CAAA,KACxB,CACL,IAAMC,CAAAA,CAAUd,EAAAA,CAAMa,CAAa,CAAA,CAEnC,IAAA,IAASvD,CAAAA,CAAI,CAAA,CAAGA,EAAIwD,CAAAA,CAAQ,MAAA,CAAQxD,CAAAA,EAAAA,CAClC,GAAIwD,EAAQxD,CAAC,CAAA,CAAE,CAAC,CAAA,GAAMjB,EAAK,CACzByE,CAAAA,CAAQ,OAAOxD,CAAAA,CAAG,CAAC,EACnB,KACF,CAEJ,CAEA2C,CAAAA,CAAO,OAAO5D,CAAG,CAAA,CAEb,CAAC4D,CAAAA,CAAO,MAAQ1B,CAAAA,GAClB,aAAA,CAAcA,CAAK,CAAA,CACnBA,EAAQ,IAAA,EAEZ,CACF,EClGA,IAAMwC,CAAAA,CAAsC,IAAI,GAAA,CAazC,SAASC,EAAAA,CACd3E,CAAAA,CACAO,EACAqE,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACiB,CACjB,GAAI,CAAC/E,CAAAA,CACH,OAAO,IAAI,eAAA,CAGb,IAAMgF,EAAMtD,CAAAA,EAAQ,CACduD,EAAOP,CAAAA,CAAS,GAAA,CAAI1E,CAAG,CAAA,CACzBkF,EAAuC,IAAA,CAG3C,GAAID,EAAM,CACR,IAAME,EAAiBF,CAAAA,CAAK,CAAC,CAAA,CACvBG,CAAAA,CAAoBH,EAAK,CAAC,CAAA,CAGhC,GACE,CAACG,CAAAA,EACDJ,EAAMC,CAAAA,CAAK,CAAC,CAAA,CAAIJ,CAAAA,EAChB,CAACM,CAAAA,CAAe,MAAA,CAAO,OAAA,CAEvB,OAAOA,EAKLC,CAAAA,EACFD,CAAAA,CAAe,KAAA,CACb3C,CAAAA,CAAiB,6BAA8B5D,CAAW,CAC5D,EAGFyF,CAAAA,CAAcrE,CAAG,EACjBkF,CAAAA,CAAcD,CAAAA,CAAK,CAAC,EACtB,CAEA,IAAMI,CAAAA,CAAa,IAAI,eAAA,CAEvB,OAAAX,EAAS,GAAA,CAAI1E,CAAAA,CAAK,CAChBqF,CAAAA,CACAN,EACAC,CAAAA,CACAF,CAAAA,CACAI,CACF,CAAC,CAAA,CAEGH,GACFZ,CAAAA,CACEnE,CAAAA,CACA,IAAM,CACJsF,GACEtF,CAAAA,CACAwC,CAAAA,CAAiBjC,CAAAA,CAAM,yBAAA,CAA2B1B,EAAa,CACjE,EACF,CAAA,CACA+F,CACF,EAGKS,CACT,CASA,eAAsBC,EAAAA,CACpBtF,CAAAA,CACA2C,EAA8C,IAAA,CAC/B,CAEf,GAAI3C,CAAAA,CAAK,CACP,IAAMiF,CAAAA,CAAOP,EAAS,GAAA,CAAI1E,CAAG,EAEzBiF,CAAAA,GAEEtC,CAAAA,EACiBsC,CAAAA,CAAK,CAAC,EACd,KAAA,CAAMtC,CAAK,EAGxB4C,EAAAA,CAAevF,CAAG,GAEtB,CACF,CAOO,SAASuF,EAAAA,CAAevF,EAA0B,CACvDqE,CAAAA,CAAcrE,CAAI,CAAA,CAClB0E,EAAS,MAAA,CAAO1E,CAAI,EACtB,CAsBO,SAASwF,EAAAA,CACdxF,CAAAA,CACAyF,EACM,CACN,IAAMR,EAAOP,CAAAA,CAAS,GAAA,CAAI1E,CAAG,CAAA,CACzBiF,IAEFA,CAAAA,CAAK,CAAC,EAAIQ,CAAAA,EAEd,CASO,SAASC,EAAAA,CACd1F,CAAAA,CACA6E,CAAAA,CACmB,CACnB,GAAI,CAAC7E,CAAAA,CACH,OAAO,IAAA,CAGT,IAAM2F,EAAUjB,CAAAA,CAAS,GAAA,CAAI1E,CAAG,CAAA,CAEhC,OACE2F,CAAAA,EAEAA,CAAAA,CAAQ,CAAC,CAAA,EAET,CAACA,CAAAA,CAAQ,CAAC,CAAA,EAEVjE,CAAAA,GAAYiE,CAAAA,CAAQ,CAAC,EAAId,CAAAA,EAEzB,CAACc,EAAQ,CAAC,CAAA,CAAE,MAAA,CAAO,OAAA,CAEZA,EAAQ,CAAC,CAAA,CAGX,IACT,CC3MO,SAASC,EAAKC,CAAAA,CAAqB,CACxC,IAAID,CAAAA,CAAO,EAEX,IAAA,IAAS3E,CAAAA,CAAI,EAAGC,CAAAA,CAAM2E,CAAAA,CAAI,OAAQ5E,CAAAA,CAAIC,CAAAA,CAAKD,CAAAA,EAAAA,CAAK,CAC9C,IAAM6E,CAAAA,CAAOD,CAAAA,CAAI,UAAA,CAAW5E,CAAC,EAC7B2E,CAAAA,CAAQA,CAAAA,CAAO,EAAA,CAAmBE,CAAAA,CAAQ,EAC5C,CAEA,OAAO,OAAOF,CAAI,CACpB,CCoBA,IAAMG,EAAAA,CAAc,GAAA,CAAS,GAAA,CACvBC,EAAe,IAAI,GAAA,CASnBC,EAAgB,IAAI,GAAA,CAKpBC,GAAuB,IAAI,GAAA,CAS1B,SAASC,EAAAA,CACdC,EACAC,CAAAA,CACM,CACNH,GAAqB,GAAA,CAAIE,CAAAA,CAAMC,CAAQ,CAAA,CAGnCJ,CAAAA,CAAc,GAAA,CAAIG,CAAI,IACxBE,EAAAA,CAAmBF,CAAI,CAAA,CACvBG,EAAAA,CAAgBH,CAAI,CAAA,EAExB,CAWO,SAASI,EAAAA,CACdJ,EACAK,CAAAA,CAA+B,IAAA,CAC/BC,EAAuB,KAAA,CACvB,CACA,IAAMC,CAAAA,CAAYP,CAAAA,GAAS,OAAA,CAAU,CAAA,CAAI,EACnCpB,CAAAA,CAAMtD,CAAAA,GAEZsE,CAAAA,CAAa,OAAA,CAASY,GAAU,CAC9B,GAAI,CAACA,CAAAA,CAAMD,CAAS,CAAA,EAAMD,CAAAA,EAAe1B,EAAM4B,CAAAA,CAAM,CAAC,EAAIA,CAAAA,CAAM,CAAC,CAAA,CAC/D,OAGFA,EAAM,CAAC,CAAA,CAAI5B,CAAAA,CAGX,IAAM6B,EAAcJ,CAAAA,CAAsBG,CAAAA,CAAM,CAAC,CAAA,CAAIA,EAAM,CAAC,CAAA,CAExDC,GACF,OAAA,CAAQ,OAAA,CAAQA,EAAYJ,CAAmB,CAAC,CAAA,CAAE,KAAA,CAAM9E,CAAI,EAEhE,CAAC,EACH,CAUA,eAAsBmF,EAAAA,CACpB9G,CAAAA,CACAyG,CAAAA,CAA+B,KAAA,CACI,CAEnC,GAAI,CAACzG,EACH,OAAO,IAAA,CAGT,IAAM4G,CAAAA,CAAQZ,CAAAA,CAAa,GAAA,CAAIhG,CAAG,EAElC,GAAI4G,CAAAA,CAAO,CAETA,CAAAA,CAAM,CAAC,CAAA,CAAIlF,CAAAA,EAAQ,CAEnB,IAAMmF,EAAcJ,CAAAA,CAAsBG,CAAAA,CAAM,CAAC,CAAA,CAAIA,CAAAA,CAAM,CAAC,CAAA,CAG5D,GAAIC,CAAAA,CACF,OAAO,MAAMA,CAAAA,CAAYJ,CAAmB,CAEhD,CAGA,OAAO,IACT,CAOO,SAASM,EAAAA,CAAmBX,CAAAA,CAAiB,CAClDE,EAAAA,CAAmBF,CAAI,EAEvB,IAAMO,CAAAA,CAAYP,IAAS,OAAA,CAAU,CAAA,CAAI,CAAA,CAGzCJ,CAAAA,CAAa,QAAQ,CAACY,CAAAA,CAAO5G,CAAAA,GAAQ,CAC/B4G,EAAMD,CAAS,CAAA,EACjBK,EAAAA,CAAkBhH,CAAG,EAEzB,CAAC,EACH,CASA,SAASuG,EAAAA,CAAgBU,EAAkB,CACzC,GAAIhB,CAAAA,CAAc,GAAA,CAAIgB,CAAK,CAAA,CACzB,OAIF,IAAMC,CAAAA,CAAUV,EAAAA,CAAc,KAAK,IAAA,CAAMS,CAAAA,CAAO,IAAA,CAAMA,CAAAA,GAAU,OAAO,CAAA,CAGjEE,CAAAA,CAAiBjB,GAAqB,GAAA,CAAIe,CAAK,EAErD,GAAIE,CAAAA,CAAgB,CAClB,IAAMC,EAAUD,CAAAA,CAAeD,CAAO,CAAA,CAEtCjB,CAAAA,CAAc,IAAIgB,CAAAA,CAAOG,CAAO,CAAA,CAEhC,MACF,CAGI7E,EAAAA,EAAU,GACZ,OAAO,gBAAA,CAAiB0E,CAAAA,CAAOC,CAAO,CAAA,CAEtCjB,CAAAA,CAAc,GAAA,CAAIgB,CAAAA,CAAO,IAAM,MAAA,CAAO,mBAAA,CAAoBA,EAAOC,CAAO,CAAC,GAE7E,CAOA,SAASZ,EAAAA,CAAmBW,CAAAA,CAAkB,CAC5C,IAAMG,CAAAA,CAAUnB,EAAc,GAAA,CAAIgB,CAAK,EAEnCG,CAAAA,GACFA,CAAAA,EAAQ,CACRnB,CAAAA,CAAc,OAAOgB,CAAK,CAAA,EAE9B,CAcO,SAASI,GACdrH,CAAAA,CACAsH,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,EACAC,CAAAA,CACAC,CAAAA,CACAC,EACA,CAEA,IAAMhB,EAAQZ,CAAAA,CAAa,GAAA,CAAIhG,CAAG,CAAA,EAAM,EAAC,CAEzC4G,CAAAA,CAAM,CAAC,CAAA,CAAIU,EACXV,CAAAA,CAAM,CAAC,CAAA,CAAIlF,CAAAA,GACXkF,CAAAA,CAAM,CAAC,EAAWb,EAAAA,CAClBa,CAAAA,CAAM,CAAC,CAAA,CAAIY,EACXZ,CAAAA,CAAM,CAAC,CAAA,CAAIa,CAAAA,CACXb,EAAM,CAAC,CAAA,CAAIc,CAAAA,CACXd,CAAAA,CAAM,CAAC,CAAA,CAAIe,CAAAA,CACXf,EAAM,CAAC,CAAA,CAAIgB,EAEX5B,CAAAA,CAAa,GAAA,CAAIhG,CAAAA,CAAK4G,CAAK,EAEvBc,CAAAA,EACFnB,EAAAA,CAAgB,OAAO,CAAA,CAGrBoB,CAAAA,EACFpB,GAAgB,QAAQ,CAAA,CAGtBiB,CAAAA,EACFrD,CAAAA,CAAW,KAAOnE,CAAAA,CAAK8G,EAAAA,CAAW,KAAK,IAAA,CAAM9G,CAAAA,CAAK,IAAI,CAAA,CAAGwH,CAAAA,CAAY,GAAI,EAE7E,CAEO,SAASR,EAAAA,CAAkBhH,CAAAA,CAAa,CAC7CgG,EAAa,MAAA,CAAOhG,CAAG,CAAA,CAGvBqE,CAAAA,CAAc,KAAOrE,CAAG,EAC1B,CC7OA,IAAM6H,EAAAA,CAAY,IAAI,GAAA,CAGf,SAASC,EAAAA,CAAqB9H,CAAAA,CAAa+H,EAAuB,CACvE,IAAIC,EAAMH,EAAAA,CAAU,GAAA,CAAI7H,CAAG,CAAA,CAEtBgI,CAAAA,EACHH,EAAAA,CAAU,GAAA,CAAI7H,EAAMgI,CAAAA,CAAM,IAAI,GAAM,CAAA,CAGtCA,CAAAA,CAAI,IAAID,CAAE,EACZ,CAEO,SAASE,GAAkBjI,CAAAA,CAAa+H,CAAAA,CAAiB,CAC9D,IAAMC,EAAMH,EAAAA,CAAU,GAAA,CAAI7H,CAAG,CAAA,CAEzBgI,IACFA,CAAAA,CAAI,MAAA,CAAOD,CAAE,CAAA,CAGTC,CAAAA,CAAI,OAAS,CAAA,EACfH,EAAAA,CAAU,MAAA,CAAO7H,CAAG,GAG1B,CAEO,SAASkI,EAAqBlI,CAAAA,CAAauD,CAAAA,CAAa,CAC7D,IAAM4E,CAAAA,CAAMN,EAAAA,CAAU,GAAA,CAAI7H,CAAG,CAAA,CAE7B,GAAImI,EACF,GAAIA,CAAAA,CAAI,OAAS,CAAA,CAAG,CAElB,IAAMJ,CAAAA,CAAKI,EAAI,MAAA,EAAO,CAAE,IAAA,EAAK,CAAE,MAC/BJ,CAAAA,CAAIxE,CAAQ,EACd,CAAA,KACE4E,EAAI,OAAA,CAASJ,CAAAA,EAAOA,EAAGxE,CAAQ,CAAC,EAGtC,CAEO,SAAS6E,EAAAA,CAAapI,CAAAA,CAAoB+H,EAA2B,CAC1E,OAAK/H,CAAAA,EAKL8H,EAAAA,CAAe9H,EAAK+H,CAAE,CAAA,CAGf,IAAM,CACXE,GAAejI,CAAAA,CAAK+H,CAAE,EACxB,CAAA,EARSpG,CASX,CCnDA,IAAM0G,EAAAA,CAAAA,CAAoBzF,EAAAA,EAAiB,CAAI,GAAK,EAAA,EAAM,GAAA,CAE7C0F,CAAAA,CAA+B,CAC1C,SAAUtJ,EAAAA,CACV,OAAA,CAASqJ,EAAAA,CACT,cAAA,CAAgBA,GAAmB,EAAA,CACnC,qBAAA,CAAuB,IACvB,OAAA,CAAS,CACP,OAAQhK,EAAAA,CAAmB,mBAAA,CAC3B,iBAAA,CAAmB,mBACrB,EACA,KAAA,CAAO,CACL,MAAOgK,EAAAA,CAAmB,EAAA,CAC1B,SAAUA,EAAAA,CACV,YAAA,CAAc,IAAA,CACd,OAAA,CAAS,IAGT,OAAA,CAAS,CACP,IACA,GAAA,CACA,GAAA,CACA,IACA,GAAA,CACA,GAAA,CACA,GAAA,CACA,GACF,EAGA,OAAA,CAAS,CAACvJ,CAAAA,CAAKC,EAAAA,CAAM,MAAO,QAAA,CAAU,SAAA,CAAW,OAAO,CAC1D,CACF,CAAA,CAQO,SAASwJ,GACdC,CAAAA,CACwB,CACxB,IAAMC,CAAAA,CAAY/I,CAAAA,CAAe8I,CAAY,CAAA,CAG7C,OAAOE,CAAAA,CACL,CAAE,MAAOJ,CAAAA,CAAc,KAAA,CAAO,QAASA,CAAAA,CAAc,OAAQ,CAAA,CAC7DG,CAAAA,CACAH,CACF,CACF,CAOO,SAASK,EAAAA,EAAkC,CAChD,OAAO,CAAE,GAAGL,CAAc,CAC5B,CASO,SAASM,EAAAA,CACdrI,CAAAA,CACAsI,CAAAA,CAMmE,CAGnE,IAAMC,CAAAA,CAASJ,CAAAA,CACbJ,CAAAA,CACAO,EAAYnJ,CAAAA,CAAemJ,CAAS,EAAI,EAC1C,EAEA,OAAOE,EAAAA,CAAmBxI,CAAAA,CAAKuI,CAAM,CACvC,CASO,SAASC,GACdxI,CAAAA,CACAyI,CAAAA,CACe,CA9HjB,IAAAC,CAAAA,CA+HE,IAAIC,CAAAA,CAASF,EAAc,MAAA,CAC3BE,CAAAA,CAASA,EAAUA,CAAAA,CAAO,WAAA,GAA2BpK,CAAAA,CAErD,IAAIqK,CAAAA,CAGAD,CAAAA,GAAWpK,GAAOoK,CAAAA,GAAWnK,EAAAA,GAC/BoK,CAAAA,CAAAA,CAAOF,CAAAA,CAAAD,EAAc,IAAA,GAAd,IAAA,CAAAC,CAAAA,CAAsBD,CAAAA,CAAc,KAGvCG,CAAAA,EAAQ,OAAOA,IAASzK,CAAAA,EAAUkD,EAAAA,CAAmBuH,CAAI,CAAA,GAC3DA,CAAAA,CAAO,IAAA,CAAK,SAAA,CAAUA,CAAI,CAAA,CAAA,CAAA,CAI9BC,EAAAA,CAAuBJ,EAAc,OAAA,CAASG,CAAI,EAGlD,IAAME,CAAAA,CAAcL,CAAAA,CAAc,eAAA,CAC9B,UACAA,CAAAA,CAAc,WAAA,CAGZM,EAAanI,EAAAA,CAAqBZ,CAAAA,CAAKyI,EAAc,aAAa,CAAA,CAClEO,CAAAA,CAAUjJ,EAAAA,CAAkBgJ,EAAYN,CAAAA,CAAc,MAAM,CAAA,CAE5DQ,CAAAA,CADY/H,GAAclB,CAAG,CAAA,CAE/B,EAAA,CACAyI,CAAAA,CAAc,SAAWA,CAAAA,CAAc,MAAA,EAAU,GAI/CS,CAAAA,CACJD,CAAAA,EAAWD,GAAW,CAACC,CAAAA,CAAQ,QAAA,CAAS,GAAG,GAAK,CAAC,QAAA,CAAS,KAAKD,CAAO,CAAA,CAClE,IACA,EAAA,CAEN,OAAAP,CAAAA,CAAc,GAAA,CAAMQ,EAAUC,CAAAA,CAAYF,CAAAA,CAC1CP,EAAc,MAAA,CAASE,CAAAA,CACvBF,EAAc,WAAA,CAAcK,CAAAA,CAC5BL,CAAAA,CAAc,IAAA,CAAOG,EAEdH,CACT,CAWA,SAASI,EAAAA,CACP/G,EACA8G,CAAAA,CACM,CAON,GALI,CAAC9G,GAAW,CAAC8G,CAAAA,EAMfA,aAAgB,QAAA,EACf,OAAO,OAAS3K,CAAAA,EAAa2K,CAAAA,YAAgB,IAAA,EAC7C,OAAO,iBAAmB3K,CAAAA,EAAa2K,CAAAA,YAAgB,eAExD,OAGF,IAAIO,EAEJ,GAAIpK,CAAAA,CAAe6J,CAAI,CAAA,CACrBO,EAAmBtL,CAAAA,CAA2B,uBAAA,CAAA,KAAA,GACrC+K,aAAgB,WAAA,EAAe,WAAA,CAAY,OAAOA,CAAI,CAAA,CAC/DO,CAAAA,CAAmBtL,CAAAA,CAA2B,uBACrCwD,EAAAA,CAAmBuH,CAAI,CAAA,CAChCO,CAAAA,CAAmBrL,GAAmB,GAAA,CAAMC,EAAAA,CAAAA,KAG5C,OAGE+D,CAAAA,YAAmB,QAChBA,CAAAA,CAAQ,GAAA,CAAI9D,CAAY,CAAA,EAC3B8D,CAAAA,CAAQ,IAAI9D,CAAAA,CAAcmL,CAAgB,CAAA,CAG5ClK,CAAAA,CAAS6C,CAAO,CAAA,EAChB,CAAC,MAAM,OAAA,CAAQA,CAAO,GAEtB,CAACD,CAAAA,CAAeC,CAAwB,CAAA,CAAE9D,EAAa,WAAA,EAAa,IAEpE8D,CAAAA,CAAQ9D,CAAY,EAAImL,CAAAA,EAE5B,CAGA,IAAMC,EAAAA,CAAe,CACnB,WAAA,CACA,YAAA,CACA,SAAA,CACA,eACF,EAmBO,SAASjB,CAAAA,CACdkB,CAAAA,CACAC,CAAAA,CACAC,EAA8B,EAAC,CAChB,CACf,MAAA,CAAO,MAAA,CAAOA,EAAcF,CAAAA,CAAYC,CAAc,CAAA,CAGtDE,EAAAA,CAAY,QAASH,CAAAA,CAAYC,CAAAA,CAAgBC,CAAY,CAAA,CAC7DC,GAAY,SAAA,CAAWH,CAAAA,CAAYC,CAAAA,CAAgBC,CAAY,EAG/D,IAAA,IAAWE,CAAAA,IAAYL,GACrBM,EAAAA,CAAkBD,CAAAA,CAAUJ,EAAYC,CAAAA,CAAgBC,CAAY,CAAA,CAGtE,OAAOA,CACT,CAKA,SAASG,EAAAA,CAIPD,CAAAA,CACAJ,EACAC,CAAAA,CACAC,CAAAA,CACM,CACN,IAAMI,EAAkBN,CAAAA,CAAWI,CAAQ,EACrCG,CAAAA,CAAiBN,CAAAA,CAAeG,CAAQ,CAAA,CAE1CE,CAAAA,EAAmBC,CAAAA,CAErBL,CAAAA,CAAaE,CAAQ,CAAA,CACnBA,CAAAA,GAAa,aACT,EAAC,CAAE,OAAOG,CAAAA,CAAyBD,CAAwB,CAAA,CAC3D,GAAG,MAAA,CAAOA,CAAAA,CAA0BC,CAAuB,CAAA,CAAA,CAExDD,CAAAA,EAAmBC,KAC5BL,CAAAA,CAAaE,CAAQ,CAAA,CAAIE,CAAAA,EAAmBC,GAEhD,CAUO,SAASJ,EAAAA,CACdC,CAAAA,CACAJ,EACAC,CAAAA,CACAC,CAAAA,CACM,CACN,IAAMM,EAAOR,CAAAA,CAAWI,CAAQ,EAC1BK,CAAAA,CAAWR,CAAAA,CAAeG,CAAQ,CAAA,CAExC,GAAIK,CAAAA,CACF,GAAIL,IAAa,SAAA,CAAW,CAE1B,IAAMM,CAAAA,CACHF,CAAAA,YAA4D,SAC5DC,CAAAA,YACC,OAAA,CACEvB,CAAAA,CAAwBwB,CAAAA,CAC1BlI,EAAegI,CAAI,CAAA,CACnB,CAAE,GAAIA,CAAuB,EAC3BG,CAAAA,CAA2BD,CAAAA,CAC7BlI,CAAAA,CAAeiI,CAAQ,EACvB3K,CAAAA,CAAe2K,CAAyB,CAAA,CAG5C,IAAA,IAAWrK,KAAO,MAAA,CAAO,IAAA,CAAKuK,CAAS,CAAA,CAAG,CACxC,IAAMC,CAAAA,CAAWxK,EAAI,WAAA,EAAY,CAEjC,QAAWyK,CAAAA,IAAe3B,CAAAA,CACpB2B,CAAAA,CAAY,WAAA,KAAkBD,CAAAA,EAChC,OAAO1B,EAAO2B,CAAW,CAAA,CAI7B3B,EAAO9I,CAAG,CAAA,CAAIuK,CAAAA,CAAUvK,CAAG,EAC7B,CAEA8J,CAAAA,CAAaE,CAAQ,CAAA,CAAIlB,EAC3B,MACEgB,CAAAA,CAAaE,CAAQ,CAAA,CAAI,CACvB,GAAGI,CAAAA,CACH,GAAG1K,CAAAA,CAAe2K,CAAmC,CACvD,CAAA,CAAA,KAGFA,CAAAA,GAAa,MAAA,EACb7K,CAAAA,CAAS4K,CAAI,CAAA,EACb,EAAGA,aAA4C,OAAA,CAAA,GAG/CN,CAAAA,CAAaE,CAAQ,CAAA,CAAI,CAAE,GAAGI,CAAK,GAEvC,CClUA,IAAMM,CAAAA,CAAS,IAAI,IAEbC,EAAAA,CAAS,IAAI,GAAA,CACbC,EAAAA,CAAY,IACZC,EAAAA,CAAqB,EAAA,CACrBC,GAA6B,sBAAA,CAC7BC,EAAAA,CAA2B,sBAgB3BC,EAAAA,CACJ,oNAAA,CA0BK,SAASC,EAAAA,CACdC,EACAC,CAAAA,CAAgB,IAAA,CACR,CAGR,IAAMnL,EAAMkL,CAAAA,CAAO,QAAA,CAEnB,GAAIlL,CAAAA,EAAOmL,EACT,OAAO,OAAOnL,IAAQtB,CAAAA,CACjBsB,CAAAA,CACAA,EAAyBkL,CAAM,CAAA,CAGtC,GAAM,CACJ,IAAA3K,CAAAA,CAAM,EAAA,CACN,OAAA2I,CAAAA,CAASpK,CAAAA,CACT,QAAAuD,CAAAA,CAAU,IAAA,CACV,IAAA,CAAA8G,CAAAA,CAAO,KACP,WAAA,CAAAE,CAAAA,CAAc,aAChB,CAAA,CAAI6B,CAAAA,CAIAE,EAAgB,EAAA,CACpB,GAAI/I,CAAAA,CAAS,CACX,IAAI1C,CAAAA,CAEA0C,CAAAA,YAAmB,OAAA,CACrB1C,CAAAA,CAAMyC,EAAeC,CAAO,CAAA,CAE5B1C,CAAAA,CAAM0C,CAAAA,CAKR,IAAMgJ,CAAAA,CAAO,MAAA,CAAO,KAAK1L,CAAG,CAAA,CACtBuB,EAAMmK,CAAAA,CAAK,MAAA,CAGbnK,CAAAA,CAAM,CAAA,EACRmK,EAAK,IAAA,EAAK,CAGZ,IAAIxF,CAAAA,CAAM,EAAA,CACV,QAAS5E,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIC,CAAAA,CAAK,EAAED,CAAAA,CACrB+J,EAAAA,CAAkB,KAAKK,CAAAA,CAAKpK,CAAC,CAAC,CAAA,GAChC4E,CAAAA,EAAOwF,CAAAA,CAAKpK,CAAC,EAAI,GAAA,CAAMtB,CAAAA,CAAI0L,CAAAA,CAAKpK,CAAC,CAAC,CAAA,CAAI,GAAA,CAAA,CAI1CmK,CAAAA,CAAgBxF,CAAAA,CAAKC,CAAG,EAC1B,CAIA,IAAMyF,CAAAA,CACJpC,CAAAA,CACA0B,GACArK,CAAAA,CACAqK,EAAAA,CACAvB,CAAAA,CACAuB,EAAAA,CACAQ,EAGF,GAAIlC,CAAAA,GAAWpK,EACb,OAAOyM,EAAAA,CAAiBD,CAAQ,CAAA,CAGlC,IAAIE,CAAAA,CAAa,EAAA,CACjB,GAAIrC,CAAAA,CACF,GAAI,OAAOA,CAAAA,GAASzK,CAAAA,EAAUY,EAAe6J,CAAI,CAAA,CAAG,CAClD,IAAMtD,EAAM,MAAA,CAAOsD,CAAI,CAAA,CAEvBqC,CAAAA,CAAa3F,EAAI,MAAA,CAASgF,EAAAA,CAAqBhF,CAAAA,CAAMD,CAAAA,CAAKC,CAAG,EAC/D,CAAA,KAAA,GAAWsD,aAAgB,QAAA,CACzBA,CAAAA,CAAK,QAAQ,CAAC1J,CAAAA,CAAOO,CAAAA,GAAQ,CAE3BwL,GACExL,CAAAA,CACA,GAAA,EACC,OAAOP,CAAAA,GAAUf,EAASe,CAAAA,CAAQ,GAAA,CAAMgM,EAAAA,CAAYhM,CAAa,GAClE,IACJ,CAAC,EAEG+L,CAAAA,CAAW,MAAA,CAASX,KACtBW,CAAAA,CAAa5F,CAAAA,CAAK4F,CAAU,CAAA,CAAA,CAAA,KAAA,GAErBhM,EAAS2J,CAAI,CAAA,EAAK,CAACvH,EAAAA,CAAmBuH,CAAI,CAAA,CAGnDqC,CAAAA,CAAa,GAAA,CAAMC,EAAAA,CAAYtC,CAAI,CAAA,CAAA,KAC9B,CACL,IAAM/J,CAAAA,CAAII,CAAAA,CAAS2J,CAAI,CAAA,CACnB,IAAA,CAAK,SAAA,CAAUlJ,EAAAA,CAAWkJ,CAAI,CAAC,CAAA,CAC/B,OAAOA,CAAI,CAAA,CAEfqC,EAAapM,CAAAA,CAAE,MAAA,CAASyL,EAAAA,CAAqBjF,CAAAA,CAAKxG,CAAC,CAAA,CAAIA,EACzD,CAGF,OAAOmM,EAAAA,CAAiBD,EAAWV,EAAAA,CAAYY,CAAU,CAC3D,CAEA,IAAME,EAAAA,CAAY,IAAI,OAAA,CAClBC,EAAAA,CAAe,EAQnB,SAASF,EAAAA,CAAY9L,CAAAA,CAAqB,CACxC,IAAIiM,CAAAA,CAAKF,EAAAA,CAAU,IAAI/L,CAAG,CAAA,CAE1B,OAAKiM,CAAAA,EACHF,EAAAA,CAAU,GAAA,CAAI/L,CAAAA,CAAMiM,EAAK,EAAED,EAAa,EAGnCC,CACT,CAUA,SAASL,EAAAA,CAAiBD,CAAAA,CAA0B,CAClD,OAAOP,GAAyB,IAAA,CAAKO,CAAQ,EACzCA,CAAAA,CAAS,OAAA,CAAQR,GAA4B,EAAE,CAAA,CAC7CF,EAAAA,CACAhF,CAAAA,CAAK0F,CAAQ,CAAA,CACfA,CACN,CAQA,SAASO,GAAejF,CAAAA,CAAiC,CAEvD,OAAKA,CAAAA,CAAM,OAIJlF,CAAAA,EAAQ,CAAIkF,EAAM,MAAA,CAHhB,KAIX,CAQO,SAASkF,EAAAA,CAMd9L,CAAAA,CAC0E,CAC1E,GAAI,CAACA,CAAAA,CACH,OAAO,IAAA,CAGT,IAAM4G,EAAQ8D,CAAAA,CAAO,GAAA,CAAI1K,CAAG,CAAA,CAE5B,OAAO4G,CAAAA,CAAQA,CAAAA,CAAM,KAAO,IAC9B,CAQO,SAASmF,EAAAA,CACd/L,CAAAA,CAMY,CACZ,OAAO0K,EAAO,GAAA,CAAI1K,CAAa,CACjC,CAUO,SAASgM,EAAAA,CACdhM,CAAAA,CACAT,CAAAA,CACAgI,CAAAA,CACAC,EACM,CACN,GAAID,IAAQ,CAAA,CAAG,CACb0E,GAAYjM,CAAG,CAAA,CACf,MACF,CAEA,IAAMkM,CAAAA,CAAOxK,CAAAA,GACPyK,CAAAA,CAAQ5E,CAAAA,CAAMA,EAAM,GAAA,CAAO,CAAA,CAC3B6E,CAAAA,CAAc5E,CAAAA,CAAYA,EAAY,GAAA,CAAO,CAAA,CAEnDkD,EAAO,GAAA,CAAI1K,CAAAA,CAAK,CACd,IAAA,CAAAT,CAAAA,CACA,IAAA,CAAA2M,CAAAA,CACA,MAAOE,CAAAA,CAAc,CAAA,CAAIF,CAAAA,CAAOE,CAAAA,CAAc,OAC9C,MAAA,CAAQ7E,CAAAA,GAAQ,EAAA,CAAK,MAAA,CAAY2E,EAAOC,CAC1C,CAAC,EAEGA,CAAAA,CAAQ,CAAA,EACVE,GAAerM,CAAAA,CAAKmM,CAAK,EAE7B,CAQA,SAASE,EAAAA,CAAerM,CAAAA,CAAa8B,EAAkB,CACrDqC,CAAAA,CAAW,KAAOnE,CAAAA,CAAK,IAAMiM,EAAAA,CAAYjM,CAAAA,CAAK,IAAI,CAAA,CAAG8B,CAAE,EACzD,CAQO,SAASmK,GAAYjM,CAAAA,CAAasM,CAAAA,CAAyB,KAAA,CAAa,CAC7E,GAAIA,CAAAA,CAAe,CACjB,IAAM1F,CAAAA,CAAQmF,GAAS/L,CAAG,CAAA,CAG1B,GAAI,CAAC4G,GAAS,CAACiF,EAAAA,CAAejF,CAAK,CAAA,CACjC,MAEJ,CAEA8D,CAAAA,CAAO,MAAA,CAAO1K,CAAG,CAAA,CAEjB,IAAMuM,CAAAA,CAAQ5B,EAAAA,CAAO,IAAI3K,CAAG,CAAA,CAExBuM,IACF5B,EAAAA,CAAO,MAAA,CAAO3K,CAAG,CAAA,CACjBwM,GAAU,IAAMD,CAAAA,CAAM,OAAOvM,CAAG,CAAC,GAErC,CAeA,SAASwM,EAAAA,CAAUzE,CAAAA,CAAyB,CAC1C,GAAI,CACF,OAAA,CAAQ,OAAA,CAAQA,GAAI,CAAA,CAAE,KAAA,CAAMpG,CAAI,EAClC,CAAA,MAAQuC,CAAAA,CAAA,CAER,CACF,CAQA,SAASuI,EAAAA,CAAazM,CAAAA,CAAauM,CAAAA,CAA0B,CAC3D,IAAM3F,CAAAA,CAAQ8D,CAAAA,CAAO,IAAI1K,CAAG,CAAA,CAE5B,GAAIuM,CAAAA,EAAS3F,CAAAA,CAAO,CAClB,GAAM,CAAE,IAAA,CAAArH,CAAAA,CAAM,OAAAmN,CAAAA,CAAQ,UAAA,CAAAC,EAAY,OAAA,CAAAtK,CAAQ,CAAA,CAAIuE,CAAAA,CAAM,KAEpD+D,EAAAA,CAAO,GAAA,CAAI3K,CAAAA,CAAKuM,CAAK,EACrBC,EAAAA,CAAU,IACRD,CAAAA,CAAM,GAAA,CAAIvM,EAAK,CAAE,GAAG4G,EAAO,IAAA,CAAM,CAAE,KAAArH,CAAAA,CAAM,MAAA,CAAAmN,CAAAA,CAAQ,UAAA,CAAAC,EAAY,OAAA,CAAAtK,CAAQ,CAAE,CAAC,CAC1E,EACF,CACF,CAUA,eAAsBuK,GACpB5M,CAAAA,CACAgJ,CAAAA,CAC4C,CAC5C,IAAMuD,CAAAA,CAAQvD,EAAc,UAAA,CAE5B,GAAI,CAACuD,CAAAA,EAASM,GAAgB7D,CAAa,CAAA,CACzC,OAAO,IAAA,CAGT,IAAIpC,CAAAA,CAEJ,GAAI,CACFA,CAAAA,CAAQ,MAAM2F,CAAAA,CAAM,GAAA,CAAIvM,CAAG,EAC7B,CAAA,MAAQkE,EAAA,CAEN,OAAO,IACT,CAGA,OAAI,CAAC0C,CAAAA,EAAS8D,EAAO,GAAA,CAAI1K,CAAG,EACnB,IAAA,CAGL6L,EAAAA,CAAejF,CAAK,CAAA,EACtB4F,GAAU,IAAMD,CAAAA,CAAM,OAAOvM,CAAG,CAAC,EAE1B,IAAA,EAGF4G,CACT,CAUO,SAASkG,GACd9M,CAAAA,CACA4G,CAAAA,CACA2F,CAAAA,CACS,CACT,OAAA7B,CAAAA,CAAO,GAAA,CAAI1K,CAAAA,CAAK4G,CAAK,EACrB+D,EAAAA,CAAO,GAAA,CAAI3K,EAAKuM,CAAK,CAAA,CAEjB3F,EAAM,MAAA,EACRyF,EAAAA,CAAerM,CAAAA,CAAK4G,CAAAA,CAAM,OAASlF,CAAAA,EAAS,EAG9CwG,CAAAA,CAAkBlI,CAAAA,CAAK4G,EAAM,IAAI,CAAA,CAE1B,CAACA,CAAAA,CAAM,OAASlF,CAAAA,EAAQ,CAAIkF,EAAM,KAC3C,CASA,eAAsBmG,EAAAA,CAMpB/M,CAAAA,CACAgN,CAAAA,CACAC,CAAAA,CAMQ,CAER,GAAI,CAACjN,CAAAA,CACH,OAAO,KAGT,IAAM4G,CAAAA,CAAQmF,EAAAA,CACZ/L,CACF,EAEA,GAAI,CAAC4G,EACH,OAAO,IAAA,CAGT,IAAMsG,CAAAA,CAAc1N,CAAAA,CAASwN,CAAO,CAAA,CAAItN,EAAesN,CAAO,CAAA,CAAIA,EAE5DG,CAAAA,CAAkB,CACtB,GAAGvG,CAAAA,CAAM,IAAA,CACT,IAAA,CAAMsG,CACR,EAGM7K,CAAAA,CAAU8K,CAAAA,CAAgB,QAE5B9K,CAAAA,EAAWA,CAAAA,CAAQ,OACrB8K,CAAAA,CAAgB,OAAA,CAAU,CAAE,GAAG9K,CAAQ,CAAA,CACvC,OAAO8K,CAAAA,CAAgB,OAAA,CAAQ,MAGjC,IAAMC,CAAAA,CAAe,CACnB,GAAGxG,EACH,IAAA,CAAMuG,CACR,EAMA,OAJAzC,CAAAA,CAAO,IAAI1K,CAAAA,CAAKoN,CAAY,CAAA,CAC5BX,EAAAA,CAAazM,EAAK2K,EAAAA,CAAO,GAAA,CAAI3K,CAAG,CAAC,EACjCkI,CAAAA,CAAkBlI,CAAAA,CAAKmN,CAAe,CAAA,CAElCF,GAAYA,CAAAA,CAAS,OAAA,CAChB,MAAMnG,EAAAA,CAAW9G,CAAG,EAGtB,IACT,CAQO,SAAS6M,EAAAA,CAAgB7D,EAAuC,CACrE,IAAMqE,CAAAA,CAASrE,CAAAA,CAAc,aAAeV,CAAAA,CAAc,WAAA,CAE1D,OACE,CAAC,EAAE+E,CAAAA,EAAUA,CAAAA,CAAOrE,CAAa,CAAA,CAAA,EAAMA,CAAAA,CAAc,QAAU,QAEnE,CAcO,SAASsE,EAAAA,CAMdC,EACAC,CAAAA,CACAxE,CAAAA,CAM0E,CAM1E,GAJI,CAACuE,GAAYC,CAAAA,GAAc,MAAA,EAAaA,CAAAA,GAAc,IAAA,EAItDX,GAAgB7D,CAAa,CAAA,CAC/B,OAAO,IAAA,CAIT,IAAMpC,EAAQmF,EAAAA,CACZwB,CACF,CAAA,CAEA,GAAI,CAAC3G,CAAAA,CACH,OAAO,IAAA,CAMT,GAHkBiF,GAAejF,CAAK,CAAA,CAIpC,OAAAqF,EAAAA,CAAYsB,CAAQ,CAAA,CACb,IAAA,CAGT,IAAMhO,CAAAA,CAAOqH,CAAAA,CAAM,KAInB,OAAOrH,CAAAA,EAAQA,CAAAA,CAAK,UAAA,CAAa,KAAOA,CAC1C,CASO,SAASkO,EAAAA,CAMdC,CAAAA,CACA1E,EAMA2E,CAAAA,CAAmB,KAAA,CACb,CAEN,IAAMJ,EAAWvE,CAAAA,CAAc,QAAA,CAE/B,GAAIuE,CAAAA,CAAU,CACZ,IAAMC,CAAAA,CAAYxE,CAAAA,CAAc,SAAA,CAC1B4E,CAAAA,CAAY5E,EAAc,SAAA,CAGhC,GACEwE,CAAAA,GACC,CAACG,GAAW3E,CAAAA,CAAc,WAAA,CAAA,EAC3B,EAAE4E,CAAAA,EAAaA,EAAUF,CAAAA,CAAQ1E,CAAa,GAE9CgD,EAAAA,CAASuB,CAAAA,CAAUG,EAAQF,CAAAA,CAAWxE,CAAAA,CAAc,SAAS,CAAA,CAGxD2E,GACHlB,EAAAA,CAAac,CAAAA,CAAUvE,EAAc,UAAU,CAAA,CAAA,KAE5C,CACL,IAAMpC,CAAAA,CAAQmF,EAAAA,CAASwB,CAAQ,EAG3B3G,CAAAA,EAASA,CAAAA,CAAM,MAAQA,CAAAA,CAAM,IAAA,CAAK,YACpCqF,EAAAA,CAAYsB,CAAQ,EAExB,CAEArF,EAAkBqF,CAAAA,CAAUG,CAAM,CAAA,CAClCnI,EAAAA,CAAegI,CAAQ,CAAA,CAEvB,IAAMM,CAAAA,CAAe7E,CAAAA,CAAc,SAE/B6E,CAAAA,EACFtI,EAAAA,CAAesI,CAAY,EAE/B,CACF,CCnnBA,eAAsBC,EAAAA,CAMpBvK,CAAAA,CACAwK,CAAAA,CACc,CAEd,GAAI,CAACxK,CAAAA,CACH,OAAO,KAIT,IAAMlB,CAAAA,CAAWkB,CAAAA,CAAsB,OAAA,CACnCyK,EAAc3L,CAAAA,EAAWA,CAAAA,CAAQ,IAAI9D,CAAY,CAAA,CAEjDyP,EAEFA,CAAAA,CAAcA,CAAAA,CAAY,WAAA,EAAY,CAAE,MAAK,CAE7CA,CAAAA,CAAc,EAAA,CAIhB,IAAMC,EAAWD,CAAAA,CAAY,KAAA,CAAM,GAAA,CAAK,CAAC,EAAE,CAAC,CAAA,CAExCzO,EAEJ,GAAI,CACF,GAAIwO,CAAAA,CAEFxO,CAAAA,CACEwO,CAAAA,GAAiB,QAAA,CACbxK,EAAS,IAAA,CACT,MAAMA,EAASwK,CAAY,CAAA,WAEjCE,CAAAA,CAAS,QAAA,CAAS5P,EAAgB,CAAA,EAClC4P,EAAS,QAAA,CAAS,OAAO,EAEzB1O,CAAAA,CAAO,MAAMgE,EAAS,IAAA,EAAK,CAAA,KAAA,GAAA,CAE1B0K,CAAAA,CAAS,QAAA,CAAS,qBAAqB,CAAA,EACtCA,CAAAA,CAAS,QAAA,CACP7P,CAAAA,CAA2B,uBAC7B,CAAA,GACF,OAAOmF,CAAAA,CAAS,QAAA,GAAa5E,EAE7BY,CAAAA,CAAO,MAAMgE,EAAS,QAAA,EAAS,CAAA,KAAA,GACtB,8CAA8C,IAAA,CAAK0K,CAAQ,CAAA,CACpE1O,CAAAA,CAAO,MAAMgE,CAAAA,CAAS,WAAA,WAEtBhE,CAAAA,CAAO,MAAMgE,EAAS,IAAA,EAAK,CAEvB,OAAOhE,CAAAA,GAASb,EAAQ,CAC1B,IAAMwP,EAAU3O,CAAAA,CAAK,IAAA,GACrB,GACG2O,CAAAA,CAAQ,UAAA,CAAW,GAAG,GAAKA,CAAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAC/CA,EAAQ,UAAA,CAAW,GAAG,CAAA,EAAKA,CAAAA,CAAQ,SAAS,GAAG,CAAA,CAEhD,GAAI,CACF3O,CAAAA,CAAO,KAAK,KAAA,CAAM2O,CAAO,EAC3B,CAAA,MAAQhK,EAAA,CAER,CAEJ,CAGJ,CAAA,MAASiK,CAAAA,CAAQ,CAEf5O,CAAAA,CAAO,KACT,CAEA,OAAOA,CACT,CAUO,IAAM6O,GAAkB,CAM7B7K,CAAAA,CAMA2H,EACAvI,CAAAA,CAKW,IAAA,GAC2D,CACtE,IAAM0L,EAAkBnD,CAAAA,CAAO,eAAA,CACzBqC,CAAAA,CAAWrC,CAAAA,CAAO,SAClBoD,CAAAA,CAAYvB,EAAAA,CAAO,IAAA,CAAK,IAAA,CAAMQ,CAAkB,CAAA,CAQtD,GAAI,CAAChK,CAAAA,CACH,OAAO,CACL,EAAA,CAAI,KAAA,CAEJ,KAAA,CAAAZ,CAAAA,CACA,KAAM0L,CAAAA,EAAA,IAAA,CAAAA,EAAmB,IAAA,CACzB,OAAA,CAAS,KACT,MAAA,CAAAnD,CAAAA,CACA,MAAA,CAAQoD,CAAAA,CACR,WAAY,KAAA,CACZ,SAAA,CAAW,MACX,OAAA,CAAS,IACX,EAQF,IAAMC,CAAAA,CACJ,OAAO,QAAA,GAAa5P,GAAY4E,CAAAA,YAAoB,QAAA,CAElDhE,CAAAA,CAAOgE,CAAAA,CAAS,KAKlB8K,CAAAA,GAAoB,MAAA,GAElB9O,CAAAA,EAAS,IAAA,EACR,8BAA8B,IAAA,CAC7B,MAAA,CAAO,UAAU,QAAA,CAAS,IAAA,CAAKA,CAAI,CACrC,CAAA,EACE,MAAA,CAAO,IAAA,CAAKA,CAAI,CAAA,CAAE,MAAA,GAAW,KAEjCgE,CAAAA,CAAS,IAAA,CAAOhE,EAAO8O,CAAAA,CAAAA,CAGrBnD,CAAAA,CAAO,eAAA,GACT3H,CAAAA,CAAS,KAAOhE,CAAAA,CAAO4C,EAAAA,CAAY5C,CAAI,CAAA,CAAA,CAGrC2L,CAAAA,CAAO,SACT3H,CAAAA,CAAS,IAAA,CAAOhE,CAAAA,CAAO2L,CAAAA,CAAO,OAAO3L,CAAI,CAAA,CAAA,CAG3C,IAAM8C,CAAAA,CAAUD,EAAemB,CAAAA,CAAS,OAAO,CAAA,CAG/C,GAAIgL,EAAkB,CACpB,IAAMb,EAKF,CACF,IAAA,CAAMnK,EAAS,IAAA,CACf,QAAA,CAAUA,CAAAA,CAAS,QAAA,CACnB,GAAIA,CAAAA,CAAS,EAAA,CACb,WAAYA,CAAAA,CAAS,UAAA,CACrB,KAAMA,CAAAA,CAAS,IAAA,CACf,GAAA,CAAKA,CAAAA,CAAS,IACd,MAAA,CAAQA,CAAAA,CAAS,OACjB,UAAA,CAAYA,CAAAA,CAAS,WAIrB,IAAA,CAAM,SACJhE,CAAAA,YAAgB,WAAA,CAAc,IAAI,IAAA,CAAK,CAACA,CAAI,CAAC,EAAI,IAAI,IAAA,CACvD,IAAA,CAAM,SAAYA,EAClB,IAAA,CAAM,SAAYA,EAElB,KAAA,CAAO,KAAO,CAAE,GAAGmO,CAAO,CAAA,CAAA,CAC1B,WAAA,CAAa,SACXnO,CAAAA,YAAgB,WAAA,CAAcA,EAAO,IAAI,WAAA,CAAY,CAAC,CAAA,CACxD,QAAA,CAAU,SAAaA,CAAAA,YAAgB,SAAWA,CAAAA,CAAO,IAAI,SAC7D,KAAA,CAAO,SACL,IAAI,UAAA,CAAWA,CAAAA,YAAgB,WAAA,CAAcA,CAAAA,CAAO,IAAI,WAAA,CAAY,CAAC,CAAC,CAAA,CAExE,MAAAoD,CAAAA,CACA,IAAA,CAAApD,CAAAA,CACA,OAAA,CAAA8C,EACA,MAAA,CAAA6I,CAAAA,CACA,OAAQoD,CAAAA,CACR,UAAA,CAAY,MACZ,SAAA,CAAW/K,CAAAA,CAAS,EAAA,EAAM,CAACZ,EAC3B,OAAA,CAAS,CAAC,CAACA,CACb,EAEA,OAAO+K,CACT,CAGA,OAAIlO,EAAS+D,CAAQ,CAAA,GAEnBA,EAAS,KAAA,CAAQZ,CAAAA,CACjBY,EAAS,OAAA,CAAUlB,CAAAA,CACnBkB,CAAAA,CAAS,UAAA,CAAa,MACtBA,CAAAA,CAAS,MAAA,CAAS+K,CAAAA,CAClB/K,CAAAA,CAAS,UAAYA,CAAAA,CAAS,EAAA,EAAM,CAACZ,CAAAA,CACrCY,EAAS,OAAA,CAAU,CAAC,CAACZ,CAAAA,CAAAA,CAGhBY,CACT,EClPA,SAASiL,EAAAA,CAAkBC,CAAAA,CAAmC,CAC5D,IAAM3M,CAAAA,CAAK,IAAA,CAAK,MAAM2M,CAAU,CAAA,CAAI/M,GAAQ,CAE5C,OAAK,KAAA,CAAMI,CAAE,EAGN,IAAA,CAFE,IAAA,CAAK,IAAI,CAAA,CAAG,IAAA,CAAK,MAAMA,CAAE,CAAC,CAGrC,CAaO,SAAS4M,EAAAA,CACdC,CAAAA,CACe,CACf,GAAI,CAACA,CAAAA,CACH,OAAO,IAAA,CAGT,IAAMtM,EAAUsM,CAAAA,CAAiB,OAAA,EAAW,EAAC,CACvCC,CAAAA,CAAavM,EAAQ,aAAa,CAAA,CAExC,GAAIuM,CAAAA,CAAY,CAEd,IAAMtK,CAAAA,CAAU,OAAOsK,CAAU,CAAA,CAEjC,GAAI,CAAC,KAAA,CAAMtK,CAAO,CAAA,EAAKA,GAAW,CAAA,CAChC,OAAOA,EAAU,GAAA,CAGnB,IAAMxC,EAAK0M,EAAAA,CAAkBI,CAAU,CAAA,CAEvC,GAAI9M,IAAO,IAAA,CACT,OAAOA,CAEX,CAGA,IAAM+M,CAAAA,CAAkB,iBAAA,CAIlBC,CAAAA,CACJzM,CAAAA,CAAQwM,EAAkB,QAAQ,CAAA,EAClCxM,EAAQ,IAAA,CAAOwM,CAAAA,CAAkB,QAAQ,CAAA,CAE3C,GAAIC,CAAAA,CAAqB,CACvB,IAAMxK,CAAAA,CAAU,MAAA,CAAOwK,CAAmB,CAAA,CAE1C,GAAI,CAAC,KAAA,CAAMxK,CAAO,CAAA,CAChB,OAAOA,EAAU,GAErB,CAIA,IAAMyK,CAAAA,CACJ1M,CAAAA,CAAQwM,EAAkB,KAAK,CAAA,EAAKxM,CAAAA,CAAQ,IAAA,CAAOwM,EAAkB,KAAK,CAAA,CAE5E,OAAIE,CAAAA,CACKP,GAAkBO,CAAgB,CAAA,CAGpC,IACT,CAkBA,eAAsBC,EAAAA,CAMpBC,CAAAA,CAMA/D,EAC4E,CAC5E,GAAM,CACJ,OAAA,CAAAgE,CAAAA,CAAU,CAAA,CACV,KAAA,CAAAC,EAAQ,CAAA,CACR,OAAA,CAAAC,CAAAA,CAAU,CAAA,CACV,SAAAC,CAAAA,CACA,OAAA,CAAAC,CAAAA,CAAU,GACV,WAAA,CAAAC,CAAAA,CACA,OAAAC,CAAAA,CACA,OAAA,CAAAC,CACF,CAAA,CAAIvE,CAAAA,CAEAwE,CAAAA,CAAU,CAAA,CACVC,EAAWR,CAAAA,CACTS,CAAAA,CAAaV,CAAAA,CAAU,CAAA,CAAIA,EAAU,CAAA,CACvCxB,CAAAA,CAEJ,KAAOgC,CAAAA,EAAWE,GAAY,CAG5B,GAAIF,EAAU,CAAA,EAAKhC,CAAAA,CAAS,CAC1B,IAAMmC,CAAAA,CAAMnC,CAAAA,CAAO,MAAA,CACboC,EAAUD,CAAAA,CAAI,OAAA,CAEhBC,IACF,MAAM9M,CAAAA,CAAkB8M,EAASpC,CAAAA,CAAQgC,CAAO,CAAA,CAI5CG,CAAAA,CAAI,aACNA,CAAAA,CAAI,QAAA,CAAWA,EAAI,QAAA,CACnBA,CAAAA,CAAI,SAAW5E,EAAAA,CAAiB4E,CAAAA,CAAK,KAAK,CAAA,CAAA,EAGhD,CAKAnC,CAAAA,CAAS,MAAMuB,CAAAA,CAAUS,CAAAA,CAAU,EAAGA,CAAO,CAAA,CAC7C,IAAM/M,CAAAA,CAAQ+K,EAAO,KAAA,CAIrB,GACE/K,EACI,MAAMoN,EAAAA,CACJrC,EACAgC,CAAAA,CACAE,CAAAA,CACAL,CAAAA,CACAD,CAAAA,CACAG,CACF,CAAA,CACA,EACEF,GACAG,CAAAA,CAAUE,CAAAA,EACT,MAAML,CAAAA,CAAY7B,CAAAA,CAAQgC,CAAO,CAAA,CAAA,CAGxC,MAIF,IAAIM,CAAAA,CAAaC,GAAWN,CAAAA,CAAUH,CAAM,EAG5C,GAAI7M,CAAAA,GAAUA,CAAAA,CAAM,MAAA,GAAW,KAAOA,CAAAA,CAAM,MAAA,GAAW,GAAA,CAAA,CAAM,CAE3D,IAAMuN,CAAAA,CAAexB,EAAAA,CAAgBhB,CAAM,CAAA,CAIvCwC,IAAiB,IAAA,GACnBF,CAAAA,CAAaL,EAAW,IAAA,CAAK,GAAA,CAC3BO,EACAb,CAAAA,EAAYa,CACd,CAAA,EAEJ,CAEA,MAAMrO,EAAAA,CAAgBmO,CAAU,EAChCL,CAAAA,EAAYP,CAAAA,EAAW,EACvBO,CAAAA,CAAW,IAAA,CAAK,GAAA,CAAIA,CAAAA,CAAUN,GAAYM,CAAQ,CAAA,CAClDD,IACF,CAEA,OAAOhC,CACT,CAwBA,eAAsBqC,EAAAA,CAMpBrC,CAAAA,CACAgC,EACAE,CAAAA,CACAL,CAAAA,CAMAD,CAAAA,CAAoB,GACpBG,CAAAA,CACkB,CA9OpB,IAAAxG,CAAAA,CAAAkH,EAAAC,CAAAA,CAuPE,GALIV,IAAYE,CAAAA,EAAAA,CAKZ3G,CAAAA,CAAAyE,EAAO,KAAA,GAAP,IAAA,EAAAzE,CAAAA,CAAc,WAAA,CAChB,OAAO,KAAA,CAIT,GAAIsG,CAAAA,CAAa,CACf,IAAMtL,CAAAA,CAAS,MAAMsL,CAAAA,CAAY7B,CAAAA,CAAQgC,CAAO,CAAA,CAEhD,GAAIzL,IAAW,IAAA,CACb,OAAO,CAACA,CAEZ,CAEA,OAAO,EAAA,CACJqL,GAAW,EAAC,EAAG,QAAA,CAAA,CAASc,CAAAA,CAAAA,CAAAD,EAAAzC,CAAAA,CAAO,KAAA,GAAP,IAAA,CAAA,MAAA,CAAAyC,CAAAA,CAAc,SAAd,IAAA,CAAAC,CAAAA,CAAwB,CAAC,CAAA,GACjD,CAACX,GACAA,CAAAA,CAAQ,IAAA,CAAMvG,CAAAA,EAAWA,CAAAA,CAAO,aAAY,GAAMwE,CAAAA,CAAO,OAAO,MAAM,CAAA,CAAA,CAE5E,CASA,SAASuC,EAAAA,CAAWd,CAAAA,CAAeK,CAAAA,CAAuC,CACxE,OAAO,OAAOA,IAAW7Q,CAAAA,CACpB6Q,CAAAA,CAAqCL,CAAK,CAAA,CAC3CK,CAAAA,CACE,IAAA,CAAK,MAAA,GAAWL,CAAAA,CAChBA,CACR,CCrQA,eAAsBkB,GAMpBpB,CAAAA,CAMAqB,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CAAc,EACdC,CAAAA,CAAe,CAAA,CACfC,EAAoB,KAAA,CACpBC,CAAAA,CAAqB,MACrB5O,CAAAA,CAC4E,CAC5E,GAAI,CAACuO,EACH,OAAOrB,CAAAA,GAGT,IAAI2B,CAAAA,CAAiB,EACjBlD,CAAAA,CAEJ,KAAA,CAAO8C,CAAAA,GAAgB,CAAA,EAAKI,EAAiBJ,CAAAA,IACvCC,CAAAA,CAAe,GACjB,MAAM5O,EAAAA,CAAgB4O,EAAc1O,CAAM,CAAA,CAG5C2L,CAAAA,CAAS,MAAMuB,GAAU,CAEzB2B,CAAAA,EAAAA,CAGG,EAAAJ,CAAAA,CAAc,GAAKI,CAAAA,EAAkBJ,CAAAA,EACtC,CAACF,CAAAA,EACAC,GAAqBA,CAAAA,CAAkB7C,CAAAA,CAAQkD,CAAc,CAAA,CAAA,CAAA,EAMhE,MACE,MAAM/O,EAAAA,CAAgByO,CAAAA,CAAiBvO,CAAM,EAGzCA,CAAAA,EAAUA,CAAAA,CAAO,QACnB,OAAO2L,CAAAA,CAAAA,MAGR,CAACgD,CAAAA,EAAqB5N,EAAAA,EAAa,EACnC,CAAC6N,GAAsB5N,EAAAA,EAAU,EAItC,OAAO2K,CACT,CCzEA,IAAMmD,EAAAA,CAAqB,CAAC,GAAA,CAAK,GAAA,CAAK,GAAG,CAAA,CAInCC,EAAAA,CACJ,iNAAA,CAGIC,EAAAA,CAAY5H,GAChB,OAAO,cAAA,GAAmB3K,CAAAA,EAAa2K,CAAAA,YAAgB,eAE5C6H,EAAAA,CAAa,CAACC,EAAgBC,CAAAA,IAAoC,CAC7E,OAAAD,CAAAA,CACA,KAAA,CAAAC,CAAAA,CACA,QAAA,CAAUA,EAAQD,CAAAA,CAASC,CAAAA,CAAQ,MACrC,CAAA,CAAA,CAWO,SAASC,GACd5Q,CAAAA,CACA2K,CAAAA,CACmB,CACnB,IAAM/B,EAAO+B,CAAAA,CAAO,IAAA,CAEpB,OAAO,OAAO,cAAA,GAAmB1M,GAAa,CAACuS,EAAAA,CAAS5H,CAAI,CAAA,CACxDiI,GAAY7Q,CAAAA,CAAK2K,CAAAA,CAAQ/B,CAAI,CAAA,CAC7BkI,GAAa9Q,CAAAA,CAAK2K,CAAAA,CAAQ/B,CAAI,CACpC,CAEA,SAASiI,EAAAA,CACP7Q,EACA2K,CAAAA,CACA/B,CAAAA,CACmB,CACnB,OAAO,IAAI,OAAA,CAAQ,CAACnH,EAASsP,CAAAA,GAAW,CACtC,IAAMC,CAAAA,CAAM,IAAI,eAEVxP,CAAAA,CAASmJ,CAAAA,CAAO,MAAA,CAChBsG,CAAAA,CAAQ,IAAMD,CAAAA,CAAI,KAAA,GAElBE,CAAAA,CAAU1J,CAAAA,EAAmB,CACjChG,CAAAA,CAAO,mBAAA,CAAoB,OAAA,CAASyP,CAAK,EAEzC,GAAI,CACFzJ,CAAAA,GACF,OAASpF,CAAAA,CAAO,CACd2O,CAAAA,CAAO3O,CAAK,EACd,CACF,CAAA,CAEA4O,EAAI,IAAA,CAAKrG,CAAAA,CAAO,OAAkB3K,CAAG,CAAA,CACrCgR,CAAAA,CAAI,YAAA,CAAe,OACnBA,CAAAA,CAAI,eAAA,CAAkBrG,EAAO,WAAA,GAAgB,SAAA,CAE7C,IAAI,OAAA,CAAQA,CAAAA,CAAO,OAAO,CAAA,CAAE,QAC1B,CAACzL,CAAAA,CAAOiD,IACNoO,EAAAA,CAAkB,IAAA,CAAKpO,CAAI,CAAA,EAAK6O,CAAAA,CAAI,gBAAA,CAAiB7O,CAAAA,CAAMjD,CAAK,CACpE,CAAA,CAEA8R,CAAAA,CAAI,MAAA,CAAO,WAActK,CAAAA,EACvBiE,CAAAA,CAAO,gBAAA,CACL8F,EAAAA,CACE/J,EAAM,MAAA,CACNA,CAAAA,CAAM,iBAAmBA,CAAAA,CAAM,KAAA,CAAQ,MACzC,CACF,CAAA,CAEFsK,CAAAA,CAAI,MAAA,CAAS,IACXE,CAAAA,CAAO,IAAM,CACX,IAAMpP,CAAAA,CAAU,IAAI,OAAA,CAEpB,IAAA,IAAWqP,CAAAA,IAAQH,CAAAA,CAAI,uBAAsB,CAAE,KAAA,CAAM,OAAO,CAAA,CAAG,CAC7D,IAAMI,CAAAA,CAAQD,CAAAA,CAAK,OAAA,CAAQ,GAAG,EAE1BC,CAAAA,CAAQ,CAAA,EACVtP,CAAAA,CAAQ,MAAA,CAAOqP,EAAK,KAAA,CAAM,CAAA,CAAGC,CAAK,CAAA,CAAGD,EAAK,KAAA,CAAMC,CAAAA,CAAQ,CAAC,CAAA,CAAE,IAAA,EAAM,EAErE,CAEA,IAAMpO,CAAAA,CAAW,IAAI,QAAA,CACnBsN,EAAAA,CAAmB,QAAA,CAASU,CAAAA,CAAI,MAAM,CAAA,CAAI,IAAA,CAAOA,CAAAA,CAAI,QAAA,CACrD,CAAE,MAAA,CAAQA,CAAAA,CAAI,OAAQ,UAAA,CAAYA,CAAAA,CAAI,WAAY,OAAA,CAAAlP,CAAQ,CAC5D,CAAA,CAGA,OAAO,cAAA,CAAekB,CAAAA,CAAU,KAAA,CAAO,CAAE,MAAOgO,CAAAA,CAAI,WAAY,CAAC,CAAA,CAEjEvP,EAAQuB,CAAQ,EAClB,CAAC,CAAA,CAEHgO,CAAAA,CAAI,QAAU,IACZE,CAAAA,CAAO,IAAMH,CAAAA,CAAO,IAAI,SAAA,CAAU,wBAAwB,CAAC,CAAC,CAAA,CAG9D,IAAMM,CAAAA,CAAU,IACdH,CAAAA,CAAO,IACLH,EACEvP,CAAAA,CAAO,MAAA,EACLS,EAAiB,yBAAA,CAA2B5D,CAAW,CAC3D,CACF,CAAA,CAIF,GAFA2S,CAAAA,CAAI,QAAUK,CAAAA,CAEV7P,CAAAA,CAAO,OAAA,CACT,OAAO6P,GAAQ,CAGjB7P,CAAAA,CAAO,gBAAA,CAAiB,OAAA,CAASyP,CAAK,CAAA,CAEtCD,CAAAA,CAAI,KAAKpI,CAA8B,EACzC,CAAC,CACH,CAEA,eAAekI,EAAAA,CACb9Q,EACA2K,CAAAA,CACA/B,CAAAA,CACmB,CACnB,IAAM9G,CAAAA,CAAU,IAAI,OAAA,CAAQ6I,CAAAA,CAAO,OAAO,CAAA,CACtC2G,EAAS1I,CAAAA,CACT+H,CAAAA,CAEJ,GAAI,CAACH,EAAAA,CAAS5H,CAAI,CAAA,CAAG,CAEnB,IAAM2I,CAAAA,CAAO3I,aAAgB,IAAA,CAAOA,CAAAA,CAAO,MAAM,IAAI,SAASA,CAAI,CAAA,CAAE,IAAA,EAAK,CAEzE+H,EAAQY,CAAAA,CAAK,IAAA,CACbD,EAASC,CAAAA,CAAK,MAAA,GAEVA,CAAAA,CAAK,IAAA,EAAQ,CAACzP,CAAAA,CAAQ,IAAI,cAAc,CAAA,EAC1CA,EAAQ,GAAA,CAAI,cAAA,CAAgByP,EAAK,IAAI,EAEzC,CAEA,IAAIb,EAAS,CAAA,CAEb,OAAO,MAAM1Q,CAAAA,CAAK,CAChB,GAAG2K,CAAAA,CACH,OAAA,CAAA7I,CAAAA,CACA,IAAA,CAAMwP,EAAO,WAAA,CACX,IAAI,eAAA,CAAgB,CAClB,UAAUE,CAAAA,CAAO1M,CAAAA,CAAY,CAC3B4L,CAAAA,EAAUc,EAAM,UAAA,CAChB7G,CAAAA,CAAO,iBAAkB8F,EAAAA,CAAWC,CAAAA,CAAQC,CAAK,CAAC,CAAA,CAClD7L,CAAAA,CAAW,OAAA,CAAQ0M,CAAK,EAC1B,CACF,CAAC,CACH,EAEA,MAAA,CAAQ,MACV,CAAgB,CAClB,CCzJO,SAASC,EAAAA,CACdzO,EACA0O,CAAAA,CACG,CAEH,GACE,CAACA,CAAAA,EACD,OAAO,QAAA,GAAatT,GACpB,EAAE4E,CAAAA,YAAoB,QAAA,CAAA,EACtB,CAACA,EAAS,IAAA,CAEV,OAAOA,CAAAA,CAGT,IAAMlB,EAAUkB,CAAAA,CAAS,OAAA,CAEnB2N,EAAQ7O,CAAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAA,CACxC,MAAA,CACA,MAAA,CAAOA,CAAAA,CAAQ,IAAI,gBAAgB,CAAC,GAAK,MAAA,CACzC4O,CAAAA,CAAS,EAEPiB,CAAAA,CAAU,IAAI,QAAA,CAClB3O,CAAAA,CAAS,KAAK,WAAA,CACZ,IAAI,gBAAgB,CAClB,SAAA,CAAUwO,EAAO1M,CAAAA,CAAY,CAC3B4L,CAAAA,EAAUc,CAAAA,CAAM,WAEhBE,CAAAA,CACEjB,EAAAA,CAAWC,CAAAA,CAAQC,CAAAA,EAAS,KAAK,GAAA,CAAIA,CAAAA,CAAOD,CAAM,CAAC,CACrD,CAAA,CACA5L,CAAAA,CAAW,QAAQ0M,CAAK,EAC1B,CACF,CAAC,CACH,CAAA,CACAxO,CACF,EAGA,IAAA,IAAWvD,CAAAA,IAAO,CAAC,KAAA,CAAO,YAAA,CAAc,MAAM,CAAA,CAC5C,MAAA,CAAO,cAAA,CAAekS,CAAAA,CAASlS,EAAK,CAAE,KAAA,CAAOuD,EAASvD,CAAG,CAAE,CAAC,CAAA,CAG9D,OAAOkS,CACT,CClCA,eAAsBC,EAAAA,CAMpB1L,CAAAA,CACAwI,CAAAA,CAKAjG,CAAAA,CAM4E,CAvC9E,IAAAC,CAAAA,CAwCE,IAAMyE,CAAAA,CAAS,MAAMuB,CAAAA,CAAUxI,CAAmB,EAC5C9D,CAAAA,CAAQ+K,CAAAA,CAAO,MAErB,GAAI,CAAC/K,CAAAA,CAEH,OAAA8K,GAAoBC,CAAAA,CAAQ1E,CAAa,EAElC0E,CAAAA,CAKL1E,CAAAA,CAAc,SAChB,MAAMhG,CAAAA,CAAkBgG,CAAAA,CAAc,OAAA,CAASrG,CAAK,CAAA,CAKtD,IAAMyP,EAAczP,CAAAA,CAAM,WAAA,CAEpB0P,EAASrJ,CAAAA,CAAc,MAAA,CAkB7B,GAhBI,CAACoJ,GAAeC,CAAAA,EAAUA,CAAAA,CAAO,IAAA,EACnCA,CAAAA,CAAO,KAAK,aAAA,CAAeC,EAAAA,CAAY3P,CAAsB,CAAC,EAK5DqG,CAAAA,CAAc,QAAA,GAAa,oBAC7B0E,CAAAA,CAAO,IAAA,CAAA,CAAQzE,EAAAD,CAAAA,CAAc,eAAA,GAAd,IAAA,CAAAC,CAAAA,CAAiC,MAIlDwE,EAAAA,CAAoBC,CAAAA,CAAQ1E,CAAAA,CAAe,IAAI,EAGrB,CAACoJ,CAAAA,EAAepJ,CAAAA,CAAc,eAAA,CAEjC,CACrB,IAAMuJ,CAAAA,CAAWvJ,EAAc,QAAA,CAE/B,GAAIuJ,IAAavT,EAAAA,CACf,MAAM2D,CAAAA,CAIJ4P,CAAAA,GAAa,UACf,MAAM,IAAI,OAAA,CAAQ,IAAM,IAAI,EAEhC,CAEA,OAAO7E,CACT,CAGA,IAAM8E,EAAAA,CAAoB,CACxB,eAAA,CACA,qBAAA,CACA,SACA,WACF,CAAA,CAMA,SAASF,EAAAA,CAAY3P,EAAqC,CAExD,IAAMuI,EAAS,CACb,GAAGvI,EAAM,MAAA,CACT,IAAA,CAAM,MAAA,CACN,IAAA,CAAM,OACN,QAAA,CAAU,MAAA,CACV,SAAU,MAAA,CACV,OAAA,CAASP,EAAeO,CAAAA,CAAM,MAAA,CAAO,OAAwB,CAC/D,EAEA,IAAA,IAAWD,CAAAA,IAAQ8P,EAAAA,CACbtH,CAAAA,CAAO,QAAQxI,CAAI,CAAA,GACrBwI,CAAAA,CAAO,OAAA,CAAQxI,CAAI,CAAA,CAAI,YAAA,CAAA,CAI3B,IAAM+P,CAAAA,CAAO,MAAA,CAAO,OAAO,IAAI,KAAA,CAAM9P,CAAAA,CAAM,OAAO,EAAGA,CAAAA,CAAO,CAC1D,OAAAuI,CAAAA,CACA,OAAA,CAASA,EACT,QAAA,CAAUvI,CAAAA,CAAM,QAAA,EAAY,CAAE,GAAGA,CAAAA,CAAM,QAAA,CAAU,OAAAuI,CAAO,CAC1D,CAAC,CAAA,CAED,OAAAuH,CAAAA,CAAK,IAAA,CAAO9P,EAAM,IAAA,CAClB8P,CAAAA,CAAK,KAAA,CAAQ9P,CAAAA,CAAM,MAEZ8P,CACT,CAEO,SAASC,EAAAA,CAOd/P,EACAY,CAAAA,CAMAyF,CAAAA,CAMM,CACNrG,CAAAA,CAAM,MAAA,CAASA,EAAM,MAAA,EAAWY,CAAAA,EAAYA,CAAAA,CAAS,MAAA,EAAW,EAChEZ,CAAAA,CAAM,UAAA,CACJA,EAAM,UAAA,EAAeY,CAAAA,EAAYA,EAAS,UAAA,EAAe,EAAA,CAC3DZ,CAAAA,CAAM,MAAA,CAASA,EAAM,OAAA,CAAUqG,CAAAA,CAC/BrG,EAAM,QAAA,CAAWY,CAAAA,CACjBZ,EAAM,WAAA,CAAcA,CAAAA,CAAM,IAAA,GAAS/D,EACrC,CC1HA,IAAM+T,EAAAA,CAAmB,MAAA,CAAO,MAAA,CAAO,CACrC,UAAA,CAAY,IACd,CAAC,CAAA,CAqBD,eAAsBC,EAAAA,CAMpBrS,CAAAA,CACAsI,EAKW,IAAA,CACiE,CA5E9E,IAAAI,EAAAA,CAgFE,GAAIJ,CAAAA,EAAa,OAAOA,EAAU,QAAA,EAAa,QAAA,CAAU,CACvD,IAAMgK,CAAAA,CAASvF,GAKbzE,CAAAA,CAAU,QAAA,CAAUA,CAAAA,CAAU,SAAA,CAAWA,CAAS,CAAA,CAEpD,GAAIgK,EACF,OAAOA,CAEX,CAEA,IAAMC,CAAAA,CAAgBlK,EAAAA,CAKpBrI,CAAAA,CAAKsI,CAAS,CAAA,CAEV,CACJ,OAAA,CAAAjE,CAAAA,CACA,YAAAmO,CAAAA,CACA,QAAA,CAAAxF,CAAAA,CACA,UAAA,CAAA1I,EACA,SAAA,CAAA2I,CAAAA,CACA,UAAAhG,CAAAA,CACA,cAAA,CAAAE,EACA,kBAAA,CAAAC,CAAAA,CACA,eAAA,CAAA2I,CAAAA,CAAkB,CACpB,CAAA,CAAIwC,CAAAA,CACEE,EAAiBxF,CAAAA,GAAc,MAAA,EAAahG,IAAc,MAAA,CAC1D0B,CAAAA,CAAS4J,CAAAA,CAAc,MAAA,CAIvBG,EACJD,CAAAA,GACC9J,CAAAA,GAAWpK,GAAOoK,CAAAA,GAAWnK,EAAAA,CAAAA,GAAAA,CAC7BkK,GAAA6J,CAAAA,CAAc,IAAA,GAAd,IAAA,CAAA7J,EAAAA,CAAsB,CAAC6J,CAAAA,CAAc,OAAA,CAAA,CAElCI,CAAAA,CAAgB,CAAC,EACrB3F,CAAAA,EACA3I,CAAAA,EACAC,CAAAA,EACAmO,CAAAA,EACAD,GACArL,CAAAA,EACAC,CAAAA,CAAAA,CAGEwL,EAA2B,IAAA,CAG3BD,CAAAA,GACFC,EAAYlI,EAAAA,CAAiB6H,CAAa,CAAA,CAAA,CAI5C,IAAIM,EAKO,IAAA,CAGX,GAAID,GAAaH,CAAAA,CAAgB,CAC/B,IAAMH,CAAAA,CAASvF,EAAAA,CAKb6F,CAAAA,CAAW3F,CAAAA,CAAWsF,CAAa,CAAA,CAErC,GAAID,EACF,OAAOA,CAAAA,CAIT,GAAIC,CAAAA,CAAc,UAAA,CAAY,CAC5B,IAAMO,EAAS,MAAMzG,EAAAA,CAAeuG,CAAAA,CAAWL,CAAa,EACtDQ,CAAAA,CACJD,CAAAA,EACAE,EAAAA,CACEF,CAAAA,CAAO,KACPF,CAAAA,CACAL,CACF,EAGF,GACEQ,CAAAA,EACAxG,GACEqG,CAAAA,CACA,CAAE,GAAGE,CAAAA,CAAQ,KAAMC,CAAS,CAAA,CAC5BR,EAAc,UAChB,CAAA,CAEA,OAAOQ,CAEX,CAIER,CAAAA,CAAc,WAAA,GAAgB,QAC9B,CAAChH,EAAAA,CAAaqH,CAAS,CAAA,EACvB,CAACtG,GAAgBiG,CAAa,CAAA,GAE9BM,CAAAA,CAAkBG,EAAAA,CAChB,CACE,IAAA,CAAMT,CAAAA,CAAc,WAAA,CACpB,MAAA,CAAQ,IACR,UAAA,CAAY,EAAA,CACZ,OAAA,CAAS,EACX,CAAA,CACAK,CAAAA,CACAL,CACF,CAAA,EAEJ,CAGA,GAAIK,CAAAA,EAAatO,CAAAA,CAAY,CAC3B,IAAM2O,EAAW9N,EAAAA,CAEfyN,CAAAA,CAAWtO,CAAU,CAAA,CAEvB,GAAI2O,CAAAA,CACF,OAAOA,CAEX,CAEA,IAAMC,EAAAA,CAAcX,CAAAA,CAAc,OAAS,EAAC,CACtC,CAAE,OAAA,CAAA5D,EAAAA,CAAU,CAAA,CAAG,YAAA,CAAAwE,EAAa,CAAA,CAAID,EAAAA,CAGhCE,CAAAA,CAAab,CAAAA,CAAc,OAG3Bc,EAAAA,CAAgB,MAAOnN,CAAAA,CAA8BiJ,CAAAA,CAAU,IAAM,CAEzE,IAAMmD,EACJI,CAAAA,EACAnH,EAAAA,CACEqH,CACF,CAAA,CAKF,GAAI,CAACzD,CAAAA,CAAS,CAEZ,GAAI0D,CAAAA,CAAiB,CACnB,IAAM7P,CAAAA,CAAW6P,EAEjB,OAAAA,CAAAA,CAAkB,IAAA,CAEX7P,CACT,CAEI4P,CAAAA,EAAa,CAAC1M,IACZe,CAAAA,CACoB8F,EAAAA,CACpB6F,EACA3F,CAAAA,CACAsF,CACF,CAAA,GAKE9G,EAAAA,CAASmH,EAAWR,EAAAA,CAAkBnF,CAAAA,CAAWhG,CAAS,CAAA,CAC1DU,EAAkBiL,CAAAA,CAAWR,EAAgB,CAAA,CAAA,CAG/CzK,CAAAA,CAAkBiL,EAAWR,EAAgB,CAAA,CAAA,CAKjDG,EAAc,QAAA,CAAWK,EAC3B,CAEA,IAAM5S,EAAAA,CAAMuS,CAAAA,CAAc,GAAA,CAGpBzN,GAAaV,EAAAA,CACjBwO,CAAAA,CACA5S,GACAqE,CAAAA,CACAC,CAAAA,EAAc,EACd,CAAC,CAACkO,CAAAA,CAEF,CAAC,EAAEnO,CAAAA,GAAY,CAAC8K,GAAWgE,EAAAA,CAAAA,CAC7B,CAAA,CAIM1K,EAAgB8J,CAAAA,CAEtB9J,CAAAA,CAAc,MAAA,CAAS3D,EAAAA,CAAW,OAGlC,IAAMmM,EAAAA,CAAQ,IAAMnM,EAAAA,CAAW,MAAMsO,CAAAA,CAAY,MAAM,CAAA,CAEnDA,CAAAA,GACEA,EAAW,OAAA,CACbnC,EAAAA,GAEAmC,CAAAA,CAAW,gBAAA,CAAiB,QAASnC,EAAK,CAAA,CAAA,CAI9C,IAAI9D,EAAAA,CAMAnK,EAKO,IAAA,CAEX,GAAI,CACEuP,CAAAA,CAAc,SAAA,GAOZK,GAAatO,CAAAA,EAAc,CAAC6K,CAAAA,EAC9B,MAAM,KAGR,MAAM1M,CAAAA,CAAkB8P,EAAc,SAAA,CAAW9J,CAAa,GAIhE,IAAMjB,CAAAA,CAAK+K,CAAAA,CAAc,OAAA,CACnBe,EAAOC,EAAAA,CAAS9K,CAAAA,CAAe6J,CAAM,CAAA,CAwB3C,GAtBAtP,CAAAA,CAAYwE,CAAAA,CACR,MAAMA,CAAAA,CACJxH,GACAsT,CACF,CAAA,CAEA,MAAO7K,CAAAA,CAAc,gBAAA,EAAoBA,EAAc,IAAA,CACnDmI,EAAAA,CAAwB5Q,EAAAA,CAAKyI,CAAa,EAC1C,KAAA,CAAMzI,EAAAA,CAAKsT,CAAmB,CAAA,CAAA,CAQtCtQ,EAAWyO,EAAAA,CACTzO,CAAAA,CACAyF,CAAAA,CAAc,kBAChB,EAGIxJ,CAAAA,CAAS+D,CAAQ,EAAG,CAGtB,GAAIsQ,IAAS7K,CAAAA,EAAiBzF,CAAAA,CAAS,MAAA,GAAW,GAAA,CAChD,OAAOsP,CAAAA,CAiCT,GAxBI,OAAO,QAAA,GAAalU,GAAY4E,CAAAA,YAAoB,QAAA,CACtDA,CAAAA,CAAS,IAAA,CAAOyF,EAAc,MAAA,CAC1B,MAAMA,EAAc,MAAA,CAAOzF,CAAQ,EACnC,MAAMuK,EAAAA,CAAkBvK,CAAAA,CAAUyF,CAAAA,CAAc,YAAY,CAAA,CACvDjB,CAAAA,GAEH,SAAUxE,CAAAA,EAAY,MAAA,GAAUA,IAEpCA,CAAAA,CAAW,CAAE,IAAA,CAAMA,CAAS,IAYhCA,CAAAA,CAAS,MAAA,CAASyF,EAIdzF,CAAAA,CAAS,EAAA,GAAO,QAAa,CAACA,CAAAA,CAAS,EAAA,CACzC,MAAM,IAAIC,EAAAA,CACRwF,CAAAA,CAAc,MAAA,CACZ,MAAA,CACAzI,GACA,mBAAA,EACCgD,CAAAA,CAAS,MAAA,EAAU,IAAA,CAAA,CACtByF,EACAzF,CACF,CAEJ,CAEAmK,EAAAA,CAASU,EAAAA,CAKP7K,EAAUyF,CAAa,CAAA,CAEzB,IAAM+K,EAAAA,CAAajB,EAAc,UAAA,CAE7BiB,EAAAA,EACF,MAAM/Q,CAAAA,CAAkB+Q,EAAAA,CAAYrG,EAAM,EAE9C,CAAA,MAASS,CAAAA,CAAQ,CACf,IAAMxL,CAAAA,CAAQwL,CAAAA,CAQduE,GACE/P,CAAAA,CACAY,CAAAA,CACAyF,CACF,CAAA,CAGA0E,EAAAA,CAASU,EAAAA,CAKP7K,CAAAA,CAAUyF,EAAerG,CAAK,EAClC,CAAA,OAAE,CACIgR,GACFA,CAAAA,CAAW,mBAAA,CAAoB,OAAA,CAASnC,EAAK,EAEjD,CAEA,OAAO9D,EACT,CAAA,CAKMsG,EAAAA,CACJ9E,GAAU,CAAA,CACLzI,CAAAA,EACCuI,EAAAA,CACE,CAACiF,EAAGvE,CAAAA,GAAYkE,EAAAA,CAAcnN,EAAqBiJ,CAAO,CAAA,CAC1D+D,EACF,CAAA,CACFG,EAAAA,CAEA,CAAE,aAAA,CAAAM,GAAe,cAAA,CAAAC,EAAe,EAAIrB,CAAAA,CAIpCxP,EAAAA,CACJ4Q,IAAiBC,EAAAA,CACb,MAAO1N,CAAAA,EAAiC,CACtC,GAAIA,CAAAA,CACF,OAAOuN,EAAAA,CAAYvN,CAAmB,EAGxC,IAAMvE,CAAAA,CAAQ,UAAA,CACZ,IAAMc,EAAkBkR,EAAAA,CAAepB,CAAa,EAAE,KAAA,CAAMnR,CAAI,EAChEwS,EACF,CAAA,CAEA,GAAI,CACF,OAAO,MAAMH,EAAAA,CAAYvN,CAAmB,CAC9C,QAAE,CACA,YAAA,CAAavE,CAAK,EACpB,CACF,CAAA,CACA8R,EAAAA,CAEAI,GAA2B,CAAC3N,CAAAA,CAAsB,QACtD0L,EAAAA,CACE1L,CAAAA,CACAnD,EAAAA,CACAwP,CACF,EAGIuB,EAAAA,CAAmB/D,CAAAA,CACrBD,EAAAA,CACE+D,EAAAA,CACA9D,EACAwC,CAAAA,CAAc,iBAAA,CACdA,CAAAA,CAAc,kBAAA,CACdA,EAAc,YAAA,CACdA,CAAAA,CAAc,kBACdA,CAAAA,CAAc,kBAAA,CACda,CACF,CAAA,CACAS,EAAAA,EAAyB,CAG7B,OAAIjB,IACEtO,CAAAA,EACFW,EAAAA,CAAmB2N,EAAWkB,EAAgB,CAAA,CAAA,CAI5C7M,GAAaE,CAAAA,EAAkBC,CAAAA,GACjCN,EAAAA,CACE8L,CAAAA,CACAiB,GACA,MAAA,CACA5M,CAAAA,CACA4M,GACA,CAAC,CAAC1M,EACF,CAAC,CAACC,CAAAA,CACFmL,CAAAA,CAAc,qBAChB,CAAA,CAAA,CAIGuB,EACT,CAWA,SAASd,GACPF,CAAAA,CACA9F,CAAAA,CACArC,CAAAA,CAC0E,CAC1E,GAAI,CAEF,IAAM3H,EAAY,OAAO,QAAA,GAAa5E,EAClC,IAAI,QAAA,CAAS,IAAA,CAAM0U,CAAM,EACzB,CACE,EAAA,CAAI,GACJ,MAAA,CAAQA,CAAAA,CAAO,OACf,UAAA,CAAYA,CAAAA,CAAO,UAAA,CACnB,OAAA,CAASA,EAAO,OAClB,CAAA,CAOJ9P,EAAS,IAAA,CAAO8P,CAAAA,CAAO,KACvBnI,CAAAA,CAAO,QAAA,CAAWqC,CAAAA,CAElB,IAAMG,EAASU,EAAAA,CAKb7K,CAAAA,CAAU,CACV,GAAG2H,EACH,MAAA,CAAQ,KAAA,CAAA,CACR,eAAA,CAAiB,CAAA,CAAA,CACjB,gBAAiB,KAAA,CACnB,CAAC,EAED,OAAAwC,CAAAA,CAAO,OAASxC,CAAAA,CAETwC,CACT,CAAA,MAAQxJ,CAAAA,CAAA,CACN,OAAO,IACT,CACF,CAWA,SAAS4P,GACP5I,CAAAA,CACA2H,CAAAA,CACe,CACf,IAAMyB,EAAOzB,CAAAA,EAAU,CAACA,EAAO,KAAA,EAASA,CAAAA,CAAO,SAAWA,CAAAA,CAAO,OAAA,CAAQ,IAAA,CACnExQ,CAAAA,CAAUiS,GAAQlS,CAAAA,CAAe8I,CAAAA,CAAO,OAAwB,CAAA,CAEtE,OAAO7I,CAAAA,EAAW,CAACA,CAAAA,CAAQ,eAAe,EACtC,CAAE,GAAG6I,EAAQ,OAAA,CAAS,CAAE,GAAG7I,CAAAA,CAAS,eAAA,CAAiBiS,CAAK,CAAE,EAC5DpJ,CACN,CCtiBA,SAASqJ,EAAAA,CAGPrJ,CAAAA,CAAyC,CACzC,IAAMsJ,CAAAA,CAAYtJ,CAAAA,CAAO,SAAA,CAQzB,eAAeuJ,CAAAA,CAAqBC,CAAAA,CAAqC,CACvE,OAAA,OAAA,CAAQ,KAAA,CAAM,OAASA,CAAAA,CAAe,kBAAkB,CAAA,CAEjD,IACT,CAEA,IAAMC,CAAAA,CAAsD,CAC1D,MAAA,CAAAzJ,EACA,SAAA,CAAAsJ,CAAAA,CASA,MAAM,OAAA,CAAQE,EAAc1L,CAAAA,CAAgB,GAAI,CAG9C,IAAM4L,EAAiBzV,CAAAA,CAAOqV,CAAAA,CAAWE,CAAsB,CAAA,CAC3DF,EAAUE,CAAY,CAAA,CACtB,OACEG,CAAAA,CACJD,CAAAA,EACC,CAAE,GAAA,CAAK,MAAA,CAAOF,CAAY,CAAE,EACzBnU,CAAAA,CAAMsU,CAAAA,CAAgB,IAItBC,CAAAA,CAAcvU,CAAAA,CACjB,QAAQ,WAAA,CAAa,EAAE,CAAA,CAEvB,OAAA,CAAQ,gBAAiB,EAAE,CAAA,CAG9B,GAAI,WAAA,CAAY,KAAKuU,CAAW,CAAA,CAC9B,MAAM,IAAI,MAAM,qCAAqC,CAAA,CAKvD,IAAMC,CAAAA,CAAe,sBAAA,CAAuB,KAAKD,CAAW,CAAA,CAExDF,CAAAA,EAAkBA,CAAAA,CAAe,MAAQrU,CAAAA,CACvCmI,CAAAA,CAAamM,EAAiB7L,CAAa,CAAA,CAC3CA,EACFN,CAAAA,CAAaA,CAAAA,CAAawC,CAAAA,CAAQ2J,CAAe,EAAG7L,CAAa,CAAA,CAIrE,OAAO4J,EAAAA,CAAOrS,CAAAA,CAAKwU,CAAY,CACjC,CACF,CAAA,CAOA,OAAO,IAAI,KAAA,CACTJ,CAAAA,CACA,CACE,GAAA,CAAIK,EAASC,CAAAA,CAAuB,CAClC,GAAIA,CAAAA,IAAQN,EACV,OAAOA,CAAAA,CAAWM,CAA0C,CAAA,CAK9D,GAAI,SAAOA,CAAAA,EAAS,QAAA,EAAYA,CAAAA,GAAS,MAAA,CAAA,CAKzC,OAAI9V,CAAAA,CAAOqV,CAAAA,CAAWS,CAAI,CAAA,CACjBN,CAAAA,CAAW,QAAQ,IAAA,CAAK,IAAA,CAAMM,CAAI,CAAA,CAGpCR,EAAqB,IAAA,CAAK,IAAA,CAAMQ,CAAI,CAC7C,CACF,CACF,CACF","file":"index.mjs","sourcesContent":["export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CHARSET_UTF_8 = 'charset=utf-8';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\nexport const FUNCTION = 'function';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n\nexport const REJECT = 'reject';\n\n// Larger timer delays overflow and fire immediately in browsers and Node.js (~24.8 days)\nexport const MAX_DELAY_MS = 2147483647;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, MAX_DELAY_MS, OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\n// Prevent stack overflow with recursion depth limit\nconst MAX_DEPTH = 10;\n\nexport const hasOwn = (o: any, k: string) =>\n Object.prototype.hasOwnProperty.call(o, k);\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 (hasOwn(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function checks for dangerous properties like '__proto__', 'constructor',\n * and 'prototype'. If none are present, the object is returned as-is (zero-copy fast path).\n * Otherwise, a shallow copy is created with the dangerous properties removed.\n *\n * @param obj - The object to sanitize\n * @returns A safe object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const hasProto = hasOwn(obj, '__proto__');\n const hasCtor = hasOwn(obj, 'constructor');\n const hasPrototype = hasOwn(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n // Copy key by key, as a spread compiled to assignments would let \"__proto__\" set the prototype\n const safeObj = {} as Record;\n\n for (const key of Object.keys(obj)) {\n if (key !== '__proto__' && key !== 'constructor' && key !== 'prototype') {\n safeObj[key] = obj[key];\n }\n }\n\n return safeObj as T;\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 // Without a prototype, a \"__proto__\" key is kept as a regular property instead of setting the prototype\n const sortedObj = Object.create(null) as Record;\n\n Object.keys(obj)\n .sort()\n .forEach((k) => (sortedObj[k] = obj[k]));\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 + (baseUrl.includes('?') ? '&' : '?') + 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, depth = 0) => {\n // Stop recursion if maximum depth is reached\n if (depth >= MAX_DEPTH) {\n return s;\n }\n\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 depth + 1,\n );\n }\n } else if (isObject(obj)) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key], depth + 1);\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], depth + 1);\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 // This is for compatibility with server frameworks that expect the literal notation\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 `:` or `{}` (like in OpenAPI paths), where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:` or `{}`.\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 || (url.indexOf(':') === -1 && url.indexOf('{') === -1)) {\n return url;\n }\n\n // Use a single RegExp and avoid unnecessary casts and function calls\n // Precompute keys for faster lookup\n const params = urlPathParams as DefaultUrlParams;\n\n // Use a replacer function that avoids extra work\n return url.replace(/:(\\w+)|\\{(\\w+)\\}/g, (match, colonKey, braceKey) => {\n const key = colonKey || braceKey;\n\n // Use hasOwnProperty for strict key existence check\n if (hasOwn(params, key)) {\n const value = params[key];\n\n // Only replace if value is not undefined or null\n if (value !== undefined && value !== null) {\n const encoded = encodeURIComponent(String(value));\n\n // These can't be encoded, and URL parsers would move the request to another path\n if (encoded === '.' || encoded === '..') {\n throw new Error('Path params \".\" and \"..\" not allowed.');\n }\n\n return encoded;\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL starts with a scheme (e.g., \"http://\", \"https://\").\n * A \"://\" appearing later, e.g. in a query string, does not make the URL absolute.\n *\n * @param url - The URL string to check.\n * @returns `true` if the URL is absolute, otherwise `false`.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n}\n\nexport const timeNow = () => Date.now();\n\nexport const noop = () => {};\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 (value === 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 (\n typeof globalThis !== UNDEFINED &&\n typeof globalThis.Buffer !== UNDEFINED &&\n globalThis.Buffer.isBuffer(value)\n ) {\n return false;\n }\n\n if (value instanceof Date || isSearchParams(value)) {\n return false;\n }\n\n if (isObject(value)) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` (plain object)\n if (proto === Object.prototype) {\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\n/**\n * Waits for the given time. When a signal is passed, the wait ends early once it is aborted.\n *\n * @param {number} ms - The time to wait in milliseconds.\n * @param {AbortSignal} [signal] - An optional signal that ends the wait when aborted.\n * @returns {Promise} - A promise that resolves with `true` once the wait is over.\n */\nexport const delayInvocation = (\n ms: number,\n signal?: AbortSignal,\n): Promise =>\n new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n if (signal) {\n signal.removeEventListener('abort', done);\n }\n resolve(true);\n };\n const timer = setTimeout(done, Math.min(ms, MAX_DELAY_MS));\n\n if (signal) {\n if (signal.aborted) {\n done();\n } else {\n signal.addEventListener('abort', done);\n }\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, depth = 0): any {\n if (depth >= MAX_DEPTH) {\n return data;\n }\n\n if (data && isObject(data) && typeof data.data !== UNDEFINED) {\n return flattenData(data.data, depth + 1);\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 // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key.toLowerCase()] = value;\n });\n } else {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n // Assigning \"__proto__\" would set the prototype of the result\n if (hasOwn(headers, key) && key !== '__proto__') {\n headersObject[key.toLowerCase()] = headers[key];\n }\n }\n }\n\n return headersObject;\n}\n\n/**\n * Determines if the current environment is a browser.\n *\n * @returns {boolean} - True if running in a browser environment, false otherwise.\n */\nexport function isBrowser(): boolean {\n // For node and some mobile frameworks like React Native, `add/removeEventListener` doesn't exist on window!\n return (\n typeof window !== UNDEFINED && typeof window.addEventListener === FUNCTION\n );\n}\n\n/**\n * Creates an abort/timeout error compatible with all JS runtimes.\n * Falls back to a plain Error with the correct `name` when DOMException is unavailable (e.g. React Native).\n *\n * @param {string} message - The error message.\n * @param {string} name - The error name (e.g. 'AbortError', 'TimeoutError').\n * @returns {DOMException | Error} - An error object with the specified name.\n */\nexport function createAbortError(\n message: string,\n name: string,\n): DOMException | Error {\n if (typeof DOMException !== UNDEFINED) {\n return new DOMException(message, name);\n }\n\n const error = new Error(message);\n error.name = name;\n\n return error;\n}\n\n/**\n * Detects if the user is on a slow network connection\n * @returns {boolean} True if connection is slow, false otherwise or if detection unavailable\n */\nexport const isSlowConnection = (): boolean => {\n const conn = typeof navigator !== UNDEFINED && (navigator as any).connection;\n\n return conn && ['slow-2g', '2g', '3g'].includes(conn.effectiveType);\n};\n\n/**\n * Detects if the page is hidden, e.g. when its tab is in the background or the window is minimized\n * @returns {boolean} True if the page is hidden, false otherwise or outside browsers\n */\nexport const isPageHidden = (): boolean =>\n typeof document !== UNDEFINED && document.visibilityState === 'hidden';\n\n/**\n * Detects if the browser is offline\n * @returns {boolean} True if the browser is offline, false otherwise or if the connection state is unknown\n */\nexport const isOffline = (): boolean =>\n typeof navigator !== UNDEFINED && navigator.onLine === false;\n","import { FUNCTION } from './constants';\nimport type { InterceptorFunction } from './types/interceptor-manager';\nimport { isObject, sanitizeObject } from './utils';\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 Args - Type of additional arguments.\n * @template I - Type of interceptors.\n *\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n * @param {T} data - The data object to process.\n * @param {...Args} args - Additional arguments to pass to interceptors.\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptors<\n T extends object,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Args extends any[] = any[],\n I = InterceptorFunction | InterceptorFunction[],\n>(interceptors: I | undefined, data: T, ...args: Args): Promise {\n if (!interceptors) {\n return;\n }\n\n const merge = (v: unknown) =>\n v &&\n isObject(data) &&\n isObject(v) &&\n Object.assign(data, sanitizeObject(v));\n\n if (typeof interceptors === FUNCTION) {\n merge(await (interceptors as InterceptorFunction)(data, ...args));\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n merge(await interceptor(data, ...args));\n }\n }\n}\n","import type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\n/**\n * This is a base error class\n */\nexport class FetchError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends Error {\n // Declared only, and set in the constructor, as class fields would need a helper in the ES2018 bundle\n declare status: number;\n declare statusText: string;\n declare config: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >;\n declare isCancelled: boolean;\n declare request: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >;\n declare response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null;\n\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message);\n\n this.request = request;\n this.response = response;\n this.status = response ? response.status : 0;\n this.statusText = response ? response.statusText : '';\n this.config = request;\n this.isCancelled = false;\n this.name = 'FetchError';\n }\n}\n","import { FetchError } from './fetch-error';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\nexport class ResponseError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends FetchError {\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message, request, response);\n\n this.name = 'ResponseError';\n }\n}\n","/**\n * @module timeout-wheel\n * @description\n * Ultra-minimal timing wheel implementation optimized for max performance & many requests.\n * For most of the cases it's 4-100x faster than setTimeout and setInterval alone.\n * Provides efficient scheduling and cancellation of timeouts using a circular array.\n *\n * Position 0 → 1 → 2 → ... → 599 → 0 → 1 → 2 ...\n * Time: 0s 1s 2s 599s 600s 601s 602s\n *\n * The timing wheel consists of 600 slots (one per second for 10 min).\n * Each slot contains a list of timeout items, each associated with a unique key and callback.\n * Timeouts are scheduled by placing them in the appropriate slot based on the delay in seconds.\n * The wheel advances every second, executing and removing callbacks as their timeouts expire.\n * Defaults to setTimeout if the delay doesn't fit in the wheel (~10 minutes) or is not divisible by 1000.\n *\n * @remarks\n * - Designed for minimal footprint and simplicity.\n * - Only supports second-level granularity (minimum timeout: 1 second).\n * - Timeouts never fire early, but may fire up to 1 second late.\n * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { MAX_DELAY_MS } from './constants';\nimport { noop, timeNow } from './utils';\n\ntype TimeoutCallback = () => unknown | Promise;\ntype TimeoutItem = [string, TimeoutCallback]; // [key, callback]\n\nconst WHEEL_SIZE = 600; // 600 slots for 10 min (1 slot per second)\nconst SECOND = 1000; // 1 second in milliseconds\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\nlet lastTick = 0; // Time when the wheel last advanced (or started)\nlet timer: NodeJS.Timeout | null = null;\n\nconst handleCallback = ([key, callback]: TimeoutItem): void => {\n keyMap.delete(key);\n\n try {\n const result = callback();\n if (result && result instanceof Promise) {\n // Silently ignore async errors to prevent wheel from stopping\n result.catch(noop);\n }\n } catch {\n // Ignore callback errors to prevent wheel from stopping\n }\n};\n\nexport const addTimeout = (\n key: string,\n cb: TimeoutCallback,\n ms: number,\n): void => {\n removeTimeout(key);\n\n // A running wheel is already part-way through its current second, so the timeout\n // waits one more slot to never fire early. A new wheel starts its first second now.\n const seconds = ms / SECOND + (timer && timeNow() !== lastTick ? 1 : 0);\n\n // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || seconds >= WHEEL_SIZE || ms % SECOND !== 0) {\n keyMap.set(key, [\n setTimeout(\n handleCallback.bind(null, [key, cb]),\n Math.min(ms, MAX_DELAY_MS),\n ),\n ]); // Store timeout ID instead of slot\n\n return;\n }\n\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n lastTick = timeNow();\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n lastTick = timeNow();\n const slot = wheel[position];\n\n // Use slot.length directly (not cached) so mid-iteration mutations\n // from callbacks (e.g. removeTimeout) are handled correctly\n for (let i = 0; i < slot.length; i++) {\n handleCallback(slot[i]);\n }\n\n slot.length = 0; // Reuse array, avoid GC allocation\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }, SECOND);\n }\n};\n\nexport const removeTimeout = (key: string): void => {\n const slotOrTimeout = keyMap.get(key);\n\n if (slotOrTimeout !== undefined) {\n // It's a Timeout object from setTimeout\n if (Array.isArray(slotOrTimeout)) {\n clearTimeout(slotOrTimeout[0]);\n } else {\n const slotArr = wheel[slotOrTimeout];\n\n for (let i = 0; i < slotArr.length; i++) {\n if (slotArr[i][0] === key) {\n slotArr.splice(i, 1);\n break;\n }\n }\n }\n\n keyMap.delete(key);\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }\n};\n\nexport const clearAllTimeouts = () => {\n // Clear native setTimeout timeouts first!\n keyMap.forEach((value) => {\n if (Array.isArray(value)) {\n clearTimeout(value[0]);\n }\n });\n\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n\n keyMap.clear();\n\n for (let i = 0; i < WHEEL_SIZE; i++) {\n wheel[i].length = 0;\n }\n\n position = 0;\n};\n","/**\n * @module inflight-manager\n *\n * Manages in-flight asynchronous requests using unique keys to enable deduplication and cancellation.\n *\n * Provides utilities for:\n * - Deduplication of requests within a configurable time window (`dedupeTime`)\n * - Timeout management and automatic request abortion\n * - AbortController lifecycle and cancellation logic\n * - Concurrency control and request state tracking\n * - In-flight promise deduplication to prevent duplicate network calls\n *\n * @remarks\n * - Requests with the same key within the deduplication interval share the same AbortController and in-flight promise.\n * - Supports cancellation of previous requests when a new one with the same key is issued, if `isCancellable` is enabled.\n * - Timeout logic ensures requests are aborted after a specified duration, if enabled.\n * - Internal queue state is managed via a Map, keyed by request identifier.\n * - Polled requests are also marked as \"in-flight\" to prevent duplicate requests.\n */\n\nimport { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { createAbortError, timeNow } from './utils';\n\nexport type InFlightItem = [\n AbortController, // AbortController for the request\n boolean, // Whether timeout is enabled for the request\n number, // Timestamp when the request was marked in-flight\n boolean, // isCancellable - whether the request can be cancelled\n Promise | null, // Optional in-flight promise for deduplication\n];\n\nconst inFlight: Map = 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 {string | null} key - Unique key for the request (e.g. cache key).\n * @param {string} url - The request URL (for error messages/timeouts).\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 {AbortController} - A promise that resolves to an AbortController.\n */\nexport function markInFlight(\n key: string | null,\n url: string,\n timeout: number | undefined,\n dedupeTime: number,\n isCancellable: boolean,\n isTimeoutEnabled: boolean,\n): AbortController {\n if (!key) {\n return new AbortController();\n }\n\n const now = timeNow();\n const item = inFlight.get(key);\n let prevPromise: Promise | null = null;\n\n // Previous request is in-flight, check if we can reuse it\n if (item) {\n const prevController = item[0];\n const prevIsCancellable = item[3];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (\n !prevIsCancellable &&\n now - item[2] < dedupeTime &&\n !prevController.signal.aborted\n ) {\n return prevController;\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 (prevIsCancellable) {\n prevController.abort(\n createAbortError('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n removeTimeout(key);\n prevPromise = item[4];\n }\n\n const controller = new AbortController();\n\n inFlight.set(key, [\n controller,\n isTimeoutEnabled,\n now,\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n createAbortError(url + ' aborted due to timeout', TIMEOUT_ERROR),\n );\n },\n timeout as number,\n );\n }\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param key - Unique key for the request.\n * @param {boolean} error - Optional error to abort the request with. If null, the request is simply removed but no abort sent.\n * @returns {Promise} - A promise that resolves when the request is aborted and removed.\n */\nexport async function abortRequest(\n key: string | null,\n error: DOMException | Error | null | string = null,\n): Promise {\n // If the key is not in the queue, there's nothing to remove\n if (key) {\n const item = inFlight.get(key);\n\n if (item) {\n // If the request is not yet aborted, abort it with the provided error\n if (error) {\n const controller = item[0];\n controller.abort(error);\n }\n\n removeInFlight(key);\n }\n }\n}\n\n/**\n * Removes a request from the in-flight queue without aborting or clearing timeout.\n *\n * @param key - Unique key for the request.\n */\nexport function removeInFlight(key: string | null): void {\n removeTimeout(key!);\n inFlight.delete(key!);\n}\n\n/**\n * Gets the AbortController for a request key.\n *\n * @param key - Unique key for the request.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n key: string,\n): Promise {\n const item = inFlight.get(key);\n\n return item && item[0];\n}\n\n/**\n * Adds helpers for in-flight promise deduplication.\n *\n * @param key - Unique key for the request.\n * @param promise - The promise to store.\n */\nexport function setInFlightPromise(\n key: string,\n promise: Promise,\n): void {\n const item = inFlight.get(key);\n if (item) {\n // store the promise at index 4 — item is already the Map's reference, no need to re-set\n item[4] = promise;\n }\n}\n\n/**\n * Retrieves the in-flight promise for a request key if it exists and is within the dedupeTime interval.\n *\n * @param key - Unique key for the request.\n * @param dedupeTime - Deduplication time in milliseconds.\n * @returns {Promise | null} - The in-flight promise or null.\n */\nexport function getInFlightPromise(\n key: string | null,\n dedupeTime: number,\n): Promise | null {\n if (!key) {\n return null;\n }\n\n const prevReq = inFlight.get(key);\n\n if (\n prevReq &&\n // If the request is in-flight and has a promise\n prevReq[4] &&\n // If the request is cancellable, we will not reuse it\n !prevReq[3] &&\n // If the request is within the dedupeTime\n timeNow() - prevReq[2] < dedupeTime &&\n // If one request is cancelled, ALL deduped requests get cancelled\n !prevReq[0].signal.aborted\n ) {\n return prevReq[4] as Promise;\n }\n\n return null;\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","/**\n * @module revalidator-manager\n *\n * Provides utilities for managing cache revalidation functions, including:\n * - Registering and unregistering revalidators for specific cache keys.\n * - Triggering revalidation for a given key.\n * - Enabling or disabling automatic revalidation on window focus and if user comes back online for specific keys.\n * - Attaching and removing global focus and online event handlers to trigger revalidation.\n *\n * Revalidators are functions that can be registered to revalidate cache entries when needed.\n * They are typically used to refresh data in the cache when the window gains focus or when specific actions occur.\n * @performance O(1) lookup by key makes it blazing fast to register, unregister, and revalidate cache entries.\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n * @remarks\n * - Designed to be used in various environments (Deno, Node.js, Bun, Browser, etc.) to ensure cache consistency and freshness.\n */\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { FetchResponse } from './types';\nimport { isBrowser, noop, timeNow } from './utils';\n\nexport type RevalidatorFn = (\n isStaleRevalidation?: boolean,\n) => Promise;\n\ntype EventType = 'focus' | 'online';\n\ntype RevalidatorEntry = [\n RevalidatorFn, // main revalidator\n number, // lastUsed\n number, // ttl\n number?, // staleTime\n RevalidatorFn?, // bgRevalidator\n boolean?, // refetchOnFocus\n boolean?, // refetchOnReconnect\n number?, // focusThrottleInterval\n];\n\nconst DEFAULT_TTL = 3 * 60 * 1000; // Default TTL of 3 minutes\nconst revalidators = new Map();\n\n/**\n * Stores cleanup functions for active event handlers (browser or custom providers).\n * Each entry removes the corresponding event listener when called.\n * @remarks\n * - Improves performance by reducing the number of event listeners.\n * - Enables efficient O(1) lookup and management of event handlers for revalidation.\n */\nconst eventHandlers = new Map void>();\n\n/** Subscribe to an event and return a cleanup function */\nexport type EventProvider = (handler: () => void) => () => void;\n\nconst customEventProviders = new Map();\n\n/**\n * Registers a custom event provider for 'focus' or 'online' events.\n * Useful for non-browser environments like React Native.\n *\n * @param type - The event type ('focus' or 'online').\n * @param provider - A function that subscribes to the event and returns a cleanup function.\n */\nexport function setEventProvider(\n type: EventType,\n provider: EventProvider,\n): void {\n customEventProviders.set(type, provider);\n\n // Re-register if already active\n if (eventHandlers.has(type)) {\n removeEventHandler(type);\n addEventHandler(type);\n }\n}\n\n/**\n * Triggers revalidation for all registered entries based on the given event type.\n * For example, if it's a 'focus' event, it will revalidate entries that have the `refetchOnFocus` flag set.\n * Updates the timestamp and invokes the revalidator function for each applicable entry.\n *\n * @param type - The type of event that caused the revalidation (e.g., 'focus' or 'online').\n * @param isStaleRevalidation - If `true`, uses background revalidator and doesn't mark as in-flight.\n * @param isThrottled - If `true`, skips entries that were requested or revalidated within their `focusThrottleInterval`.\n */\nexport function revalidateAll(\n type: EventType,\n isStaleRevalidation: boolean = true,\n isThrottled: boolean = false,\n) {\n const flagIndex = type === 'focus' ? 5 : 6;\n const now = timeNow();\n\n revalidators.forEach((entry) => {\n if (!entry[flagIndex] || (isThrottled && now - entry[1] < entry[7]!)) {\n return;\n }\n\n entry[1] = now;\n\n // If it's a stale revalidation, use the background revalidator function\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n if (revalidator) {\n Promise.resolve(revalidator(isStaleRevalidation)).catch(noop);\n }\n });\n}\n\n/**\n * Revalidates an entry by executing the registered revalidation function.\n *\n * @param key The unique identifier for the cache entry to revalidate. If `null`, no revalidation occurs.\n * @param isStaleRevalidation - If `true`, it does not mark revalidated requests as in-flight.\n * @returns A promise that resolves to the result of the revalidator function, or\n * `null` if no key or revalidator is found, or a `FetchResponse` if applicable.\n */\nexport async function revalidate(\n key: string | null,\n isStaleRevalidation: boolean = false,\n): Promise {\n // If no key is provided, no revalidation occurs\n if (!key) {\n return null;\n }\n\n const entry = revalidators.get(key);\n\n if (entry) {\n // Update only the lastUsed timestamp without resetting the whole array\n entry[1] = timeNow();\n\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n // If no revalidator function is registered, return null\n if (revalidator) {\n return await revalidator(isStaleRevalidation);\n }\n }\n\n // If no revalidator is registered for the key, return null\n return null;\n}\n\n/**\n * Removes all revalidators associated with the specified event type.\n *\n * @param type - The event type whose revalidators should be removed.\n */\nexport function removeRevalidators(type: EventType) {\n removeEventHandler(type);\n\n const flagIndex = type === 'focus' ? 5 : 6;\n\n // Clear all revalidators with this flag\n revalidators.forEach((entry, key) => {\n if (entry[flagIndex]) {\n removeRevalidator(key);\n }\n });\n}\n\n/**\n * Registers a generic revalidation event handler for the specified event type.\n * Supports browser window events and custom event providers (e.g. for React Native).\n * Ensures the handler is only added once.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'online').\n */\nfunction addEventHandler(event: EventType) {\n if (eventHandlers.has(event)) {\n return;\n }\n\n // Focus events are throttled, so that e.g. switching between tabs quickly doesn't revalidate every time\n const handler = revalidateAll.bind(null, event, true, event === 'focus');\n\n // Priority 1: Custom event provider (works in any environment including React Native)\n const customProvider = customEventProviders.get(event);\n\n if (customProvider) {\n const cleanup = customProvider(handler);\n\n eventHandlers.set(event, cleanup);\n\n return;\n }\n\n // Priority 2: Browser window events\n if (isBrowser()) {\n window.addEventListener(event, handler);\n\n eventHandlers.set(event, () => window.removeEventListener(event, handler));\n }\n}\n\n/**\n * Removes the event handler for the specified event type.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n const cleanup = eventHandlers.get(event);\n\n if (cleanup) {\n cleanup();\n eventHandlers.delete(event);\n }\n}\n\n/**\n * Registers a revalidation functions for a specific cache key.\n *\n * @param {string} key Cache key to utilize\n * @param {RevalidatorFn} revalidatorFn Main revalidation function (marks in-flight requests)\n * @param {number} [ttl] Time to live in milliseconds (default: 3 minutes)\n * @param {number} [staleTime] Time (in seconds) after which the cache entry is considered stale\n * @param {RevalidatorFn} [bgRevalidatorFn] For stale revalidation (does not mark in-flight requests)\n * @param {boolean} [refetchOnFocus] Whether to revalidate on window focus\n * @param {boolean} [refetchOnReconnect] Whether to revalidate on network reconnect\n * @param {number} [focusThrottleInterval] Time (in milliseconds) after a request or revalidation during which focus events don't revalidate it\n */\nexport function addRevalidator(\n key: string,\n revalidatorFn: RevalidatorFn, // Main revalidation function (marks in-flight requests)\n ttl?: number,\n staleTime?: number,\n bgRevalidatorFn?: RevalidatorFn, // For stale revalidation (does not mark in-flight requests)\n refetchOnFocus?: boolean,\n refetchOnReconnect?: boolean,\n focusThrottleInterval?: number,\n) {\n // Existing entries are updated in place\n const entry = revalidators.get(key) || ([] as unknown as RevalidatorEntry);\n\n entry[0] = revalidatorFn;\n entry[1] = timeNow();\n entry[2] = ttl ?? DEFAULT_TTL;\n entry[3] = staleTime;\n entry[4] = bgRevalidatorFn;\n entry[5] = refetchOnFocus;\n entry[6] = refetchOnReconnect;\n entry[7] = focusThrottleInterval;\n\n revalidators.set(key, entry);\n\n if (refetchOnFocus) {\n addEventHandler('focus');\n }\n\n if (refetchOnReconnect) {\n addEventHandler('online');\n }\n\n if (staleTime) {\n addTimeout('s:' + key, revalidate.bind(null, key, true), staleTime * 1000);\n }\n}\n\nexport function removeRevalidator(key: string) {\n revalidators.delete(key);\n\n // Clean up stale timer\n removeTimeout('s:' + key);\n}\n\n/**\n * Periodically cleans up expired revalidators from the registry.\n * Removes any revalidator whose TTL has expired.\n *\n * @param {number} intervalMs How often to run cleanup (default: 3 minutes)\n * @returns {() => void} A function to stop the periodic cleanup\n */\nexport function startRevalidatorCleanup(\n intervalMs: number = DEFAULT_TTL,\n): () => void {\n const intervalId = setInterval(() => {\n const now = timeNow();\n\n revalidators.forEach(\n ([, lastUsed, ttl, , , refetchOnFocus, refetchOnReconnect], key) => {\n // Skip focus-only or reconnect-only revalidators to keep them alive\n if (refetchOnFocus || refetchOnReconnect) {\n return;\n }\n\n if (ttl > 0 && now - lastUsed > ttl) {\n removeRevalidator(key);\n }\n },\n );\n }, intervalMs);\n\n return () => clearInterval(intervalId);\n}\n","/**\n * Manages a set of listeners (subscribers) for arbitrary string keys, allowing cross-context or cross-component\n * cache updates and synchronization. Provides functions to add, remove, and notify listeners, as well as a\n * convenient subscribe/unsubscribe API.\n *\n * @template T - The type of the response object passed to listeners.\n *\n * @remarks\n * - Listeners are grouped by a string key, which typically represents a cache key or resource identifier.\n * - When `notifySubscribers` is called for a key, all listeners registered for that key are invoked with the provided response.\n * - The `subscribe` function returns an unsubscribe function for convenient cleanup.\n *\n * @example\n * ```ts\n * const unsubscribe = subscribe('user:123', (response) => {\n * // handle updated data\n * });\n * // Later, to stop listening:\n * unsubscribe();\n * ```\n */\n\nimport { noop } from './utils';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Listener = (response: T) => void;\n\nconst listeners = new Map>();\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n let set = listeners.get(key);\n\n if (!set) {\n listeners.set(key, (set = new Set()));\n }\n\n set.add(fn);\n}\n\nexport function removeListener(key: string, fn: Listener) {\n const set = listeners.get(key);\n\n if (set) {\n set.delete(fn);\n\n // If the set is empty, remove the key from the listeners map\n if (set.size === 0) {\n listeners.delete(key);\n }\n }\n}\n\nexport function notifySubscribers(key: string, response: T) {\n const fns = listeners.get(key);\n\n if (fns) {\n if (fns.size === 1) {\n // If there's only one listener, call it directly\n const fn = fns.values().next().value;\n fn!(response);\n } else {\n fns.forEach((fn) => fn(response));\n }\n }\n}\n\nexport function subscribe(key: string | null, fn: (response: T) => void) {\n if (!key) {\n // No op if no key is provided\n return noop;\n }\n\n addListener(key, fn);\n\n // Return an unsubscribe function\n return () => {\n removeListener(key, fn);\n };\n}\n","import { processHeaders } from './utils';\nimport {\n GET,\n APPLICATION_JSON,\n HEAD,\n STRING,\n CHARSET_UTF_8,\n CONTENT_TYPE,\n REJECT,\n UNDEFINED,\n APPLICATION_CONTENT_TYPE,\n} from './constants';\nimport type {\n HeadersObject,\n Method,\n RequestConfig,\n} from './types/request-handler';\nimport {\n replaceUrlPathParams,\n appendQueryParams,\n isSearchParams,\n isJSONSerializable,\n isSlowConnection,\n isAbsoluteUrl,\n sanitizeObject,\n isObject,\n} from './utils';\n\nconst defaultTimeoutMs = (isSlowConnection() ? 60 : 30) * 1000;\n\nexport const defaultConfig: RequestConfig = {\n strategy: REJECT,\n timeout: defaultTimeoutMs, // 30 seconds (60 on slow connections)\n loadingTimeout: defaultTimeoutMs / 10, // 3 seconds (6 on slow connections)\n focusThrottleInterval: 5000, // 5 seconds\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n },\n retry: {\n delay: defaultTimeoutMs / 30, // 1 second (2 on slow connections)\n maxDelay: defaultTimeoutMs, // 30 seconds (60 on slow connections)\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 // Idempotent methods, which can be repeated safely, unlike e.g. POST requests that create resources\n methods: [GET, HEAD, 'PUT', 'DELETE', 'OPTIONS', 'TRACE'],\n },\n};\n\n/**\n * Overwrites the default configuration with the provided custom configuration.\n *\n * @param {Partial} customConfig - The custom configuration to merge into the default config.\n * @returns {Partial} - The updated default configuration object.\n */\nexport function setDefaultConfig(\n customConfig: Partial,\n): Partial {\n const sanitized = sanitizeObject(customConfig);\n\n // Merge nested retry and headers settings into the current defaults instead of replacing them\n return mergeConfigs(\n { retry: defaultConfig.retry, headers: defaultConfig.headers },\n sanitized,\n defaultConfig,\n );\n}\n\n/**\n * Returns a shallow copy of the current default configuration.\n *\n * @returns {RequestConfig} - The current default configuration.\n */\nexport function getDefaultConfig(): RequestConfig {\n return { ...defaultConfig };\n}\n\n/**\n * Build request configuration from defaults and overrides.\n * This function merges the default configuration with the provided request configuration,\n * @param {string} url - Request url\n * @param {RequestConfig | null | undefined} reqConfig - Request configuration\n * @return {RequestConfig} - Merged request configuration\n */\nexport function buildConfig(\n url: string,\n reqConfig?: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null,\n): RequestConfig {\n // Merging gives the request its own copies of nested objects like headers, so that\n // mutations (e.g. by interceptors) never leak into the global defaults\n const merged = mergeConfigs(\n defaultConfig,\n reqConfig ? sanitizeObject(reqConfig) : {},\n );\n\n return buildFetcherConfig(url, merged);\n}\n\n/**\n * Builds the fetcher configuration by setting the method, body, headers, and URL.\n * It also handles query parameters and path parameters. This fn mutates the passed `requestConfig` object.\n * @param {string} url - The endpoint URL to which the request will be sent.\n * @param {RequestConfig} requestConfig - The request configuration object containing method, body, headers, and other options.\n * @return {RequestConfig} - The modified request configuration object with the URL, method, body, and headers set appropriately.\n **/\nexport function buildFetcherConfig(\n url: string,\n requestConfig: RequestConfig,\n): RequestConfig {\n let method = requestConfig.method as Method;\n method = method ? (method.toUpperCase() as Method) : GET;\n\n let body: RequestConfig['data'] | undefined;\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (method !== GET && method !== HEAD) {\n body = requestConfig.body ?? requestConfig.data;\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (body && typeof body !== STRING && isJSONSerializable(body)) {\n body = JSON.stringify(body);\n }\n }\n\n setContentTypeIfNeeded(requestConfig.headers, body);\n\n // Native fetch compatible settings\n const credentials = requestConfig.withCredentials\n ? 'include'\n : requestConfig.credentials;\n\n // The explicitly passed query params\n const dynamicUrl = replaceUrlPathParams(url, requestConfig.urlPathParams);\n const urlPath = appendQueryParams(dynamicUrl, requestConfig.params);\n const isFullUrl = isAbsoluteUrl(url);\n const baseURL = isFullUrl\n ? ''\n : requestConfig.baseURL || requestConfig.apiUrl || '';\n\n // Join as a path, as plain concatenation could extend the host of the baseURL,\n // e.g. \"https://api.example.com\" + \".evil.com\" would point to another host\n const separator =\n baseURL && urlPath && !baseURL.endsWith('/') && !/^[/?#]/.test(urlPath)\n ? '/'\n : '';\n\n requestConfig.url = baseURL + separator + urlPath;\n requestConfig.method = method;\n requestConfig.credentials = credentials;\n requestConfig.body = body;\n\n return requestConfig;\n}\n\n/**\n * Ensures the `Content-Type` header is set to `application/json; charset=utf-8`\n * if it is not already present and the request method and body meet specific conditions.\n *\n * @param headers - The headers object to modify. Can be an instance of `Headers`\n * or a plain object conforming to `HeadersInit`.\n * @param body - The optional body of the request. If no body is provided and the\n * method is 'GET' or 'HEAD', the function exits without modifying headers.\n */\nfunction setContentTypeIfNeeded(\n headers?: HeadersInit | HeadersObject,\n body?: unknown,\n): void {\n // If no headers are provided, or if the body is not set and the method is PUT or DELETE, do nothing\n if (!headers || !body) {\n return;\n }\n\n // Types that should not have Content-Type set (browser handles these)\n if (\n body instanceof FormData || // Browser automatically sets multipart/form-data with boundary\n (typeof Blob !== UNDEFINED && body instanceof Blob) || // Blob/File (a File is a Blob) already have their own MIME types, don't override\n (typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream) // Stream type should be determined by the stream source\n ) {\n return;\n }\n\n let contentTypeValue: string;\n\n if (isSearchParams(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded';\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'octet-stream';\n } else if (isJSONSerializable(body)) {\n contentTypeValue = APPLICATION_JSON + ';' + CHARSET_UTF_8;\n } else {\n // Do not set Content-Type if content is not recognizable\n return;\n }\n\n if (headers instanceof Headers) {\n if (!headers.has(CONTENT_TYPE)) {\n headers.set(CONTENT_TYPE, contentTypeValue);\n }\n } else if (\n isObject(headers) &&\n !Array.isArray(headers) &&\n // Header names are case-insensitive, so check the normalized (lowercase) headers\n !processHeaders(headers as HeadersObject)[CONTENT_TYPE.toLowerCase()]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\n// The interceptors that are merged instead of replaced\nconst INTERCEPTORS = [\n 'onRequest',\n 'onResponse',\n 'onError',\n 'onLoadingSlow',\n] as const;\n\n/**\n * Merges two request configurations, applying overrides from the second config to the first.\n * Handles special merging for nested properties like 'retry' and 'headers' (deep merge),\n * and concatenates interceptor arrays for 'onRequest', 'onResponse', 'onError' and 'onLoadingSlow'.\n * If a target config is provided, it mutates that object; otherwise, creates a new one.\n *\n * @param {RequestConfig} baseConfig - The base configuration object to merge from.\n * @param {RequestConfig} overrideConfig - The override configuration object to apply on top of the base.\n * @param {RequestConfig} [targetConfig={}] - Optional target configuration object to merge into (mutated in place).\n * @returns {RequestConfig} The merged configuration object.\n *\n * @example\n * const base = { timeout: 5000, headers: { 'Accept': 'application/json' } };\n * const override = { timeout: 10000, headers: { 'Authorization': 'Bearer token' } };\n * const merged = mergeConfigs(base, override);\n * // Result: { timeout: 10000, headers: { Accept: 'application/json', Authorization: 'Bearer token' } }\n */\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig = {},\n): RequestConfig {\n Object.assign(targetConfig, baseConfig, overrideConfig);\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', baseConfig, overrideConfig, targetConfig);\n mergeConfig('headers', baseConfig, overrideConfig, targetConfig);\n\n // Merge interceptors efficiently\n for (const property of INTERCEPTORS) {\n mergeInterceptors(property, baseConfig, overrideConfig, targetConfig);\n }\n\n return targetConfig;\n}\n\n/**\n * Efficiently merges interceptor functions from base and new configs\n */\nfunction mergeInterceptors<\n K extends\n 'onRequest' | 'onResponse' | 'onError' | 'onRetry' | 'onLoadingSlow',\n>(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const baseInterceptor = baseConfig[property];\n const newInterceptor = overrideConfig[property];\n\n if (baseInterceptor && newInterceptor) {\n // This is the only LIFO interceptor, so we apply it after the response is prepared\n targetConfig[property] = (\n property === 'onResponse'\n ? [].concat(newInterceptor as never, baseInterceptor as never)\n : [].concat(baseInterceptor as never, newInterceptor as never)\n ) as RequestConfig[K];\n } else if (baseInterceptor || newInterceptor) {\n targetConfig[property] = baseInterceptor || newInterceptor;\n }\n}\n\n/**\n * Merges the specified property from the base configuration and the override configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and override configurations. Must be a key of RequestConfig.\n * @param {RequestConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestConfig} overrideConfig - The override configuration object that contains user-specific settings to merge.\n * @param {RequestConfig} targetConfig - The configuration object that will receive the merged properties.\n */\nexport function mergeConfig(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n if (override) {\n if (property === 'headers') {\n // Handle Headers instances which don't expose entries as own enumerable properties\n const isInstance =\n (base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers;\n const merged: HeadersObject = isInstance\n ? processHeaders(base)\n : { ...(base as HeadersObject) };\n const overrides: HeadersObject = isInstance\n ? processHeaders(override)\n : sanitizeObject(override as HeadersObject);\n\n // Header names are case-insensitive, so replace existing entries instead of duplicating them\n for (const key of Object.keys(overrides)) {\n const lowerKey = key.toLowerCase();\n\n for (const existingKey in merged) {\n if (existingKey.toLowerCase() === lowerKey) {\n delete merged[existingKey];\n }\n }\n\n merged[key] = overrides[key];\n }\n\n targetConfig[property] = merged as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...sanitizeObject(override as Record),\n } as RequestConfig[K];\n }\n } else if (\n override === undefined &&\n isObject(base) &&\n !((base as Headers | HeadersObject) instanceof Headers)\n ) {\n // Copy so that mutating the merged config never changes the base config\n targetConfig[property] = { ...base } as RequestConfig[K];\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport type {\n CacheKeyFunction,\n DefaultResponse,\n FetchResponse,\n MutationSettings,\n RequestConfig,\n} from './types/request-handler';\nimport type {\n CacheEntry,\n CacheStore,\n StoredResponse,\n} from './types/cache-manager';\nimport { GET, STRING } from './constants';\nimport {\n isJSONSerializable,\n isObject,\n isSearchParams,\n noop,\n sanitizeObject,\n sortObject,\n timeNow,\n} from './utils';\nimport { revalidate } from './revalidator-manager';\nimport { notifySubscribers } from './pubsub-manager';\nimport type { DefaultPayload, DefaultParams, DefaultUrlParams } from './types';\nimport { removeInFlight } from './inflight-manager';\nimport { addTimeout } from './timeout-wheel';\nimport { defaultConfig } from './config-handler';\nimport { processHeaders } from './utils';\n\nexport const IMMEDIATE_DISCARD_CACHE_TIME = 0; // Use it for cache entries that need to be persistent until unused by components or manually deleted\n\nconst _cache = new Map>();\n// The cache stores that keep copies of cache entries, by cache key\nconst stores = new Map();\nconst DELIMITER = '|';\nconst MIN_LENGTH_TO_HASH = 64;\nconst CACHE_KEY_SANITIZE_PATTERN = /[^\\w\\-_|/:@.?=&~%#]/g;\nconst CACHE_KEY_NEEDS_SANITIZE = /[^\\w\\-_|/:@.?=&~%#]/; // Non-global for fast test\n\n/**\n * Headers that may affect HTTP response content and should be included in cache key generation.\n * Header names are matched case-insensitively.\n *\n * - Content negotiation: accept (response format, e.g. JSON or HTML), accept-language (localization), accept-encoding (compression)\n * - Authentication: authorization (access to protected resources)\n * - Request body metadata: content-type (how the request body is interpreted)\n * - Optional: referer (may influence behavior in some APIs), origin (CORS or tenant-specific APIs),\n * user-agent (if the server returns client-specific content), cookie (session-based responses; can fragment the cache heavily)\n * - Custom headers that may affect response content: x-api-key (token-based access), x-requested-with (AJAX requests),\n * x-client-id (per-client/partner identity), x-tenant-id (multi-tenant segmentation), x-user-id (explicit user context),\n * x-app-version (version-specific behavior), x-feature-flag (feature rollout), x-device-id (per device/app instance),\n * x-platform (e.g. 'ios', 'android', 'web'), x-session-id (if it affects the response directly), x-locale (like accept-language)\n */\nconst CACHE_KEY_HEADERS =\n /^(accept(-language|-encoding)?|authorization|content-type|referer|origin|user-agent|cookie|x-(api-key|requested-with|client-id|tenant-id|user-id|app-version|feature-flag|device-id|platform|session-id|locale))$/i;\n\n/**\n * Generates a unique 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 {RequestConfig} config - 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 {RequestCredentials} [credentials=\"same-origin\"] - Whether to include credentials (include, same-origin, omit).\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @returns {string} - A unique cache key string based on the provided options.\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(\n config: RequestConfig,\n cacheKeyCheck = true,\n): string {\n // This is super fast. Effectively a no-op if cacheKey is\n // a string or a function that returns a string.\n const key = config.cacheKey;\n\n if (key && cacheKeyCheck) {\n return typeof key === STRING\n ? (key as string)\n : (key as CacheKeyFunction)(config);\n }\n\n const {\n url = '',\n method = GET,\n headers = null,\n body = null,\n credentials = 'same-origin',\n } = config;\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 let headersString = '';\n if (headers) {\n let obj: Record;\n\n if (headers instanceof Headers) {\n obj = processHeaders(headers);\n } else {\n obj = headers as Record;\n }\n\n // Filter headers to only include those that affect request identity\n // Include only headers that affect request identity, not execution behavior\n const keys = Object.keys(obj);\n const len = keys.length;\n\n // Sort keys manually for fastest deterministic output\n if (len > 1) {\n keys.sort();\n }\n\n let str = '';\n for (let i = 0; i < len; ++i) {\n if (CACHE_KEY_HEADERS.test(keys[i])) {\n str += keys[i] + ':' + obj[keys[i]] + ';';\n }\n }\n\n headersString = hash(str);\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString;\n\n // For GET requests, return early with shorter cache key\n if (method === GET) {\n return sanitizeCacheKey(cacheStr);\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING || isSearchParams(body)) {\n const str = String(body);\n\n bodyString = str.length < MIN_LENGTH_TO_HASH ? str : hash(str); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Files can't be read synchronously, so they are identified by their object\n bodyString +=\n key +\n '=' +\n (typeof value === STRING ? value : 'F' + getObjectId(value as File)) +\n '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (isObject(body) && !isJSONSerializable(body)) {\n // Blobs, buffers, streams etc. can't be read synchronously, so they are identified by their object.\n // Two different bodies never share a key, while the same body object is still deduplicated.\n bodyString = 'B' + getObjectId(body);\n } else {\n const o = isObject(body)\n ? JSON.stringify(sortObject(body))\n : String(body);\n\n bodyString = o.length > MIN_LENGTH_TO_HASH ? hash(o) : o;\n }\n }\n\n return sanitizeCacheKey(cacheStr + DELIMITER + bodyString);\n}\n\nconst objectIds = new WeakMap();\nlet lastObjectId = 0;\n\n/**\n * Returns a unique id for an object, e.g. a request body that can't be serialized.\n *\n * @param {object} obj - The object to identify.\n * @returns {number} - The id of the object.\n */\nfunction getObjectId(obj: object): number {\n let id = objectIds.get(obj);\n\n if (!id) {\n objectIds.set(obj, (id = ++lastObjectId));\n }\n\n return id;\n}\n\n/**\n * Prevents cache poisoning by removal of control chars and unusual characters.\n * When anything is removed, a hash of the original key is appended so that keys\n * differing only in the removed characters (e.g. `?a[]=1` and `?a=1`) don't collide.\n *\n * @param {string} cacheStr - The raw cache key.\n * @returns {string} - The sanitized cache key.\n */\nfunction sanitizeCacheKey(cacheStr: string): string {\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '') +\n DELIMITER +\n hash(cacheStr)\n : cacheStr;\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the expiry time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(entry: CacheEntry): boolean {\n // No expiry time means the entry never expires\n if (!entry.expiry) {\n return false;\n }\n\n return timeNow() > entry.expiry;\n}\n\n/**\n * Retrieves a cached response from the internal cache using the provided key.\n *\n * @param key - The unique key identifying the cached entry. If null, returns null.\n * @returns The cached {@link FetchResponse} if found, otherwise null.\n */\nexport function getCacheData<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n key: string | null,\n): FetchResponse | null {\n if (!key) {\n return null;\n }\n\n const entry = _cache.get(key);\n\n return entry ? entry.data : null;\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 * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string | null,\n):\n | CacheEntry<\n FetchResponse\n >\n | null\n | undefined {\n return _cache.get(key as string);\n}\n\n/**\n * Sets a new cache entry or updates an existing one, with optional TTL (time-to-live).\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {number} [ttl] - Optional TTL in seconds. If not provided, the cache entry will not expire.\n * @param {number} [staleTime] - Optional stale time in seconds. If provided, the cache entry will be considered stale after this time.\n */\nexport function setCache(\n key: string,\n data: T,\n ttl?: number,\n staleTime?: number,\n): void {\n if (ttl === 0) {\n deleteCache(key);\n return;\n }\n\n const time = timeNow();\n const ttlMs = ttl ? ttl * 1000 : 0;\n const staleTimeMs = staleTime ? staleTime * 1000 : 0; // Ensure default value for staleTime\n\n _cache.set(key, {\n data,\n time,\n stale: staleTimeMs > 0 ? time + staleTimeMs : undefined, // Use undefined if staleTime is not set\n expiry: ttl === -1 ? undefined : time + ttlMs,\n });\n\n if (ttlMs > 0) {\n scheduleExpiry(key, ttlMs);\n }\n}\n\n/**\n * Deletes a cache entry once it expires.\n *\n * @param {string} key Cache key to utilize\n * @param {number} ms - The time until the entry expires, in milliseconds.\n */\nfunction scheduleExpiry(key: string, ms: number): void {\n addTimeout('c:' + key, () => deleteCache(key, true), ms);\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n * @param {boolean} [removeExpired=false] - If true, only deletes the cache entry if it is expired or stale.\n */\nexport function deleteCache(key: string, removeExpired: boolean = false): void {\n if (removeExpired) {\n const entry = getCache(key);\n\n // If the entry does not exist, or it is neither expired nor stale, do not delete\n if (!entry || !isCacheExpired(entry)) {\n return;\n }\n }\n\n _cache.delete(key);\n\n const store = stores.get(key);\n\n if (store) {\n stores.delete(key);\n callStore(() => store.delete(key));\n }\n}\n\n/**\n * Prunes the cache by removing entries that have expired based on the provided cache time.\n */\nexport function pruneCache(): void {\n _cache.clear();\n stores.clear();\n}\n\n/**\n * Calls a cache store method. Store errors, e.g. of a full localStorage, are ignored so that they can't break requests.\n *\n * @param {() => unknown} fn - The function calling the store.\n */\nfunction callStore(fn: () => unknown): void {\n try {\n Promise.resolve(fn()).catch(noop);\n } catch {\n // Ignored\n }\n}\n\n/**\n * Saves a copy of a cached response in a cache store, so that it can be restored later, e.g. after a page reload.\n *\n * @param {string} key Cache key to utilize\n * @param {CacheStore} [store] - The cache store. If not provided, nothing is saved.\n */\nfunction persistCache(key: string, store?: CacheStore): void {\n const entry = _cache.get(key);\n\n if (store && entry) {\n const { data, status, statusText, headers } = entry.data as FetchResponse;\n\n stores.set(key, store);\n callStore(() =>\n store.set(key, { ...entry, data: { data, status, statusText, headers } }),\n );\n }\n}\n\n/**\n * Reads the entry of a cache key from the cache store of a request, e.g. one saved during a previous page load.\n * Expired entries are deleted from the store.\n *\n * @param {string} key Cache key to utilize\n * @param {RequestConfig} requestConfig - The request configuration.\n * @returns {Promise | null>} - The stored entry, or null if there is no valid one or the in-memory cache has an entry already.\n */\nexport async function getStoredCache(\n key: string,\n requestConfig: RequestConfig,\n): Promise | null> {\n const store = requestConfig.cacheStore;\n\n if (!store || isCacheBypassed(requestConfig)) {\n return null;\n }\n\n let entry: CacheEntry | null | undefined;\n\n try {\n entry = await store.get(key);\n } catch {\n // A failing store is treated like an empty one\n return null;\n }\n\n // Another request may have cached a response in the meantime\n if (!entry || _cache.has(key)) {\n return null;\n }\n\n if (isCacheExpired(entry)) {\n callStore(() => store.delete(key));\n\n return null;\n }\n\n return entry;\n}\n\n/**\n * Caches a response restored from a cache store in memory, keeping its original stale and expiry times.\n *\n * @param {string} key Cache key to utilize\n * @param {CacheEntry} entry - The cache entry with the restored response.\n * @param {CacheStore} store - The cache store that the response was restored from.\n * @returns {boolean} - True if the restored response is fresh, false if it's stale.\n */\nexport function restoreCache(\n key: string,\n entry: CacheEntry,\n store: CacheStore,\n): boolean {\n _cache.set(key, entry);\n stores.set(key, store);\n\n if (entry.expiry) {\n scheduleExpiry(key, entry.expiry - timeNow());\n }\n\n notifySubscribers(key, entry.data);\n\n return !entry.stale || timeNow() < entry.stale;\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string | null} key Cache key to utilize. If null, no mutation occurs.\n * @param {ResponseData} newData - The new data to be cached.\n * @param {MutationSettings|undefined} settings - Mutation settings.\n */\nexport async function mutate<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n key: string | null,\n newData: ResponseData,\n settings?: MutationSettings,\n): Promise | null> {\n // If no key is provided, do nothing\n if (!key) {\n return null;\n }\n\n const entry = getCache(\n key,\n );\n\n if (!entry) {\n return null;\n }\n\n const updatedData = isObject(newData) ? sanitizeObject(newData) : newData;\n\n const updatedResponse = {\n ...entry.data,\n data: updatedData,\n };\n\n // The ETag belongs to the original data, so the changed data must not be revalidated with it\n const headers = updatedResponse.headers;\n\n if (headers && headers.etag) {\n updatedResponse.headers = { ...headers };\n delete updatedResponse.headers.etag;\n }\n\n const updatedEntry = {\n ...entry,\n data: updatedResponse,\n };\n\n _cache.set(key, updatedEntry);\n persistCache(key, stores.get(key));\n notifySubscribers(key, updatedResponse);\n\n if (settings && settings.refetch) {\n return await revalidate(key);\n }\n\n return null;\n}\n\n/**\n * Checks whether a request should bypass the cache, because of its cache buster or `cache: 'reload'`.\n *\n * @param {RequestConfig} requestConfig - The request configuration.\n * @returns {boolean} - True if the cache should be bypassed.\n */\nexport function isCacheBypassed(requestConfig: RequestConfig): boolean {\n const buster = requestConfig.cacheBuster || defaultConfig.cacheBuster;\n\n return (\n !!(buster && buster(requestConfig)) || requestConfig.cache === 'reload'\n );\n}\n\n/**\n * Retrieves a cached response if available and valid, otherwise returns null.\n *\n * @template ResponseData - The type of the response data.\n * @template RequestBody - The type of the request body.\n * @template QueryParams - The type of the query parameters.\n * @template PathParams - The type of the path parameters.\n * @param {string | null} cacheKey - The cache key to look up.\n * @param {number | undefined} cacheTime - The maximum time to cache entry.\n * @param {RequestConfig} requestConfig - The fetcher configuration.\n * @returns {FetchResponse | null} - The cached response or null.\n */\nexport function getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n cacheKey: string | null,\n cacheTime: number | undefined,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): FetchResponse | null {\n // If cache key or time is not provided, return null\n if (!cacheKey || cacheTime === undefined || cacheTime === null) {\n return null;\n }\n\n if (isCacheBypassed(requestConfig)) {\n return null;\n }\n\n // Retrieve the cached entry\n const entry = getCache(\n cacheKey,\n );\n\n if (!entry) {\n return null;\n }\n\n const isExpired = isCacheExpired(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n const data = entry.data;\n\n // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n // The placeholder stored while a request is in flight is not a response, so treat it as a miss\n return data && data.isFetching ? null : data;\n}\n\n/**\n * Sets or deletes the response cache based on cache settings and notifies subscribers.\n *\n * @param {FetchResponse} output - The response to cache.\n * @param {RequestConfig} requestConfig - The request configuration.\n * @param {boolean} [isError=false] - Whether the response is an error.\n */\nexport function handleResponseCache<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n output: FetchResponse,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n isError: boolean = false,\n): void {\n // It is string as it is called once request is made\n const cacheKey = requestConfig.cacheKey as string;\n\n if (cacheKey) {\n const cacheTime = requestConfig.cacheTime;\n const skipCache = requestConfig.skipCache;\n\n // Fast path: only set cache if cacheTime is positive and not skipping cache\n if (\n cacheTime &&\n (!isError || requestConfig.cacheErrors) &&\n !(skipCache && skipCache(output, requestConfig))\n ) {\n setCache(cacheKey, output, cacheTime, requestConfig.staleTime);\n\n // Error responses are only cached in memory\n if (!isError) {\n persistCache(cacheKey, requestConfig.cacheStore);\n }\n } else {\n const entry = getCache(cacheKey);\n\n // Don't let the in-flight placeholder outlive a request whose result isn't cached\n if (entry && entry.data && entry.data.isFetching) {\n deleteCache(cacheKey);\n }\n }\n\n notifySubscribers(cacheKey, output);\n removeInFlight(cacheKey);\n\n const prevCacheKey = requestConfig._prevKey;\n\n if (prevCacheKey) {\n removeInFlight(prevCacheKey);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { mutate } from './cache-manager';\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n FUNCTION,\n STRING,\n} from './constants';\nimport {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n ResponseError,\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n} from './types';\nimport { flattenData, isObject, processHeaders } from './utils';\n\n/**\n * Parses the response data based on the Content-Type header, or reads it as the given response type.\n *\n * @param response - The Response object to parse.\n * @param responseType - How to read the body regardless of its Content-Type, e.g. as a Blob, or `'stream'` to leave it unread.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse,\n responseType?: RequestConfig['responseType'],\n): Promise {\n // Bail early if response is null or undefined\n if (!response) {\n return null;\n }\n\n // Get the content-type header once\n const headers = (response as Response).headers;\n let contentType = headers && headers.get(CONTENT_TYPE);\n\n if (contentType) {\n // Lowercase and trim for consistent matching\n contentType = contentType.toLowerCase().trim();\n } else {\n contentType = '';\n }\n\n // Split for mime type without charset\n const mimeType = contentType.split(';', 1)[0];\n\n let data;\n\n try {\n if (responseType) {\n // The body is read as requested, or left unread as a stream to be read by the caller\n data =\n responseType === 'stream'\n ? response.body\n : await response[responseType]();\n } else if (\n mimeType.includes(APPLICATION_JSON) ||\n mimeType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (\n (mimeType.includes('multipart/form-data') || // Parse as FormData\n mimeType.includes(\n APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded', // Handle URL-encoded forms\n )) &&\n typeof response.formData === FUNCTION\n ) {\n data = await response.formData();\n } else if (/^(image|video|audio)\\/|octet-stream|pdf|zip/.test(mimeType)) {\n data = await response.arrayBuffer(); // Parse as ArrayBuffer for binary types\n } else {\n data = await response.text();\n\n if (typeof data === STRING) {\n const trimmed = data.trim();\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n data = JSON.parse(trimmed);\n } catch {\n // leave as text if parsing fails\n }\n }\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\n/**\n * Prepare response object with additional information.\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} config - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\nexport const prepareResponse = <\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n config: RequestConfig,\n error: ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null,\n): FetchResponse => {\n const defaultResponse = config.defaultResponse;\n const cacheKey = config.cacheKey;\n const mutatator = mutate.bind(null, cacheKey as string) as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >['mutate'];\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 ?? null,\n headers: null,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: false,\n isError: true,\n } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n const isNativeResponse =\n typeof Response === FUNCTION && response instanceof Response;\n\n let data = response.data;\n\n // Set the default response if the provided data is an empty object or array\n // Other objects, e.g. Blobs, buffers and streams, have no keys either, but aren't empty\n if (\n defaultResponse !== undefined &&\n (data === undefined ||\n data === null ||\n (/^\\[object (Object|Array)\\]$/.test(\n Object.prototype.toString.call(data),\n ) &&\n Object.keys(data).length === 0))\n ) {\n response.data = data = defaultResponse;\n }\n\n if (config.flattenResponse) {\n response.data = data = flattenData(data);\n }\n\n if (config.select) {\n response.data = data = config.select(data);\n }\n\n const headers = processHeaders(response.headers);\n\n // Native fetch Response extended by extra information\n if (isNativeResponse) {\n const output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > = {\n body: response.body,\n bodyUsed: response.bodyUsed,\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 // Convert methods to use arrow functions to preserve correct return types\n // Lazily construct Blob from ArrayBuffer\n blob: async () =>\n data instanceof ArrayBuffer ? new Blob([data]) : new Blob(),\n json: async () => data as ResponseData, // Return the already parsed JSON data\n text: async () => data as string, // Return the already parsed text data\n // The body was already read, so a copy of this response is returned instead of Response.clone()\n clone: () => ({ ...output }),\n arrayBuffer: async () =>\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0), // Return the ArrayBuffer directly\n formData: async () => (data instanceof FormData ? data : new FormData()), // Return the already parsed FormData\n bytes: async () =>\n new Uint8Array(data instanceof ArrayBuffer ? data : new ArrayBuffer(0)),\n // Enhance the response with extra information\n error,\n data,\n headers,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: response.ok && !error,\n isError: !!error,\n };\n\n return output;\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 (isObject(response)) {\n // Assigned one by one, as Object.assign() with an object literal is measurably slower here\n response.error = error;\n response.headers = headers;\n response.isFetching = false;\n response.mutate = mutatator;\n response.isSuccess = response.ok && !error;\n response.isError = !!error;\n }\n\n return response;\n};\n","import { applyInterceptors } from './interceptor-manager';\nimport type { FetchResponse, RetryConfig, RetryFunction } from './types';\nimport { delayInvocation, timeNow } from './utils';\nimport { generateCacheKey } from './cache-manager';\nimport { FUNCTION } from './constants';\n\nfunction getMsFromHttpDate(dateString: string): number | null {\n const ms = Date.parse(dateString) - timeNow();\n\n if (!isNaN(ms)) {\n return Math.max(0, Math.floor(ms));\n }\n return null;\n}\n\n/**\n * Calculates the number of milliseconds to wait before retrying a request,\n * based on the `Retry-After` HTTP header in the provided response.\n *\n * The function supports both numeric (seconds) and HTTP-date formats for the `Retry-After` header.\n * - If the header is a number, it is interpreted as seconds and converted to milliseconds.\n * - If the header is a date, the function calculates the difference between the date and the current time.\n *\n * @param extendedResponse - The response object containing headers, or `null`.\n * @returns The number of milliseconds to wait before retrying, or `null` if the header is not present or invalid.\n */\nexport function getRetryAfterMs(\n extendedResponse: FetchResponse | null,\n): number | null {\n if (!extendedResponse) {\n return null;\n }\n\n const headers = extendedResponse.headers || {};\n const retryAfter = headers['retry-after'];\n\n if (retryAfter) {\n // Try parsing as seconds\n const seconds = Number(retryAfter);\n\n if (!isNaN(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n const ms = getMsFromHttpDate(retryAfter);\n\n if (ms !== null) {\n return ms;\n }\n }\n\n // Headers are already in lowercase\n const RATELIMIT_RESET = 'ratelimit-reset';\n\n // Unix timestamp when the rate limit window resets (relative to current time)\n // Fallback to checking 'ratelimit-reset-after' OR 'x-ratelimit-reset-after' headers\n const rateLimitResetAfter =\n headers[RATELIMIT_RESET + '-after'] ||\n headers['x-' + RATELIMIT_RESET + '-after'];\n\n if (rateLimitResetAfter) {\n const seconds = Number(rateLimitResetAfter);\n\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n }\n\n // ISO 8601 datetime when the rate limit resets\n // Fallback to checking 'ratelimit-reset-at' 'x-ratelimit-reset-at' headers\n const rateLimitResetAt =\n headers[RATELIMIT_RESET + '-at'] || headers['x-' + RATELIMIT_RESET + '-at'];\n\n if (rateLimitResetAt) {\n return getMsFromHttpDate(rateLimitResetAt);\n }\n\n return null;\n}\n\n/**\n * Executes a request function with retry logic according to the provided configuration.\n *\n * The function attempts the request up to the specified number of retries, applying delay and backoff strategies.\n * Retries can be triggered based on response status codes, custom logic, or the presence of a `Retry-After` header.\n * Optionally, an `onRetry` interceptor can be invoked before each retry attempt.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param requestFn - The function that performs the request. Receives `isStaleRevalidation` and `attempt` as arguments.\n * @param config - The retry configuration, including retry count, delay, backoff, retry conditions, and hooks.\n * @returns A promise resolving to the fetch response, or rejecting if all retries are exhausted.\n * @throws Error if the maximum number of retries is exceeded or a non-retriable error occurs.\n */\nexport async function withRetry<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation: boolean,\n attempt: number,\n ) => Promise<\n FetchResponse\n >,\n config: RetryConfig,\n): Promise> {\n const {\n retries = 0,\n delay = 0,\n backoff = 1,\n maxDelay,\n retryOn = [],\n shouldRetry,\n jitter,\n methods,\n } = config;\n\n let attempt = 0;\n let waitTime = delay;\n const maxRetries = retries > 0 ? retries : 0;\n let output: FetchResponse;\n\n while (attempt <= maxRetries) {\n // Subsequent attempts will have output defined, but the first attempt may not.\n // Let's apply onRetry interceptor and regenerate cache key if ot really changes.\n if (attempt > 0 && output!) {\n const cfg = output.config;\n const onRetry = cfg.onRetry;\n\n if (onRetry) {\n await applyInterceptors(onRetry, output, attempt);\n\n // If the key was automatically generated, we need to regenerate it as config may change.\n // We don't detect whether config changed for performance reasons.\n if (cfg._isAutoKey) {\n cfg._prevKey = cfg.cacheKey as string;\n cfg.cacheKey = generateCacheKey(cfg, false);\n }\n }\n }\n\n // Performance optimization: Call the request function with the current attempt number\n // If this is the first attempt, we pass `isStaleRevalidation` as `false`,\n // otherwise we pass `true` to indicate that this is a stale revalidation (no cache hit).\n output = await requestFn(attempt > 0, attempt);\n const error = output.error;\n\n // Stop unless a failed response should be retried according to the retry settings,\n // or a successful one according to shouldRetry\n if (\n error\n ? await getShouldStopRetrying(\n output,\n attempt,\n maxRetries,\n shouldRetry,\n retryOn,\n methods,\n )\n : !(\n shouldRetry &&\n attempt < maxRetries &&\n (await shouldRetry(output, attempt))\n )\n ) {\n break;\n }\n\n // The delay before the next retry, randomized with jitter unless the server asks for one below\n let retryDelay = withJitter(waitTime, jitter);\n\n // Handle rate limiting if the error status is 429 (Too Many Requests) or 503 (Service Unavailable)\n if (error && (error.status === 429 || error.status === 503)) {\n // Try to extract the \"Retry-After\" value from the response headers\n const retryAfterMs = getRetryAfterMs(output);\n\n // If a valid retry-after value is found, override the wait time before next retry\n // Cap it with maxDelay so that a server can't make the client wait indefinitely\n if (retryAfterMs !== null) {\n retryDelay = waitTime = Math.min(\n retryAfterMs,\n maxDelay || retryAfterMs,\n );\n }\n }\n\n await delayInvocation(retryDelay);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n }\n\n return output!;\n}\n\n/**\n * Determines whether to stop retrying based on the error, current attempt count, and retry configuration.\n *\n * This function checks:\n * - If the maximum number of retries has been reached.\n * - If the request was aborted, e.g. with its signal or by a newer request. Aborted requests are never retried.\n * - If a custom `shouldRetry` callback is provided, its result is used to decide.\n * - If no custom logic is provided, falls back to checking if the error status is included in the `retryOn` list,\n * and the request method in the `methods` list, if any.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param output - The response object containing the error and request configuration.\n * @param attempt - The current retry attempt number.\n * @param maxRetries - The maximum number of retry attempts allowed.\n * @param shouldRetry - Optional custom function to determine if a retry should occur.\n * @param retryOn - Optional list of HTTP status codes that should trigger a retry.\n * @param methods - Optional list of request methods that are retried on the `retryOn` statuses. All methods are retried without it.\n * @returns A promise resolving to `true` if retrying should stop, or `false` to continue retrying.\n */\nexport async function getShouldStopRetrying<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n output: FetchResponse,\n attempt: number,\n maxRetries: number,\n shouldRetry?: RetryFunction<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n retryOn: number[] = [],\n methods?: string[],\n): Promise {\n // Safety first: always respect max retries\n // We check retries provided regardless of the shouldRetry being provided so to avoid infinite loops.\n // It is a fail-safe so to prevent excessive retry attempts even if custom retry logic suggests a retry.\n if (attempt === maxRetries) {\n return true;\n }\n\n // Aborted requests are never retried, as e.g. a retry of one cancelled by a newer request would cancel the newer one\n if (output.error?.isCancelled) {\n return true;\n }\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n\n if (result !== null) {\n return !result;\n }\n }\n\n return !(\n (retryOn || []).includes(output.error?.status ?? 0) &&\n (!methods ||\n methods.some((method) => method.toUpperCase() === output.config.method))\n );\n}\n\n/**\n * Randomizes a retry delay with jitter, so that clients that failed at the same time, e.g. during an outage, don't retry all at once.\n *\n * @param delay - The delay computed from the `delay`, `backoff` and `maxDelay` settings, in milliseconds.\n * @param jitter - `true` for a random delay between 0 and the computed one (\"full jitter\"), or a function that returns the delay to use.\n * @returns The delay to wait before the retry, in milliseconds.\n */\nfunction withJitter(delay: number, jitter: RetryConfig['jitter']): number {\n return typeof jitter === FUNCTION\n ? (jitter as (delay: number) => number)(delay)\n : jitter\n ? Math.random() * delay\n : delay;\n}\n","import type { RequestConfig, FetchResponse } from './types';\nimport { delayInvocation, isOffline, isPageHidden } from './utils';\n\n/**\n * Executes a request function with polling, stopping when shouldStopPolling returns true,\n * pollingInterval is not set, or maxAttempts is reached.\n * Polling pauses while the page is hidden or the browser is offline, unless allowed by refreshWhenHidden or refreshWhenOffline.\n *\n * @template Output The type of the output returned by the request function.\n * @param requestFn - The function that performs a single request (with retries).\n * @param pollingInterval - Interval in ms between polling attempts.\n * @param shouldStopPolling - Function to determine if polling should stop.\n * @param maxAttempts - Maximum number of polling attempts, default: 0 (unlimited).\n * @param pollingDelay - Delay in ms before each polling attempt, default: 0.\n * @param refreshWhenHidden - Whether to keep polling while the page is hidden, default: false.\n * @param refreshWhenOffline - Whether to keep polling while the browser is offline, default: false.\n * @param signal - The signal passed to the request. Polling stops once it is aborted.\n * @returns The final output from the last request.\n */\nexport async function withPolling<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation?: boolean,\n attempt?: number,\n ) => Promise<\n FetchResponse\n >,\n pollingInterval?: RequestConfig['pollingInterval'],\n shouldStopPolling?: RequestConfig['shouldStopPolling'],\n maxAttempts = 0,\n pollingDelay = 0,\n refreshWhenHidden = false,\n refreshWhenOffline = false,\n signal?: AbortSignal,\n): Promise> {\n if (!pollingInterval) {\n return requestFn();\n }\n\n let pollingAttempt = 0;\n let output: FetchResponse;\n\n while (maxAttempts === 0 || pollingAttempt < maxAttempts) {\n if (pollingDelay > 0) {\n await delayInvocation(pollingDelay, signal);\n }\n\n output = await requestFn();\n\n pollingAttempt++;\n\n if (\n (maxAttempts > 0 && pollingAttempt >= maxAttempts) ||\n !pollingInterval ||\n (shouldStopPolling && shouldStopPolling(output, pollingAttempt))\n ) {\n break;\n }\n\n // Wait for the next attempt, and keep waiting while polling is paused\n do {\n await delayInvocation(pollingInterval, signal);\n\n // Aborting the signal of the request stops polling\n if (signal && signal.aborted) {\n return output;\n }\n } while (\n (!refreshWhenHidden && isPageHidden()) ||\n (!refreshWhenOffline && isOffline())\n );\n }\n\n return output!;\n}\n","import { ABORT_ERROR, UNDEFINED } from './constants';\nimport type { RequestConfig, UploadProgress } from './types';\nimport { createAbortError } from './utils';\n\n// Responses with these statuses can't have a body\nconst NULL_BODY_STATUSES = [204, 205, 304];\n\n// Headers that browsers don't let requests set. fetch() skips them silently, while\n// XMLHttpRequest logs errors for them, so they are skipped before sending.\nconst FORBIDDEN_HEADERS =\n /^(accept-charset|accept-encoding|connection|content-length|cookie2?|date|dnt|expect|host|keep-alive|origin|referer|set-cookie|te|trailer|transfer-encoding|upgrade|via)$|^(proxy-|sec-|access-control-request-)/;\n\n// ReadableStream is missing in some environments, e.g. React Native\nconst isStream = (body: unknown): body is ReadableStream =>\n typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream;\n\nexport const toProgress = (loaded: number, total?: number): UploadProgress => ({\n loaded,\n total,\n progress: total ? loaded / total : undefined,\n});\n\n/**\n * Sends a request and reports the upload progress of its body to `onUploadProgress`.\n * Browsers and React Native don't report the upload progress of fetch(), so XMLHttpRequest is used there.\n * Elsewhere, e.g. in Node.js, the body is streamed with fetch() and counted while it is sent.\n *\n * @param {string} url - The request URL.\n * @param {RequestConfig} config - The request configuration, with a body and `onUploadProgress`.\n * @returns {Promise} - The response.\n */\nexport function fetchWithUploadProgress(\n url: string,\n config: RequestConfig,\n): Promise {\n const body = config.body as BodyInit;\n\n return typeof XMLHttpRequest !== UNDEFINED && !isStream(body)\n ? sendWithXhr(url, config, body)\n : sendStreamed(url, config, body);\n}\n\nfunction sendWithXhr(\n url: string,\n config: RequestConfig,\n body: BodyInit,\n): Promise {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n // fetchf() always sets the signal, as it handles timeouts and cancellation with it\n const signal = config.signal!;\n const abort = () => xhr.abort();\n\n const settle = (fn: () => void) => {\n signal.removeEventListener('abort', abort);\n\n try {\n fn();\n } catch (error) {\n reject(error);\n }\n };\n\n xhr.open(config.method as string, url);\n xhr.responseType = 'blob';\n xhr.withCredentials = config.credentials === 'include';\n\n new Headers(config.headers).forEach(\n (value, name) =>\n FORBIDDEN_HEADERS.test(name) || xhr.setRequestHeader(name, value),\n );\n\n xhr.upload.onprogress = (event) =>\n config.onUploadProgress!(\n toProgress(\n event.loaded,\n event.lengthComputable ? event.total : undefined,\n ),\n );\n\n xhr.onload = () =>\n settle(() => {\n const headers = new Headers();\n\n for (const line of xhr.getAllResponseHeaders().split(/\\r?\\n/)) {\n const index = line.indexOf(':');\n\n if (index > 0) {\n headers.append(line.slice(0, index), line.slice(index + 1).trim());\n }\n }\n\n const response = new Response(\n NULL_BODY_STATUSES.includes(xhr.status) ? null : xhr.response,\n { status: xhr.status, statusText: xhr.statusText, headers },\n );\n\n // Like fetch(), the response tells its final URL, e.g. after redirects\n Object.defineProperty(response, 'url', { value: xhr.responseURL });\n\n resolve(response);\n });\n\n xhr.onerror = () =>\n settle(() => reject(new TypeError('Network request failed')));\n\n // Like fetch(), aborted requests reject with the reason of the abort signal\n const onAbort = () =>\n settle(() =>\n reject(\n signal.reason ||\n createAbortError('The request was aborted', ABORT_ERROR),\n ),\n );\n\n xhr.onabort = onAbort;\n\n if (signal.aborted) {\n return onAbort();\n }\n\n signal.addEventListener('abort', abort);\n\n xhr.send(body as XMLHttpRequestBodyInit);\n });\n}\n\nasync function sendStreamed(\n url: string,\n config: RequestConfig,\n body: BodyInit,\n): Promise {\n const headers = new Headers(config.headers);\n let stream = body as ReadableStream;\n let total: number | undefined;\n\n if (!isStream(body)) {\n // Serialize the body like fetch() would, to know its size and content type\n const blob = body instanceof Blob ? body : await new Response(body).blob();\n\n total = blob.size;\n stream = blob.stream();\n\n if (blob.type && !headers.has('content-type')) {\n headers.set('content-type', blob.type);\n }\n }\n\n let loaded = 0;\n\n return fetch(url, {\n ...config,\n headers,\n body: stream.pipeThrough(\n new TransformStream({\n transform(chunk, controller) {\n loaded += chunk.byteLength;\n config.onUploadProgress!(toProgress(loaded, total));\n controller.enqueue(chunk);\n },\n }),\n ),\n // Required by fetch() to send a stream\n duplex: 'half',\n } as RequestInit);\n}\n","import { FUNCTION } from './constants';\nimport type { DownloadProgress } from './types';\nimport { toProgress } from './upload-progress';\n\n/**\n * Reports the download progress of a response body to `onDownloadProgress` while the body is read.\n * The body is counted as it arrives, so the progress follows the download.\n *\n * @param {T} response - The response. Other than native responses with a body, e.g. responses of HEAD requests or custom fetchers, are returned as they are.\n * @param {Function} [onDownloadProgress] - The function called with the progress. Without it, the response is returned as it is.\n * @returns {T} - A copy of the response, whose body is counted while it's read.\n */\nexport function withDownloadProgress(\n response: T,\n onDownloadProgress?: (progress: DownloadProgress) => void,\n): T {\n // Response is missing in some environments, and response bodies e.g. in React Native\n if (\n !onDownloadProgress ||\n typeof Response !== FUNCTION ||\n !(response instanceof Response) ||\n !response.body\n ) {\n return response;\n }\n\n const headers = response.headers;\n // Content-Length is the size of the compressed body, so the size of a compressed one is unknown\n const total = headers.has('content-encoding')\n ? undefined\n : Number(headers.get('content-length')) || undefined;\n let loaded = 0;\n\n const counted = new Response(\n response.body.pipeThrough(\n new TransformStream({\n transform(chunk, controller) {\n loaded += chunk.byteLength;\n // Browsers may hide the Content-Encoding header of cross-origin responses, so the progress is capped at 1\n onDownloadProgress(\n toProgress(loaded, total && Math.max(total, loaded)),\n );\n controller.enqueue(chunk);\n },\n }),\n ),\n response,\n );\n\n // Like the original response, the copy tells its final URL, whether it was redirected and its type\n for (const key of ['url', 'redirected', 'type'] as const) {\n Object.defineProperty(counted, key, { value: response[key] });\n }\n\n return counted as T;\n}\n","import type { ResponseError } from './errors/response-error';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n} from './types/request-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { handleResponseCache } from './cache-manager';\nimport { ABORT_ERROR, REJECT } from './constants';\nimport {\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n HeadersObject,\n} from './types';\nimport { processHeaders } from './utils';\n\n/**\n * Handles final processing for both success and error responses\n * Applies error interceptors, caching, notifications, and error strategy\n */\nexport async function withErrorHandling<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n isStaleRevalidation: boolean,\n requestFn: (\n isStaleRevalidation: boolean,\n ) => Promise<\n FetchResponse\n >,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): Promise> {\n const output = await requestFn(isStaleRevalidation);\n const error = output.error;\n\n if (!error) {\n // SUCCESS PATH\n handleResponseCache(output, requestConfig);\n\n return output;\n }\n\n // ERROR PATH\n\n if (requestConfig.onError) {\n await applyInterceptors(requestConfig.onError, error);\n }\n\n // Timeouts and request cancellations using AbortController do not throw any errors unless rejectCancelled is true.\n // Only handle the error if the request was not cancelled, or if it was cancelled and rejectCancelled is true.\n const isCancelled = error.isCancelled;\n\n const logger = requestConfig.logger;\n\n if (!isCancelled && logger && logger.warn) {\n logger.warn('FETCH ERROR', redactError(error as ResponseError));\n }\n\n // The defaultResponse strategy returns the default response in place of the error data.\n // The original data stays available through error.response.\n if (requestConfig.strategy === 'defaultResponse') {\n output.data = (requestConfig.defaultResponse ?? null) as typeof output.data;\n }\n\n // Handle cache and notifications FIRST (before strategy)\n handleResponseCache(output, requestConfig, true);\n\n // handle error strategy as the last part\n const shouldHandleError = !isCancelled || requestConfig.rejectCancelled;\n\n if (shouldHandleError) {\n const strategy = requestConfig.strategy;\n // Reject the promise\n if (strategy === REJECT) {\n throw error;\n }\n\n // Hang the promise\n if (strategy === 'silent') {\n await new Promise(() => null);\n }\n }\n\n return output;\n}\n\n// Credential headers that must not end up in logs\nconst SENSITIVE_HEADERS = [\n 'authorization',\n 'proxy-authorization',\n 'cookie',\n 'x-api-key',\n];\n\n/**\n * Creates a copy of the error for logging, with credential headers masked and the request body removed.\n * The error itself is left untouched.\n */\nfunction redactError(error: ResponseError): ResponseError {\n // Cache keys are dropped too, as they can contain short request bodies\n const config = {\n ...error.config,\n body: undefined,\n data: undefined,\n cacheKey: undefined,\n _prevKey: undefined,\n headers: processHeaders(error.config.headers as HeadersObject),\n };\n\n for (const name of SENSITIVE_HEADERS) {\n if (config.headers[name]) {\n config.headers[name] = '[REDACTED]';\n }\n }\n\n const copy = Object.assign(new Error(error.message), error, {\n config,\n request: config,\n response: error.response && { ...error.response, config },\n });\n\n copy.name = error.name;\n copy.stack = error.stack;\n\n return copy;\n}\n\nexport function enhanceError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): void {\n error.status = error.status || (response && response.status) || 0;\n error.statusText =\n error.statusText || (response && response.statusText) || '';\n error.config = error.request = requestConfig;\n error.response = response;\n error.isCancelled = error.name === ABORT_ERROR;\n}\n","import type {\n DefaultResponse,\n RequestConfig,\n FetchResponse,\n HeadersObject,\n} from './types/request-handler';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n} from './types/api-handler';\nimport type { StoredResponse } from './types/cache-manager';\nimport { applyInterceptors } from './interceptor-manager';\nimport { ResponseError } from './errors/response-error';\nimport { isObject, noop, processHeaders } from './utils';\nimport {\n markInFlight,\n setInFlightPromise,\n getInFlightPromise,\n} from './inflight-manager';\nimport { parseResponseData, prepareResponse } from './response-parser';\nimport {\n generateCacheKey,\n getCacheData,\n getCachedResponse,\n getStoredCache,\n isCacheBypassed,\n restoreCache,\n setCache,\n} from './cache-manager';\nimport { withRetry } from './retry-handler';\nimport { withPolling } from './polling-handler';\nimport { fetchWithUploadProgress } from './upload-progress';\nimport { withDownloadProgress } from './download-progress';\nimport { notifySubscribers } from './pubsub-manager';\nimport { addRevalidator } from './revalidator-manager';\nimport { enhanceError, withErrorHandling } from './error-handler';\nimport { FUNCTION, GET, HEAD } from './constants';\nimport { buildConfig } from './config-handler';\n\nconst inFlightResponse = Object.freeze({\n isFetching: true,\n});\n\n/**\n * Sends an HTTP request to the specified URL using the provided configuration and returns a typed response.\n *\n * @typeParam ResponseData - The expected shape of the response data. Defaults to `DefaultResponse`.\n * @typeParam RequestBody - The type of the request payload/body. Defaults to `DefaultPayload`.\n * @typeParam QueryParams - The type of the query parameters. Defaults to `DefaultParams`.\n * @typeParam PathParams - The type of the path parameters. Defaults to `DefaultUrlParams`.\n *\n * @param url - The endpoint URL to which the request will be sent.\n * @param config - Optional configuration object for the request, including headers, method, body, query, and path parameters.\n *\n * @returns A promise that resolves to a `FetchResponse` containing the typed response data and request metadata.\n *\n * @example\n * ```typescript\n * const { data } = await fetchf('/api/user', { method: 'GET' });\n * console.log(data);\n * ```\n */\nexport async function fetchf<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n): Promise> {\n // Ultra-fast early cache check if cacheKey is provided as a string\n // For workloads dominated by repeated requests, this string caching optimization\n // can potentially support millions of requests per second with minimal CPU overhead\n if (reqConfig && typeof reqConfig.cacheKey === 'string') {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(reqConfig.cacheKey, reqConfig.cacheTime, reqConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n const fetcherConfig = buildConfig<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(url, reqConfig);\n\n const {\n timeout,\n cancellable,\n cacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n refetchOnFocus,\n refetchOnReconnect,\n pollingInterval = 0,\n } = fetcherConfig;\n const isCacheEnabled = cacheTime !== undefined || staleTime !== undefined;\n const method = fetcherConfig.method;\n\n // Cached responses of GET and HEAD requests are revalidated with their ETag.\n // Custom fetchers may not handle 304 responses, so they only send it when it's enabled for them.\n const isETagEnabled =\n isCacheEnabled &&\n (method === GET || method === HEAD) &&\n (fetcherConfig.etag ?? !fetcherConfig.fetcher);\n\n const needsCacheKey = !!(\n cacheKey ||\n timeout ||\n dedupeTime ||\n isCacheEnabled ||\n cancellable ||\n refetchOnFocus ||\n refetchOnReconnect\n );\n\n let _cacheKey: string | null = null;\n\n // Generate cache key if required\n if (needsCacheKey) {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n // The initial data, which is used as the first response instead of sending the request\n let initialResponse: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n // Cache handling logic\n if (_cacheKey && isCacheEnabled) {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(_cacheKey, cacheTime, fetcherConfig);\n\n if (cached) {\n return cached;\n }\n\n // Restore the response from the cache store, e.g. one saved during a previous page load\n if (fetcherConfig.cacheStore) {\n const stored = await getStoredCache(_cacheKey, fetcherConfig);\n const restored =\n stored &&\n toResponse(\n stored.data,\n _cacheKey,\n fetcherConfig,\n );\n\n // A stale response is shown until the request below revalidates it\n if (\n restored &&\n restoreCache(\n _cacheKey,\n { ...stored, data: restored },\n fetcherConfig.cacheStore,\n )\n ) {\n return restored;\n }\n }\n\n // While there's no cached response, the initial data, e.g. data rendered on the server, is cached as the response\n if (\n fetcherConfig.initialData !== undefined &&\n !getCacheData(_cacheKey) &&\n !isCacheBypassed(fetcherConfig)\n ) {\n initialResponse = toResponse(\n {\n data: fetcherConfig.initialData,\n status: 200,\n statusText: '',\n headers: {},\n },\n _cacheKey,\n fetcherConfig,\n );\n }\n }\n\n // Deduplication logic\n if (_cacheKey && dedupeTime) {\n const inflight = getInFlightPromise<\n FetchResponse\n >(_cacheKey, dedupeTime);\n\n if (inflight) {\n return inflight;\n }\n }\n\n const retryConfig = fetcherConfig.retry || {};\n const { retries = 0, resetTimeout } = retryConfig;\n\n // The signal passed to the request. Each attempt replaces it in the config with a signal of its own.\n const userSignal = fetcherConfig.signal;\n\n // The actual request logic as a function (one poll attempt, with retries)\n const doRequestOnce = async (isStaleRevalidation: boolean, attempt = 0) => {\n // The cached response to revalidate. It's read before the cache is marked as fetching below.\n const cached =\n isETagEnabled &&\n getCacheData(\n _cacheKey,\n );\n\n // If cache key is specified, we will handle optimistic updates\n // and mark the request as in-flight, so to catch \"fetching\" state.\n // This is useful for Optimistic UI updates (e.g., showing loading spinners).\n if (!attempt) {\n // The initial data is only used once, as the first response\n if (initialResponse) {\n const response = initialResponse;\n\n initialResponse = null;\n\n return response;\n }\n\n if (_cacheKey && !isStaleRevalidation) {\n if (staleTime) {\n const existingCache = getCachedResponse(\n _cacheKey,\n cacheTime,\n fetcherConfig,\n );\n\n // Don't notify subscribers when cache exists\n // Let them continue showing stale data during background revalidation\n if (!existingCache) {\n setCache(_cacheKey, inFlightResponse, cacheTime, staleTime);\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n } else {\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n }\n\n // Attach cache key so that it can be reused in interceptors or in the final response\n fetcherConfig.cacheKey = _cacheKey;\n }\n\n const url = fetcherConfig.url as string;\n\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = markInFlight(\n _cacheKey,\n url,\n timeout,\n dedupeTime || 0,\n !!cancellable,\n // Enable timeout either by default or when retries & resetTimeout are enabled\n !!(timeout && (!attempt || resetTimeout)),\n );\n\n // Do not create a shallow copy to maintain idempotency here.\n // This ensures the original object is mutated by interceptors whenever needed, including retry logic.\n const requestConfig = fetcherConfig;\n\n requestConfig.signal = controller.signal;\n\n // The request is aborted along with the signal passed to it, which may have been aborted already\n const abort = () => controller.abort(userSignal!.reason);\n\n if (userSignal) {\n if (userSignal.aborted) {\n abort();\n } else {\n userSignal.addEventListener('abort', abort);\n }\n }\n\n let output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n let response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n try {\n if (fetcherConfig.onRequest) {\n // Zero-allocation yield to microtask queue so the outer fetchf() can call setInFlightPromise()\n // before onRequest interceptors run. This ensures that if onRequest triggers\n // another fetchf() with the same cacheKey, getInFlightPromise() finds item[4].\n // On retries (attempt > 0), setInFlightPromise() was already called during the first attempt.\n // The promise stored in item[4] is the outer doRequestPromise which covers all retries.\n // So the race only matters on the very first attempt when the outer scope hasn't had a chance to call setInFlightPromise() yet.\n if (_cacheKey && dedupeTime && !attempt) {\n await null;\n }\n\n await applyInterceptors(fetcherConfig.onRequest, requestConfig);\n }\n\n // Custom fetcher\n const fn = fetcherConfig.fetcher;\n const init = withETag(requestConfig, cached);\n\n response = (fn\n ? await fn(\n url,\n init,\n )\n : // Uploads with onUploadProgress are sent in a way that reports their progress\n await (requestConfig.onUploadProgress && requestConfig.body\n ? fetchWithUploadProgress(url, requestConfig)\n : fetch(url, init as RequestInit))) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Reports the download progress while the body is read\n response = withDownloadProgress(\n response,\n requestConfig.onDownloadProgress,\n );\n\n // Custom fetcher may return a raw data object instead of a Response instance\n if (isObject(response)) {\n // The server answered that the cached response is still valid, so it's reused instead of being sent again.\n // Like other cached responses, it has been parsed and transformed already.\n if (init !== requestConfig && response.status === 304) {\n return cached as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n // Case 1: Native Response instance\n if (typeof Response === FUNCTION && response instanceof Response) {\n response.data = requestConfig.parser\n ? await requestConfig.parser(response)\n : await parseResponseData(response, requestConfig.responseType);\n } else if (fn) {\n // Case 2: Custom fetcher that returns a response object\n if (!('data' in response && 'body' in response)) {\n // Case 3: Raw data, wrap it\n response = { data: response } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n }\n\n // Attach config and data to the response\n // This is useful for custom fetchers that do not return a Response instance\n // and for interceptors that may need to access the request config\n response.config = requestConfig;\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n // This is the pattern for fetch responses as per spec, but custom fetchers may not follow it so we check for `ok` property\n if (response.ok !== undefined && !response.ok) {\n throw new ResponseError(\n requestConfig.method +\n ' to ' +\n url +\n ' failed! Status: ' +\n (response.status || null),\n requestConfig,\n response,\n );\n }\n }\n\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig);\n\n const onResponse = fetcherConfig.onResponse;\n\n if (onResponse) {\n await applyInterceptors(onResponse, output);\n }\n } catch (_error) {\n const error = _error as ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Append additional information to Network, CORS or any other fetch() errors\n enhanceError(\n error,\n response,\n requestConfig,\n );\n\n // Prepare Extended Response\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig, error);\n } finally {\n if (userSignal) {\n userSignal.removeEventListener('abort', abort);\n }\n }\n\n return output;\n };\n\n // Inline and minimize function wrappers for performance\n // When retries are enabled, forward isStaleRevalidation so the first attempt\n // of a background SWR revalidation doesn't incorrectly mark the request as in-flight\n const baseRequest =\n retries > 0\n ? (isStaleRevalidation: boolean) =>\n withRetry(\n (_, attempt) => doRequestOnce(isStaleRevalidation, attempt),\n retryConfig,\n )\n : doRequestOnce;\n\n const { onLoadingSlow, loadingTimeout } = fetcherConfig;\n\n // Calls onLoadingSlow once a request, including its retries, is still pending after loadingTimeout.\n // Background revalidations don't show a loading state, so they are never considered slow.\n const request =\n onLoadingSlow && loadingTimeout\n ? async (isStaleRevalidation: boolean) => {\n if (isStaleRevalidation) {\n return baseRequest(isStaleRevalidation);\n }\n\n const timer = setTimeout(\n () => applyInterceptors(onLoadingSlow, fetcherConfig).catch(noop),\n loadingTimeout,\n );\n\n try {\n return await baseRequest(isStaleRevalidation);\n } finally {\n clearTimeout(timer);\n }\n }\n : baseRequest;\n\n const requestWithErrorHandling = (isStaleRevalidation = false) =>\n withErrorHandling(\n isStaleRevalidation,\n request,\n fetcherConfig,\n );\n\n // Avoid unnecessary function wrapping if polling is not enabled\n const doRequestPromise = pollingInterval\n ? withPolling(\n requestWithErrorHandling,\n pollingInterval,\n fetcherConfig.shouldStopPolling,\n fetcherConfig.maxPollingAttempts,\n fetcherConfig.pollingDelay,\n fetcherConfig.refreshWhenHidden,\n fetcherConfig.refreshWhenOffline,\n userSignal,\n )\n : requestWithErrorHandling();\n\n // If deduplication is enabled, store the in-flight promise immediately\n if (_cacheKey) {\n if (dedupeTime) {\n setInFlightPromise(_cacheKey, doRequestPromise);\n }\n\n // Only register revalidator when revalidation features are actually requested\n if (staleTime || refetchOnFocus || refetchOnReconnect) {\n addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\n fetcherConfig.focusThrottleInterval,\n );\n }\n }\n\n return doRequestPromise;\n}\n\n/**\n * Recreates a response from its copy in a cache store.\n * The data was transformed before it was stored, so it isn't transformed again.\n *\n * @param stored - The stored copy of the response.\n * @param cacheKey - The cache key of the request.\n * @param config - The request configuration.\n * @returns The response, or null if the stored copy is invalid, e.g. has an unknown status.\n */\nfunction toResponse(\n stored: StoredResponse,\n cacheKey: string,\n config: RequestConfig,\n): FetchResponse | null {\n try {\n // Without the Fetch API (e.g. with a custom fetcher in tests), a plain response object is used\n const response = (typeof Response === FUNCTION\n ? new Response(null, stored)\n : {\n ok: true,\n status: stored.status,\n statusText: stored.statusText,\n headers: stored.headers,\n }) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n response.data = stored.data as typeof response.data;\n config.cacheKey = cacheKey;\n\n const output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, {\n ...config,\n select: undefined,\n flattenResponse: false,\n defaultResponse: undefined,\n });\n\n output.config = config;\n\n return output;\n } catch {\n return null;\n }\n}\n\n/**\n * Asks the server whether a cached response is still valid, by sending its ETag in the If-None-Match header.\n * Then the server can answer 304 Not Modified instead of sending the response again.\n * Requests with an If-None-Match header of their own are sent as they are.\n *\n * @param config - The request configuration.\n * @param cached - The cached response of the request, if any.\n * @returns A copy of the configuration with the If-None-Match header, or the configuration itself if the cached response has no ETag.\n */\nfunction withETag(\n config: RequestConfig,\n cached: FetchResponse | null | false,\n): RequestConfig {\n const etag = cached && !cached.error && cached.headers && cached.headers.etag;\n const headers = etag && processHeaders(config.headers as HeadersObject);\n\n return headers && !headers['if-none-match']\n ? { ...config, headers: { ...headers, 'if-none-match': etag } }\n : config;\n}\n","import type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n RequestConfigUrlRequired,\n} from './types/api-handler';\nimport { fetchf } from '.';\nimport { mergeConfigs } from './config-handler';\nimport { hasOwn } from './utils';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if passed as \"fetcher\".\n * @see https://github.com/MattCCC/fetchff#configuration\n *\n * @param {Object} config - Configuration object for the API fetcher (see link above for full options).\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {string} [config.baseURL] - The base URL for the API.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\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 EndpointTypes extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n async function handleNonImplemented(endpointName: string): Promise {\n console.error('Add ' + endpointName + \" to 'endpoints'.\");\n\n return null;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\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 endpointName - The name of the API endpoint to call.\n * @param requestConfig - Additional configuration for the request.\n * @returns A promise that resolves with the response from the API provider.\n */\n async request(endpointName, requestConfig = {}) {\n // Use global and per-endpoint settings\n // Only own properties are endpoints, not ones inherited like \"constructor\"\n const endpointConfig = hasOwn(endpoints, endpointName as string)\n ? endpoints[endpointName]\n : undefined;\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // URL parsers ignore leading control characters and spaces, drop tabs and newlines,\n // and treat backslashes like slashes, so check the URL the way it will be resolved\n const resolvedUrl = url\n .replace(/[\\t\\n\\r]/g, '')\n // eslint-disable-next-line no-control-regex -- matching control characters is the point\n .replace(/^[\\x00-\\x20]+/, '');\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (/^[/\\\\]{2}/.test(resolvedUrl)) {\n throw new Error('Protocol-relative URLs not allowed.');\n }\n\n // Prevent potential Server-Side Request Forgery attack and leakage of credentials when same instance is used for external requests\n // Any scheme counts here, as e.g. \"http:\\\\host\" or \"http:host\" can also point to another host\n const mergedConfig = /^[a-z][a-z\\d+\\-.]*:/i.test(resolvedUrl)\n ? // Merge endpoints configs for absolute URLs only if urls match\n endpointConfig && endpointConfig.url === url\n ? mergeConfigs(_endpointConfig, requestConfig)\n : requestConfig\n : mergeConfigs(mergeConfigs(config, _endpointConfig), requestConfig);\n\n // We prevent potential Server-Side Request Forgery attack and leakage of credentials as the same instance is not used for external requests\n // Retrigger fetch to ensure completely new instance of handler being triggered for external URLs\n return fetchf(url, mergedConfig);\n },\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 | symbol) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Symbols (e.g. inspection hooks) are never endpoints, and returning a function\n // for \"then\" would make the instance a thenable that never settles when awaited\n if (typeof prop === 'symbol' || prop === 'then') {\n return undefined;\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (hasOwn(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"]} \ No newline at end of file diff --git a/dist/node/index.js b/dist/node/index.js index 347e62c..347fd11 100644 --- a/dist/node/index.js +++ b/dist/node/index.js @@ -1,3 +1,3 @@ -'use strict';var _="application/",W=_+"json",_e="charset=utf-8",q="Content-Type",E="undefined",X="object",T="string",b="function",oe="AbortError",Ne="TimeoutError",N="GET",He="HEAD",ie="reject",ue=2147483647;var Ue=10,A=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);function H(e){return e instanceof URLSearchParams}function y(e){return e!==null&&typeof e===X}function w(e){let t=A(e,"__proto__"),r=A(e,"constructor"),a=A(e,"prototype");if(!t&&!r&&!a)return e;let s={};for(let n of Object.keys(e))n!=="__proto__"&&n!=="constructor"&&n!=="prototype"&&(s[n]=e[n]);return s}function Le(e){let t=Object.create(null);return Object.keys(e).sort().forEach(r=>t[r]=e[r]),t}function Me(e,t){return t?e+(e.includes("?")?"&":"?")+t:e}function je(e,t){if(!t)return e;if(H(t)){let c=t.toString();return Me(e,c)}let r=[],a=encodeURIComponent,s=(c,u)=>{u=typeof u===b?u():u,u=u===null||u===void 0?"":u,r[r.length]=a(c)+"="+a(u);},n=(c,u,m=0)=>{if(m>=Ue)return r;let l,p,h;if(c)if(Array.isArray(u))for(l=0,p=u.length;l{if(A(r,s)){let n=r[s];if(n!=null){let o=encodeURIComponent(String(n));if(o==="."||o==="..")throw new Error('Path params "." and ".." not allowed.');return o}}return a})}function ke(e){return /^[a-z][a-z\d+\-.]*:\/\//i.test(e)}var R=()=>Date.now(),M=()=>{};function Z(e){let t=typeof e;return e==null?false:t===T||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==E&&typeof globalThis.Buffer!==E&&globalThis.Buffer.isBuffer(e)||e instanceof Date||H(e)?false:!!(y(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===b))}var U=e=>new Promise(t=>setTimeout(t,Math.min(e,ue),true));function De(e,t=0){return t>=Ue?e:e&&y(e)&&typeof e.data!==E?De(e.data,t+1):e}function x(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else for(let r in e)A(e,r)&&r!=="__proto__"&&(t[r.toLowerCase()]=e[r]);return t}function ze(){return typeof window!==E&&typeof window.addEventListener===b}function le(e,t){if(typeof DOMException!==E)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==E&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function B(e,t,...r){if(!e)return;let a=s=>s&&y(t)&&y(s)&&Object.assign(t,w(s));if(typeof e===b)a(await e(t,...r));else if(Array.isArray(e))for(let s of e)a(await s(t,...r));}var ce=class extends Error{constructor(r,a,s){super(r);this.request=a;this.response=s;this.name="FetchError",this.status=s?s.status:0,this.statusText=s?s.statusText:"",this.config=a,this.isCancelled=false;}request;response;status;statusText;config;isCancelled};var fe=class extends ce{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var de=600,me=1e3,Te=Array(de).fill(0).map(()=>[]),O=new Map,pe=0,be=0,C=null,Je=([e,t])=>{O.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(M);}catch{}},F=(e,t,r)=>{L(e);let a=r/me+(C&&R()!==be?1:0);if(r=de||r%me!==0){O.set(e,[setTimeout(Je.bind(null,[e,t]),Math.min(r,ue))]);return}let s=(pe+a)%de;Te[s].push([e,t]),O.set(e,s),C||(be=R(),C=setInterval(()=>{pe=(pe+1)%de,be=R();let n=Te[pe];for(let o=0;o{let t=O.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t];for(let a=0;a{Ge(e,le(t+" aborted due to timeout",Ne));},r),u}async function Ge(e,t=null){if(e){let r=j.get(e);r&&(t&&r[0].abort(t),ye(e));}}function ye(e){L(e),j.delete(e);}function We(e,t){let r=j.get(e);r&&(r[4]=t);}function xe(e,t){if(!e)return null;let r=j.get(e);return r&&r[4]&&!r[3]&&R()-r[2]{if(!s[r])return;s[1]=a;let n=t?s[4]:s[0];n&&Promise.resolve(n(t)).catch(M);});}async function Re(e,t=false){if(!e)return null;let r=z.get(e);if(r){r[1]=R();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function Pt(e){$e(e);let t=e==="focus"?5:6;z.forEach((r,a)=>{r[t]&&ht(a);});}function we(e){if(k.has(e))return;let t=Ve.bind(null,e,true),r=Ze.get(e);if(r){let a=r(t);k.set(e,a);return}ze()&&(window.addEventListener(e,t),k.set(e,()=>window.removeEventListener(e,t)));}function $e(e){let t=k.get(e);t&&(t(),k.delete(e));}function et(e,t,r,a,s,n,o){let i=z.get(e);i?(i[0]=t,i[1]=R(),i[2]=Xe,i[3]=a,i[4]=s,i[5]=n,i[6]=o):z.set(e,[t,R(),Xe,a,s,n,o]),n&&we("focus"),o&&we("online"),a&&F("s:"+e,Re.bind(null,e,true),a*1e3);}function ht(e){z.delete(e),L("s:"+e);}var V=new Map;function gt(e,t){let r=V.get(e);r||V.set(e,r=new Set),r.add(t);}function Dt(e,t){let r=V.get(e);r&&(r.delete(t),r.size===0&&V.delete(e));}function J(e,t){let r=V.get(e);if(r)if(r.size===1){let a=r.values().next().value;a(t);}else r.forEach(a=>a(t));}function Et(e,t){return e?(gt(e,t),()=>{Dt(e,t);}):M}var Ce=(Ee()?60:30)*1e3,v={strategy:ie,timeout:Ce,headers:{Accept:W+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:Ce/30,maxDelay:Ce,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function bt(e){let t=w(e);return Y({retry:v.retry,headers:v.headers},t,v)}function Tt(){return {...v}}function Ie(e,t){let r=Y(v,t?w(t):{});return xt(e,r)}function xt(e,t){let r=t.method;r=r?r.toUpperCase():N;let a;r!==N&&r!==He&&(a=t.body??t.data,a&&typeof a!==T&&Z(a)&&(a=JSON.stringify(a))),wt(t.headers,a);let s=t.withCredentials?"include":t.credentials,n=Ke(e,t.urlPathParams),o=je(n,t.params),c=ke(e)?"":t.baseURL||t.apiUrl||"",u=c&&o&&!c.endsWith("/")&&!/^[/?#]/.test(o)?"/":"";return t.url=c+u+o,t.method=r,t.credentials=s,t.body=a,t}function wt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==E&&t instanceof Blob||typeof File!==E&&t instanceof File||typeof ReadableStream!==E&&t instanceof ReadableStream)return;let r;if(H(t))r=_+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=_+"octet-stream";else if(Z(t))r=W+";"+_e;else return;e instanceof Headers?e.has(q)||e.set(q,r):y(e)&&!Array.isArray(e)&&!x(e)[q.toLowerCase()]&&(e[q]=r);}function Y(e,t,r={}){return Object.assign(r,e,t),tt("retry",e,t,r),tt("headers",e,t,r),Ae("onRequest",e,t,r),Ae("onResponse",e,t,r),Ae("onError",e,t,r),r}function Ae(e,t,r,a){let s=t[e],n=r[e];if(!s&&!n)return;if(!s){a[e]=n;return}if(!n){a[e]=s;return}let o=Array.isArray(s)?s:[s],i=Array.isArray(n)?n:[n];a[e]=e==="onResponse"?i.concat(o):o.concat(i);}function tt(e,t,r,a){let s=t[e],n=r[e];if(n)if(e==="headers"){let o=s instanceof Headers||n instanceof Headers,i=o?x(s):{...s},c=o?x(n):w(n);for(let u of Object.keys(c)){let m=u.toLowerCase();for(let l in i)l.toLowerCase()===m&&delete i[l];i[u]=c[u];}a[e]=i;}else a[e]={...s,...w(n)};else n===void 0&&y(s)&&!(s instanceof Headers)&&(a[e]={...s});}var Pe=new Map,I="|",qe=64,Ct=/[^\w\-_|/:@.?=&~%#]/g,At=/[^\w\-_|/:@.?=&~%#]/,It=new Set(["accept","accept-language","accept-encoding","authorization","content-type","referer","origin","user-agent","cookie","x-api-key","x-requested-with","x-client-id","x-tenant-id","x-user-id","x-app-version","x-feature-flag","x-device-id","x-platform","x-session-id","x-locale"]);function ee(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===T?r:r(e);let{url:a="",method:s=N,headers:n=null,body:o=null,credentials:i="same-origin"}=e,c="";if(n){let l;n instanceof Headers?l=x(n):l=n;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{u+=p+"="+(typeof l===T?l:"F"+at(l))+"&";}),u.length>qe&&(u=K(u));else if(y(o)&&!Z(o))u="B"+at(o);else {let l=y(o)?JSON.stringify(Le(o)):String(o);u=l.length>qe?K(l):l;}let m=s+I+a+I+i+I+c+I+u;return st(m)}var rt=new WeakMap,qt=0;function at(e){let t=rt.get(e);return t||rt.set(e,t=++qt),t}function st(e){return At.test(e)?e.replace(Ct,"")+I+K(e):e}function nt(e){return e.expiry?R()>e.expiry:false}function te(e){return Pe.get(e)}function he(e,t,r,a){if(r===0){$(e);return}let s=R(),n=r?r*1e3:0,o=a?a*1e3:0;Pe.set(e,{data:t,time:s,stale:o>0?s+o:void 0,expiry:r===-1?void 0:s+n}),n>0&&F("c:"+e,()=>{$(e,true);},n);}function $(e,t=false){if(t){let r=te(e);if(!r||!nt(r))return}Pe.delete(e);}async function Be(e,t,r){if(!e)return null;let a=te(e);if(!a)return null;let s=y(t)?w(t):t,n={...a.data,data:s},o={...a,data:n};return Pe.set(e,o),J(e,n),r&&r.refetch?await Re(e):null}function re(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||v.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let s=te(e);if(!s)return null;if(nt(s))return $(e),null;let o=s.data;return o&&o.isFetching?null:o}function Oe(e,t,r=false){let a=t.cacheKey;if(a){let s=t.cacheTime,n=t.skipCache;if(s&&(!r||t.cacheErrors)&&!(n&&n(e,t)))he(a,e,s,t.staleTime);else {let i=te(a);i&&i.data&&i.data.isFetching&&$(a);}J(a,e),ye(a);let o=t._prevKey;o&&ye(o);}}async function ot(e){if(!e)return null;let t=e.headers?.get(q);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(W)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(_+"x-www-form-urlencoded"))&&typeof e.formData===b)a=await e.formData();else if(/^(image|video|audio)\/|octet-stream|pdf|zip/.test(r))a=await e.arrayBuffer();else if(a=await e.text(),typeof a===T){let s=a.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{a=JSON.parse(s);}catch{}}}catch{a=null;}return a}var Fe=(e,t,r=null)=>{let a=t.defaultResponse,s=t.cacheKey,n=Be.bind(null,s);if(!e)return {ok:false,error:r,data:a??null,headers:null,config:t,mutate:n,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===b&&e instanceof Response,i=e.data;a!==void 0&&(i==null||typeof i===X&&Object.keys(i).length===0)&&(e.data=i=a),t.flattenResponse&&(e.data=i=De(i)),t.select&&(e.data=i=t.select(i));let c=x(e.headers);if(o){let u={body:e.body,bodyUsed:e.bodyUsed,ok:e.ok,redirected:e.redirected,type:e.type,url:e.url,status:e.status,statusText:e.statusText,blob:()=>Promise.resolve(i instanceof ArrayBuffer?new Blob([i]):new Blob),json:()=>Promise.resolve(i),text:()=>Promise.resolve(i),clone:()=>({...u}),arrayBuffer:()=>Promise.resolve(i instanceof ArrayBuffer?i:new ArrayBuffer(0)),formData:()=>Promise.resolve(i instanceof FormData?i:new FormData),bytes:()=>Promise.resolve(new Uint8Array(i instanceof ArrayBuffer?i:new ArrayBuffer(0))),error:r,data:i,headers:c,config:t,mutate:n,isFetching:false,isSuccess:e.ok&&!r,isError:!!r};return u}return y(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=n,e.isSuccess=e.ok&&!r,e.isError=!!r),e};function it(e){let t=Date.parse(e)-R();return isNaN(t)?null:Math.max(0,Math.floor(t))}function Bt(e){if(!e)return null;let t=e.headers||{},r=t["retry-after"];if(r){let o=Number(r);if(!isNaN(o)&&o>=0)return o*1e3;let i=it(r);if(i!==null)return i}let a="ratelimit-reset",s=t[a+"-after"]||t["x-"+a+"-after"];if(s){let o=Number(s);if(!isNaN(o))return o*1e3}let n=t[a+"-at"]||t["x-"+a+"-at"];return n?it(n):null}async function ut(e,t){let{retries:r=0,delay:a=0,backoff:s=1,maxDelay:n,retryOn:o=[],shouldRetry:i}=t,c=0,u=a,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await B(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=ee(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(i&&c0&&await U(s),o=await e(),n++,!(a>0&&n>=a||!t||r&&r(o,n)));)await U(t);return o}async function ct(e,t,r){let a=await t(e),s=a.error;if(!s)return Oe(a,r),a;r.onError&&await B(r.onError,s);let n=s.isCancelled;if(!n&&r.logger?.warn&&r.logger.warn("FETCH ERROR",vt(s)),r.strategy==="defaultResponse"&&(a.data=r.defaultResponse??null),Oe(a,r,true),!n||r.rejectCancelled){let i=r.strategy;if(i===ie)return Promise.reject(s);i==="silent"&&await new Promise(()=>null);}return a}var Ft=["authorization","proxy-authorization","cookie","x-api-key"];function vt(e){let t={...e.config,body:void 0,data:void 0,cacheKey:void 0,_prevKey:void 0,headers:x(e.config.headers)};for(let a of Ft)t.headers[a]&&(t.headers[a]="[REDACTED]");let r=Object.assign(new Error(e.message),e,{config:t,request:t,response:e.response&&{...e.response,config:t}});return r.name=e.name,r.stack=e.stack,r}function ft(e,t,r){e.status=e.status||t?.status||0,e.statusText=e.statusText||t?.statusText||"",e.config=e.request=r,e.response=t,e.isCancelled=e.name===oe;}var ve=Object.freeze({isFetching:true});async function ge(e,t=null){if(t&&typeof t.cacheKey=="string"){let P=re(t.cacheKey,t.cacheTime,t);if(P)return P}let r=Ie(e,t),{timeout:a,cancellable:s,cacheKey:n,dedupeTime:o,cacheTime:i,staleTime:c,refetchOnFocus:u,refetchOnReconnect:m,pollingInterval:l=0}=r,p=i!==void 0||c!==void 0,h=!!(n||a||o||p||s||u||m),f=null;if(h&&(f=ee(r)),f&&p){let P=re(f,i,r);if(P)return P}if(f&&o){let P=xe(f,o);if(P)return P}let D=r.retry||{},{retries:mt=0,resetTimeout:pt}=D,Se=async(P,se=0)=>{se||(f&&!P&&(c?re(f,i,r)||(he(f,ve,i,c),J(f,ve)):J(f,ve)),r.cacheKey=f);let S=r.url,yt=Ye(f,S,a,o||0,!!s,!!(a&&(!se||pt))),g=r;g.signal=yt.signal;let ne,d=null;try{r.onRequest&&(f&&o&&!se&&await null,await B(r.onRequest,g));let Q=r.fetcher;if(d=Q?await Q(S,g):await fetch(S,g),y(d)&&(typeof Response===b&&d instanceof Response?d.data=g.parser?await g.parser(d):await ot(d):Q&&("data"in d&&"body"in d||(d={data:d})),d.config=g,d.ok!==void 0&&!d.ok))throw new fe(g.method+" to "+S+" failed! Status: "+(d.status||null),g,d);ne=Fe(d,g);let G=r.onResponse;G&&await B(G,ne);}catch(Q){let G=Q;ft(G,d,g),ne=Fe(d,g,G);}return ne},dt=mt>0?P=>ut((se,S)=>Se(P,S),D):Se,ae=(P=false)=>ct(P,dt,r),Qe=l?lt(ae,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):ae();return f&&(o&&We(f,Qe),(c||u||m)&&et(f,ae,void 0,c,ae,!!u,!!m)),Qe}function St(e){let t=e.endpoints;function r(s){return console.error("Add "+s+" to 'endpoints'."),Promise.resolve(null)}let a={config:e,endpoints:t,async request(s,n={}){let o=A(t,s)?t[s]:void 0,i=o||{url:String(s)},c=i.url,u=c.replace(/[\t\n\r]/g,"").replace(/^[\x00-\x20]+/,"");if(/^[/\\]{2}/.test(u))throw new Error("Protocol-relative URLs not allowed.");let m=/^[a-z][a-z\d+\-.]*:/i.test(u)?o?.url===c?Y(i,n):n:Y(Y(e,i),n);return ge(c,m)}};return new Proxy(a,{get(s,n){if(n in a)return a[n];if(!(typeof n=="symbol"||n==="then"))return A(t,n)?a.request.bind(null,n):r.bind(null,n)}})} -exports.abortRequest=Ge;exports.addTimeout=F;exports.buildConfig=Ie;exports.createAbortError=le;exports.createApiFetcher=St;exports.deleteCache=$;exports.fetchf=ge;exports.fetchff=ge;exports.generateCacheKey=ee;exports.getCache=te;exports.getCachedResponse=re;exports.getDefaultConfig=Tt;exports.getInFlightPromise=xe;exports.isSlowConnection=Ee;exports.mutate=Be;exports.removeRevalidators=Pt;exports.revalidate=Re;exports.revalidateAll=Ve;exports.setCache=he;exports.setDefaultConfig=bt;exports.setEventProvider=Rt;exports.subscribe=Et;//# sourceMappingURL=index.js.map +'use strict';var z="application/",te=z+"json",$e="charset=utf-8",_="Content-Type",D="undefined",Ie="object",x="string",b="function",k="AbortError",et="TimeoutError",O="GET",re="HEAD",pe="reject",Re=2147483647;var rt=10,S=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);function J(e){return e instanceof URLSearchParams}function g(e){return e!==null&&typeof e===Ie}function B(e){let t=S(e,"__proto__"),r=S(e,"constructor"),s=S(e,"prototype");if(!t&&!r&&!s)return e;let n={};for(let a of Object.keys(e))a!=="__proto__"&&a!=="constructor"&&a!=="prototype"&&(n[a]=e[a]);return n}function st(e){let t=Object.create(null);return Object.keys(e).sort().forEach(r=>t[r]=e[r]),t}function tt(e,t){return t?e+(e.includes("?")?"&":"?")+t:e}function at(e,t){if(!t)return e;if(J(t)){let u=t.toString();return tt(e,u)}let r=[],s=encodeURIComponent,n=(u,c)=>{c=typeof c===b?c():c,c=c??"",r[r.length]=s(u)+"="+s(c);},a=(u,c,f=0)=>{if(f>=rt)return r;let l,p,m;if(u)if(Array.isArray(c))for(l=0,p=c.length;l{let o=n||a;if(S(r,o)){let i=r[o];if(i!=null){let u=encodeURIComponent(String(i));if(u==="."||u==="..")throw new Error('Path params "." and ".." not allowed.');return u}}return s})}function ot(e){return /^[a-z][a-z\d+\-.]*:\/\//i.test(e)}var h=()=>Date.now(),C=()=>{};function se(e){let t=typeof e;return e==null?false:t===x||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==D&&typeof globalThis.Buffer!==D&&globalThis.Buffer.isBuffer(e)||e instanceof Date||J(e)?false:!!(g(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===b))}var ae=(e,t)=>new Promise(r=>{let s=()=>{clearTimeout(n),t&&t.removeEventListener("abort",s),r(true);},n=setTimeout(s,Math.min(e,Re));t&&(t.aborted?s():t.addEventListener("abort",s));});function ve(e,t=0){return t>=rt?e:e&&g(e)&&typeof e.data!==D?ve(e.data,t+1):e}function E(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,s)=>{t[s.toLowerCase()]=r;});else for(let r in e)S(e,r)&&r!=="__proto__"&&(t[r.toLowerCase()]=e[r]);return t}function it(){return typeof window!==D&&typeof window.addEventListener===b}function W(e,t){if(typeof DOMException!==D)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Se=()=>{let e=typeof navigator!==D&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)},ut=()=>typeof document!==D&&document.visibilityState==="hidden",ct=()=>typeof navigator!==D&&navigator.onLine===false;async function F(e,t,...r){if(!e)return;let s=n=>n&&g(t)&&g(n)&&Object.assign(t,B(n));if(typeof e===b)s(await e(t,...r));else if(Array.isArray(e))for(let n of e)s(await n(t,...r));}var ye=class extends Error{constructor(t,r,s){super(t),this.request=r,this.response=s,this.status=s?s.status:0,this.statusText=s?s.statusText:"",this.config=r,this.isCancelled=false,this.name="FetchError";}};var he=class extends ye{constructor(t,r,s){super(t,r,s),this.name="ResponseError";}};var be=600,Pe=1e3,Qe=Array(be).fill(0).map(()=>[]),U=new Map,ge=0,Fe=0,A=null,lt=([e,t])=>{U.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(C);}catch{}},M=(e,t,r)=>{Y(e);let s=r/Pe+(A&&h()!==Fe?1:0);if(r=be||r%Pe!==0){U.set(e,[setTimeout(lt.bind(null,[e,t]),Math.min(r,Re))]);return}let n=(ge+s)%be;Qe[n].push([e,t]),U.set(e,n),A||(Fe=h(),A=setInterval(()=>{ge=(ge+1)%be,Fe=h();let a=Qe[ge];for(let o=0;o{let t=U.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Qe[t];for(let s=0;s{dt(e,W(t+" aborted due to timeout",et));},r),c}async function dt(e,t=null){if(e){let r=G.get(e);r&&(t&&r[0].abort(t),De(e));}}function De(e){Y(e),G.delete(e);}function mt(e,t){let r=G.get(e);r&&(r[4]=t);}function He(e,t){if(!e)return null;let r=G.get(e);return r&&r[4]&&!r[3]&&h()-r[2]{if(!a[s]||r&&n-a[1]{r[t]&&jt(s);});}function Ne(e){if(V.has(e))return;let t=Rt.bind(null,e,true,e==="focus"),r=pt.get(e);if(r){let s=r(t);V.set(e,s);return}it()&&(window.addEventListener(e,t),V.set(e,()=>window.removeEventListener(e,t)));}function yt(e){let t=V.get(e);t&&(t(),V.delete(e));}function ht(e,t,r,s,n,a,o,i){let u=Z.get(e)||[];u[0]=t,u[1]=h(),u[2]=Ut,u[3]=s,u[4]=n,u[5]=a,u[6]=o,u[7]=i,Z.set(e,u),a&&Ne("focus"),o&&Ne("online"),s&&M("s:"+e,Ee.bind(null,e,true),s*1e3);}function jt(e){Z.delete(e),Y("s:"+e);}var ne=new Map;function Kt(e,t){let r=ne.get(e);r||ne.set(e,r=new Set),r.add(t);}function zt(e,t){let r=ne.get(e);r&&(r.delete(t),r.size===0&&ne.delete(e));}function L(e,t){let r=ne.get(e);if(r)if(r.size===1){let s=r.values().next().value;s(t);}else r.forEach(s=>s(t));}function kt(e,t){return e?(Kt(e,t),()=>{zt(e,t);}):C}var Te=(Se()?60:30)*1e3,j={strategy:pe,timeout:Te,loadingTimeout:Te/10,focusThrottleInterval:5e3,headers:{Accept:te+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:Te/30,maxDelay:Te,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504],methods:[O,re,"PUT","DELETE","OPTIONS","TRACE"]}};function Jt(e){let t=B(e);return $({retry:j.retry,headers:j.headers},t,j)}function Wt(){return {...j}}function _e(e,t){let r=$(j,t?B(t):{});return Yt(e,r)}function Yt(e,t){let r=t.method;r=r?r.toUpperCase():O;let s;r!==O&&r!==re&&(s=t.body??t.data,s&&typeof s!==x&&se(s)&&(s=JSON.stringify(s))),Gt(t.headers,s);let n=t.withCredentials?"include":t.credentials,a=nt(e,t.urlPathParams),o=at(a,t.params),u=ot(e)?"":t.baseURL||t.apiUrl||"",c=u&&o&&!u.endsWith("/")&&!/^[/?#]/.test(o)?"/":"";return t.url=u+c+o,t.method=r,t.credentials=n,t.body=s,t}function Gt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==D&&t instanceof Blob||typeof ReadableStream!==D&&t instanceof ReadableStream)return;let r;if(J(t))r=z+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=z+"octet-stream";else if(se(t))r=te+";"+$e;else return;e instanceof Headers?e.has(_)||e.set(_,r):g(e)&&!Array.isArray(e)&&!E(e)[_.toLowerCase()]&&(e[_]=r);}var Xt=["onRequest","onResponse","onError","onLoadingSlow"];function $(e,t,r={}){Object.assign(r,e,t),Pt("retry",e,t,r),Pt("headers",e,t,r);for(let s of Xt)Vt(s,e,t,r);return r}function Vt(e,t,r,s){let n=t[e],a=r[e];n&&a?s[e]=e==="onResponse"?[].concat(a,n):[].concat(n,a):(n||a)&&(s[e]=n||a);}function Pt(e,t,r,s){let n=t[e],a=r[e];if(a)if(e==="headers"){let o=n instanceof Headers||a instanceof Headers,i=o?E(n):{...n},u=o?E(a):B(a);for(let c of Object.keys(u)){let f=c.toLowerCase();for(let l in i)l.toLowerCase()===f&&delete i[l];i[c]=u[c];}s[e]=i;}else s[e]={...n,...B(a)};else a===void 0&&g(n)&&!(n instanceof Headers)&&(s[e]={...n});}var Q=new Map,ie=new Map,oe="|",Ue=64,Zt=/[^\w\-_|/:@.?=&~%#]/g,$t=/[^\w\-_|/:@.?=&~%#]/,er=/^(accept(-language|-encoding)?|authorization|content-type|referer|origin|user-agent|cookie|x-(api-key|requested-with|client-id|tenant-id|user-id|app-version|feature-flag|device-id|platform|session-id|locale))$/i;function ue(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===x?r:r(e);let{url:s="",method:n=O,headers:a=null,body:o=null,credentials:i="same-origin"}=e,u="";if(a){let l;a instanceof Headers?l=E(a):l=a;let p=Object.keys(l),m=p.length;m>1&&p.sort();let q="";for(let T=0;T{f+=p+"="+(typeof l===x?l:"F"+bt(l))+"&";}),f.length>Ue&&(f=X(f));else if(g(o)&&!se(o))f="B"+bt(o);else {let l=g(o)?JSON.stringify(st(o)):String(o);f=l.length>Ue?X(l):l;}return Dt(c+oe+f)}var gt=new WeakMap,tr=0;function bt(e){let t=gt.get(e);return t||gt.set(e,t=++tr),t}function Dt(e){return $t.test(e)?e.replace(Zt,"")+oe+X(e):e}function Me(e){return e.expiry?h()>e.expiry:false}function Le(e){if(!e)return null;let t=Q.get(e);return t?t.data:null}function ce(e){return Q.get(e)}function we(e,t,r,s){if(r===0){le(e);return}let n=h(),a=r?r*1e3:0,o=s?s*1e3:0;Q.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+a}),a>0&&Et(e,a);}function Et(e,t){M("c:"+e,()=>le(e,true),t);}function le(e,t=false){if(t){let s=ce(e);if(!s||!Me(s))return}Q.delete(e);let r=ie.get(e);r&&(ie.delete(e),je(()=>r.delete(e)));}function je(e){try{Promise.resolve(e()).catch(C);}catch{}}function Tt(e,t){let r=Q.get(e);if(t&&r){let{data:s,status:n,statusText:a,headers:o}=r.data;ie.set(e,t),je(()=>t.set(e,{...r,data:{data:s,status:n,statusText:a,headers:o}}));}}async function wt(e,t){let r=t.cacheStore;if(!r||xe(t))return null;let s;try{s=await r.get(e);}catch{return null}return !s||Q.has(e)?null:Me(s)?(je(()=>r.delete(e)),null):s}function xt(e,t,r){return Q.set(e,t),ie.set(e,r),t.expiry&&Et(e,t.expiry-h()),L(e,t.data),!t.stale||h(){let s=t.defaultResponse,n=t.cacheKey,a=Ke.bind(null,n);if(!e)return {ok:false,error:r,data:s??null,headers:null,config:t,mutate:a,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===b&&e instanceof Response,i=e.data;s!==void 0&&(i==null||/^\[object (Object|Array)\]$/.test(Object.prototype.toString.call(i))&&Object.keys(i).length===0)&&(e.data=i=s),t.flattenResponse&&(e.data=i=ve(i)),t.select&&(e.data=i=t.select(i));let u=E(e.headers);if(o){let c={body:e.body,bodyUsed:e.bodyUsed,ok:e.ok,redirected:e.redirected,type:e.type,url:e.url,status:e.status,statusText:e.statusText,blob:async()=>i instanceof ArrayBuffer?new Blob([i]):new Blob,json:async()=>i,text:async()=>i,clone:()=>({...c}),arrayBuffer:async()=>i instanceof ArrayBuffer?i:new ArrayBuffer(0),formData:async()=>i instanceof FormData?i:new FormData,bytes:async()=>new Uint8Array(i instanceof ArrayBuffer?i:new ArrayBuffer(0)),error:r,data:i,headers:u,config:t,mutate:a,isFetching:false,isSuccess:e.ok&&!r,isError:!!r};return c}return g(e)&&(e.error=r,e.headers=u,e.isFetching=false,e.mutate=a,e.isSuccess=e.ok&&!r,e.isError=!!r),e};function qt(e){let t=Date.parse(e)-h();return isNaN(t)?null:Math.max(0,Math.floor(t))}function rr(e){if(!e)return null;let t=e.headers||{},r=t["retry-after"];if(r){let o=Number(r);if(!isNaN(o)&&o>=0)return o*1e3;let i=qt(r);if(i!==null)return i}let s="ratelimit-reset",n=t[s+"-after"]||t["x-"+s+"-after"];if(n){let o=Number(n);if(!isNaN(o))return o*1e3}let a=t[s+"-at"]||t["x-"+s+"-at"];return a?qt(a):null}async function Ot(e,t){let{retries:r=0,delay:s=0,backoff:n=1,maxDelay:a,retryOn:o=[],shouldRetry:i,jitter:u,methods:c}=t,f=0,l=s,p=r>0?r:0,m;for(;f<=p;){if(f>0&&m){let d=m.config,H=d.onRetry;H&&(await F(H,m,f),d._isAutoKey&&(d._prevKey=d.cacheKey,d.cacheKey=ue(d,false)));}m=await e(f>0,f);let q=m.error;if(q?await sr(m,f,p,i,o,c):!(i&&fo.toUpperCase()===e.config.method)))}function ar(e,t){return typeof t===b?t(e):t?Math.random()*e:e}async function Bt(e,t,r,s=0,n=0,a=false,o=false,i){if(!t)return e();let u=0,c;for(;(s===0||u0&&await ae(n,i),c=await e(),u++,!(s>0&&u>=s||!t||r&&r(c,u)));)do if(await ae(t,i),i&&i.aborted)return c;while(!a&&ut()||!o&&ct());return c}var nr=[204,205,304],or=/^(accept-charset|accept-encoding|connection|content-length|cookie2?|date|dnt|expect|host|keep-alive|origin|referer|set-cookie|te|trailer|transfer-encoding|upgrade|via)$|^(proxy-|sec-|access-control-request-)/,At=e=>typeof ReadableStream!==D&&e instanceof ReadableStream,qe=(e,t)=>({loaded:e,total:t,progress:t?e/t:void 0});function It(e,t){let r=t.body;return typeof XMLHttpRequest!==D&&!At(r)?ir(e,t,r):ur(e,t,r)}function ir(e,t,r){return new Promise((s,n)=>{let a=new XMLHttpRequest,o=t.signal,i=()=>a.abort(),u=f=>{o.removeEventListener("abort",i);try{f();}catch(l){n(l);}};a.open(t.method,e),a.responseType="blob",a.withCredentials=t.credentials==="include",new Headers(t.headers).forEach((f,l)=>or.test(l)||a.setRequestHeader(l,f)),a.upload.onprogress=f=>t.onUploadProgress(qe(f.loaded,f.lengthComputable?f.total:void 0)),a.onload=()=>u(()=>{let f=new Headers;for(let p of a.getAllResponseHeaders().split(/\r?\n/)){let m=p.indexOf(":");m>0&&f.append(p.slice(0,m),p.slice(m+1).trim());}let l=new Response(nr.includes(a.status)?null:a.response,{status:a.status,statusText:a.statusText,headers:f});Object.defineProperty(l,"url",{value:a.responseURL}),s(l);}),a.onerror=()=>u(()=>n(new TypeError("Network request failed")));let c=()=>u(()=>n(o.reason||W("The request was aborted",k)));if(a.onabort=c,o.aborted)return c();o.addEventListener("abort",i),a.send(r);})}async function ur(e,t,r){let s=new Headers(t.headers),n=r,a;if(!At(r)){let i=r instanceof Blob?r:await new Response(r).blob();a=i.size,n=i.stream(),i.type&&!s.has("content-type")&&s.set("content-type",i.type);}let o=0;return fetch(e,{...t,headers:s,body:n.pipeThrough(new TransformStream({transform(i,u){o+=i.byteLength,t.onUploadProgress(qe(o,a)),u.enqueue(i);}})),duplex:"half"})}function vt(e,t){if(!t||typeof Response!==b||!(e instanceof Response)||!e.body)return e;let r=e.headers,s=r.has("content-encoding")?void 0:Number(r.get("content-length"))||void 0,n=0,a=new Response(e.body.pipeThrough(new TransformStream({transform(o,i){n+=o.byteLength,t(qe(n,s&&Math.max(s,n))),i.enqueue(o);}})),e);for(let o of ["url","redirected","type"])Object.defineProperty(a,o,{value:e[o]});return a}async function St(e,t,r){let s=await t(e),n=s.error;if(!n)return ze(s,r),s;r.onError&&await F(r.onError,n);let a=n.isCancelled,o=r.logger;if(!a&&o&&o.warn&&o.warn("FETCH ERROR",lr(n)),r.strategy==="defaultResponse"&&(s.data=r.defaultResponse??null),ze(s,r,true),!a||r.rejectCancelled){let u=r.strategy;if(u===pe)throw n;u==="silent"&&await new Promise(()=>null);}return s}var cr=["authorization","proxy-authorization","cookie","x-api-key"];function lr(e){let t={...e.config,body:void 0,data:void 0,cacheKey:void 0,_prevKey:void 0,headers:E(e.config.headers)};for(let s of cr)t.headers[s]&&(t.headers[s]="[REDACTED]");let r=Object.assign(new Error(e.message),e,{config:t,request:t,response:e.response&&{...e.response,config:t}});return r.name=e.name,r.stack=e.stack,r}function Ft(e,t,r){e.status=e.status||t&&t.status||0,e.statusText=e.statusText||t&&t.statusText||"",e.config=e.request=r,e.response=t,e.isCancelled=e.name===k;}var ke=Object.freeze({isFetching:true});async function Oe(e,t=null){if(t&&typeof t.cacheKey=="string"){let y=fe(t.cacheKey,t.cacheTime,t);if(y)return y}let r=_e(e,t),{timeout:s,cancellable:n,cacheKey:a,dedupeTime:o,cacheTime:i,staleTime:u,refetchOnFocus:c,refetchOnReconnect:f,pollingInterval:l=0}=r,p=i!==void 0||u!==void 0,m=r.method,q=p&&(m===O||m===re)&&(r.etag??!r.fetcher),T=!!(a||s||o||p||n||c||f),d=null;T&&(d=ue(r));let H=null;if(d&&p){let y=fe(d,i,r);if(y)return y;if(r.cacheStore){let w=await wt(d,r),I=w&&Qt(w.data,d,r);if(I&&xt(d,{...w,data:I},r.cacheStore))return I}r.initialData!==void 0&&!Le(d)&&!xe(r)&&(H=Qt({data:r.initialData,status:200,statusText:"",headers:{}},d,r));}if(d&&o){let y=He(d,o);if(y)return y}let Je=r.retry||{},{retries:Ht=0,resetTimeout:Nt}=Je,N=r.signal,We=async(y,w=0)=>{let I=q&&Le(d);if(!w){if(H){let v=H;return H=null,v}d&&!y&&(u?fe(d,i,r)||(we(d,ke,i,u),L(d,ke)):L(d,ke)),r.cacheKey=d;}let ee=r.url,Ve=ft(d,ee,s,o||0,!!n,!!(s&&(!w||Nt))),P=r;P.signal=Ve.signal;let Ae=()=>Ve.abort(N.reason);N&&(N.aborted?Ae():N.addEventListener("abort",Ae));let me,R=null;try{r.onRequest&&(d&&o&&!w&&await null,await F(r.onRequest,P));let v=r.fetcher,K=fr(P,I);if(R=v?await v(ee,K):await(P.onUploadProgress&&P.body?It(ee,P):fetch(ee,K)),R=vt(R,P.onDownloadProgress),g(R)){if(K!==P&&R.status===304)return I;if(typeof Response===b&&R instanceof Response?R.data=P.parser?await P.parser(R):await Ct(R,P.responseType):v&&("data"in R&&"body"in R||(R={data:R})),R.config=P,R.ok!==void 0&&!R.ok)throw new he(P.method+" to "+ee+" failed! Status: "+(R.status||null),P,R)}me=Ce(R,P);let Ze=r.onResponse;Ze&&await F(Ze,me);}catch(v){let K=v;Ft(K,R,P),me=Ce(R,P,K);}finally{N&&N.removeEventListener("abort",Ae);}return me},Be=Ht>0?y=>Ot((w,I)=>We(y,I),Je):We,{onLoadingSlow:Ye,loadingTimeout:Ge}=r,_t=Ye&&Ge?async y=>{if(y)return Be(y);let w=setTimeout(()=>F(Ye,r).catch(C),Ge);try{return await Be(y)}finally{clearTimeout(w);}}:Be,de=(y=false)=>St(y,_t,r),Xe=l?Bt(de,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay,r.refreshWhenHidden,r.refreshWhenOffline,N):de();return d&&(o&&mt(d,Xe),(u||c||f)&&ht(d,de,void 0,u,de,!!c,!!f,r.focusThrottleInterval)),Xe}function Qt(e,t,r){try{let s=typeof Response===b?new Response(null,e):{ok:!0,status:e.status,statusText:e.statusText,headers:e.headers};s.data=e.data,r.cacheKey=t;let n=Ce(s,{...r,select:void 0,flattenResponse:!1,defaultResponse:void 0});return n.config=r,n}catch{return null}}function fr(e,t){let r=t&&!t.error&&t.headers&&t.headers.etag,s=r&&E(e.headers);return s&&!s["if-none-match"]?{...e,headers:{...s,"if-none-match":r}}:e}function dr(e){let t=e.endpoints;async function r(n){return console.error("Add "+n+" to 'endpoints'."),null}let s={config:e,endpoints:t,async request(n,a={}){let o=S(t,n)?t[n]:void 0,i=o||{url:String(n)},u=i.url,c=u.replace(/[\t\n\r]/g,"").replace(/^[\x00-\x20]+/,"");if(/^[/\\]{2}/.test(c))throw new Error("Protocol-relative URLs not allowed.");let f=/^[a-z][a-z\d+\-.]*:/i.test(c)?o&&o.url===u?$(i,a):a:$($(e,i),a);return Oe(u,f)}};return new Proxy(s,{get(n,a){if(a in s)return s[a];if(!(typeof a=="symbol"||a==="then"))return S(t,a)?s.request.bind(null,a):r.bind(null,a)}})} +exports.abortRequest=dt;exports.addTimeout=M;exports.buildConfig=_e;exports.createAbortError=W;exports.createApiFetcher=dr;exports.deleteCache=le;exports.fetchf=Oe;exports.fetchff=Oe;exports.generateCacheKey=ue;exports.getCache=ce;exports.getCachedResponse=fe;exports.getDefaultConfig=Wt;exports.getInFlightPromise=He;exports.isSlowConnection=Se;exports.mutate=Ke;exports.removeRevalidators=Lt;exports.revalidate=Ee;exports.revalidateAll=Rt;exports.setCache=we;exports.setDefaultConfig=Jt;exports.setEventProvider=Mt;exports.subscribe=kt;//# sourceMappingURL=index.js.map //# 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 8a0a6e5..6754a67 100644 --- a/dist/node/index.js.map +++ b/dist/node/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/constants.ts","../../src/utils.ts","../../src/interceptor-manager.ts","../../src/errors/fetch-error.ts","../../src/errors/response-error.ts","../../src/timeout-wheel.ts","../../src/inflight-manager.ts","../../src/hash.ts","../../src/revalidator-manager.ts","../../src/pubsub-manager.ts","../../src/config-handler.ts","../../src/cache-manager.ts","../../src/response-parser.ts","../../src/retry-handler.ts","../../src/polling-handler.ts","../../src/error-handler.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"names":["APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CHARSET_UTF_8","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","FUNCTION","ABORT_ERROR","TIMEOUT_ERROR","GET","HEAD","REJECT","MAX_DELAY_MS","MAX_DEPTH","hasOwn","o","k","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","key","sortObject","sortedObj","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","v","buildParams","prefix","depth","i","len","replaceUrlPathParams","urlPathParams","match","encoded","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","merge","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","wheel","keyMap","position","lastTick","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","customEventProviders","setEventProvider","type","provider","removeEventHandler","addEventHandler","revalidateAll","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeRevalidator","event","handler","customProvider","cleanup","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","existing","listeners","addListener","fn","set","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","merged","buildFetcherConfig","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","separator","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","isInstance","overrides","lowerKey","existingKey","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","keys","cacheStr","sanitizeCacheKey","bodyString","getObjectId","objectIds","lastObjectId","id","isCacheExpired","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","handleResponseCache","output","isError","skipCache","prevCacheKey","parseResponseData","contentType","mimeType","trimmed","prepareResponse","defaultResponse","mutatator","isNativeResponse","getMsFromHttpDate","dateString","getRetryAfterMs","extendedResponse","retryAfter","RATELIMIT_RESET","rateLimitResetAfter","rateLimitResetAt","withRetry","requestFn","retries","delay","backoff","maxDelay","retryOn","shouldRetry","attempt","waitTime","maxRetries","cfg","onRetry","getShouldStopRetrying","retryAfterMs","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","redactError","strategy","SENSITIVE_HEADERS","copy","enhanceError","inFlightResponse","fetchf","cached","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","_error","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","resolvedUrl","mergedConfig","_target","prop"],"mappings":"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","file":"index.js","sourcesContent":["export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CHARSET_UTF_8 = 'charset=utf-8';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\nexport const FUNCTION = 'function';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n\nexport const REJECT = 'reject';\n\n// Larger timer delays overflow and fire immediately in browsers and Node.js (~24.8 days)\nexport const MAX_DELAY_MS = 2147483647;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, MAX_DELAY_MS, OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\n// Prevent stack overflow with recursion depth limit\nconst MAX_DEPTH = 10;\n\nexport const hasOwn = (o: any, k: string) =>\n Object.prototype.hasOwnProperty.call(o, k);\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 (hasOwn(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function checks for dangerous properties like '__proto__', 'constructor',\n * and 'prototype'. If none are present, the object is returned as-is (zero-copy fast path).\n * Otherwise, a shallow copy is created with the dangerous properties removed.\n *\n * @param obj - The object to sanitize\n * @returns A safe object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const hasProto = hasOwn(obj, '__proto__');\n const hasCtor = hasOwn(obj, 'constructor');\n const hasPrototype = hasOwn(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n // Copy key by key, as a spread compiled to assignments would let \"__proto__\" set the prototype\n const safeObj = {} as Record;\n\n for (const key of Object.keys(obj)) {\n if (key !== '__proto__' && key !== 'constructor' && key !== 'prototype') {\n safeObj[key] = obj[key];\n }\n }\n\n return safeObj as T;\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 // Without a prototype, a \"__proto__\" key is kept as a regular property instead of setting the prototype\n const sortedObj = Object.create(null) as Record;\n\n Object.keys(obj)\n .sort()\n .forEach((k) => (sortedObj[k] = obj[k]));\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 + (baseUrl.includes('?') ? '&' : '?') + 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, depth = 0) => {\n // Stop recursion if maximum depth is reached\n if (depth >= MAX_DEPTH) {\n return s;\n }\n\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 depth + 1,\n );\n }\n } else if (isObject(obj)) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key], depth + 1);\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], depth + 1);\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 // This is for compatibility with server frameworks that expect the literal notation\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 || url.indexOf(':') === -1) {\n return url;\n }\n\n // Use a single RegExp and avoid unnecessary casts and function calls\n // Precompute keys for faster lookup\n const params = urlPathParams as DefaultUrlParams;\n\n // Use a replacer function that avoids extra work\n return url.replace(/:([a-zA-Z0-9_]+)/g, (match, key) => {\n // Use hasOwnProperty for strict key existence check\n if (hasOwn(params, key)) {\n const value = params[key];\n\n // Only replace if value is not undefined or null\n if (value !== undefined && value !== null) {\n const encoded = encodeURIComponent(String(value));\n\n // These can't be encoded, and URL parsers would move the request to another path\n if (encoded === '.' || encoded === '..') {\n throw new Error('Path params \".\" and \"..\" not allowed.');\n }\n\n return encoded;\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL starts with a scheme (e.g., \"http://\", \"https://\").\n * A \"://\" appearing later, e.g. in a query string, does not make the URL absolute.\n *\n * @param url - The URL string to check.\n * @returns `true` if the URL is absolute, otherwise `false`.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n}\n\nexport const timeNow = () => Date.now();\n\nexport const noop = () => {};\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 (value === 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 (\n typeof globalThis !== UNDEFINED &&\n typeof globalThis.Buffer !== UNDEFINED &&\n globalThis.Buffer.isBuffer(value)\n ) {\n return false;\n }\n\n if (value instanceof Date || isSearchParams(value)) {\n return false;\n }\n\n if (isObject(value)) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` (plain object)\n if (proto === Object.prototype) {\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 const delayInvocation = (ms: number): Promise =>\n new Promise((resolve) =>\n setTimeout(resolve, Math.min(ms, MAX_DELAY_MS), true),\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, depth = 0): any {\n if (depth >= MAX_DEPTH) {\n return data;\n }\n\n if (data && isObject(data) && typeof data.data !== UNDEFINED) {\n return flattenData(data.data, depth + 1);\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 // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key.toLowerCase()] = value;\n });\n } else {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n // Assigning \"__proto__\" would set the prototype of the result\n if (hasOwn(headers, key) && key !== '__proto__') {\n headersObject[key.toLowerCase()] = headers[key];\n }\n }\n }\n\n return headersObject;\n}\n\n/**\n * Determines if the current environment is a browser.\n *\n * @returns {boolean} - True if running in a browser environment, false otherwise.\n */\nexport function isBrowser(): boolean {\n // For node and some mobile frameworks like React Native, `add/removeEventListener` doesn't exist on window!\n return (\n typeof window !== UNDEFINED && typeof window.addEventListener === FUNCTION\n );\n}\n\n/**\n * Creates an abort/timeout error compatible with all JS runtimes.\n * Falls back to a plain Error with the correct `name` when DOMException is unavailable (e.g. React Native).\n *\n * @param {string} message - The error message.\n * @param {string} name - The error name (e.g. 'AbortError', 'TimeoutError').\n * @returns {DOMException | Error} - An error object with the specified name.\n */\nexport function createAbortError(\n message: string,\n name: string,\n): DOMException | Error {\n if (typeof DOMException !== UNDEFINED) {\n return new DOMException(message, name);\n }\n\n const error = new Error(message);\n error.name = name;\n\n return error;\n}\n\n/**\n * Detects if the user is on a slow network connection\n * @returns {boolean} True if connection is slow, false otherwise or if detection unavailable\n */\nexport const isSlowConnection = (): boolean => {\n const conn = typeof navigator !== UNDEFINED && (navigator as any).connection;\n\n return conn && ['slow-2g', '2g', '3g'].includes(conn.effectiveType);\n};\n","import { FUNCTION } from './constants';\nimport type { InterceptorFunction } from './types/interceptor-manager';\nimport { isObject, sanitizeObject } from './utils';\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 Args - Type of additional arguments.\n * @template I - Type of interceptors.\n *\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n * @param {T} data - The data object to process.\n * @param {...Args} args - Additional arguments to pass to interceptors.\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptors<\n T extends object,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Args extends any[] = any[],\n I = InterceptorFunction | InterceptorFunction[],\n>(interceptors: I | undefined, data: T, ...args: Args): Promise {\n if (!interceptors) {\n return;\n }\n\n const merge = (v: unknown) =>\n v &&\n isObject(data) &&\n isObject(v) &&\n Object.assign(data, sanitizeObject(v));\n\n if (typeof interceptors === FUNCTION) {\n merge(await (interceptors as InterceptorFunction)(data, ...args));\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n merge(await interceptor(data, ...args));\n }\n }\n}\n","import type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\n/**\n * This is a base error class\n */\nexport class FetchError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends Error {\n status: number;\n statusText: string;\n config: RequestConfig;\n isCancelled: boolean;\n\n constructor(\n message: string,\n public request: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n public response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message);\n\n this.name = 'FetchError';\n this.status = response ? response.status : 0;\n this.statusText = response ? response.statusText : '';\n this.config = request;\n this.isCancelled = false;\n }\n}\n","import { FetchError } from './fetch-error';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\nexport class ResponseError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends FetchError {\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message, request, response);\n\n this.name = 'ResponseError';\n }\n}\n","/**\n * @module timeout-wheel\n * @description\n * Ultra-minimal timing wheel implementation optimized for max performance & many requests.\n * For most of the cases it's 4-100x faster than setTimeout and setInterval alone.\n * Provides efficient scheduling and cancellation of timeouts using a circular array.\n *\n * Position 0 → 1 → 2 → ... → 599 → 0 → 1 → 2 ...\n * Time: 0s 1s 2s 599s 600s 601s 602s\n *\n * The timing wheel consists of 600 slots (one per second for 10 min).\n * Each slot contains a list of timeout items, each associated with a unique key and callback.\n * Timeouts are scheduled by placing them in the appropriate slot based on the delay in seconds.\n * The wheel advances every second, executing and removing callbacks as their timeouts expire.\n * Defaults to setTimeout if the delay doesn't fit in the wheel (~10 minutes) or is not divisible by 1000.\n *\n * @remarks\n * - Designed for minimal footprint and simplicity.\n * - Only supports second-level granularity (minimum timeout: 1 second).\n * - Timeouts never fire early, but may fire up to 1 second late.\n * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { MAX_DELAY_MS } from './constants';\nimport { noop, timeNow } from './utils';\n\ntype TimeoutCallback = () => unknown | Promise;\ntype TimeoutItem = [string, TimeoutCallback]; // [key, callback]\n\nconst WHEEL_SIZE = 600; // 600 slots for 10 min (1 slot per second)\nconst SECOND = 1000; // 1 second in milliseconds\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\nlet lastTick = 0; // Time when the wheel last advanced (or started)\nlet timer: NodeJS.Timeout | null = null;\n\nconst handleCallback = ([key, callback]: TimeoutItem): void => {\n keyMap.delete(key);\n\n try {\n const result = callback();\n if (result && result instanceof Promise) {\n // Silently ignore async errors to prevent wheel from stopping\n result.catch(noop);\n }\n } catch {\n // Ignore callback errors to prevent wheel from stopping\n }\n};\n\nexport const addTimeout = (\n key: string,\n cb: TimeoutCallback,\n ms: number,\n): void => {\n removeTimeout(key);\n\n // A running wheel is already part-way through its current second, so the timeout\n // waits one more slot to never fire early. A new wheel starts its first second now.\n const seconds = ms / SECOND + (timer && timeNow() !== lastTick ? 1 : 0);\n\n // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || seconds >= WHEEL_SIZE || ms % SECOND !== 0) {\n keyMap.set(key, [\n setTimeout(\n handleCallback.bind(null, [key, cb]),\n Math.min(ms, MAX_DELAY_MS),\n ),\n ]); // Store timeout ID instead of slot\n\n return;\n }\n\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n lastTick = timeNow();\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n lastTick = timeNow();\n const slot = wheel[position];\n\n // Use slot.length directly (not cached) so mid-iteration mutations\n // from callbacks (e.g. removeTimeout) are handled correctly\n for (let i = 0; i < slot.length; i++) {\n handleCallback(slot[i]);\n }\n\n slot.length = 0; // Reuse array, avoid GC allocation\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }, SECOND);\n }\n};\n\nexport const removeTimeout = (key: string): void => {\n const slotOrTimeout = keyMap.get(key);\n\n if (slotOrTimeout !== undefined) {\n // It's a Timeout object from setTimeout\n if (Array.isArray(slotOrTimeout)) {\n clearTimeout(slotOrTimeout[0]);\n } else {\n const slotArr = wheel[slotOrTimeout];\n\n for (let i = 0; i < slotArr.length; i++) {\n if (slotArr[i][0] === key) {\n slotArr.splice(i, 1);\n break;\n }\n }\n }\n\n keyMap.delete(key);\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }\n};\n\nexport const clearAllTimeouts = () => {\n // Clear native setTimeout timeouts first!\n keyMap.forEach((value) => {\n if (Array.isArray(value)) {\n clearTimeout(value[0]);\n }\n });\n\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n\n keyMap.clear();\n\n for (let i = 0; i < WHEEL_SIZE; i++) {\n wheel[i].length = 0;\n }\n\n position = 0;\n};\n","/**\n * @module inflight-manager\n *\n * Manages in-flight asynchronous requests using unique keys to enable deduplication and cancellation.\n *\n * Provides utilities for:\n * - Deduplication of requests within a configurable time window (`dedupeTime`)\n * - Timeout management and automatic request abortion\n * - AbortController lifecycle and cancellation logic\n * - Concurrency control and request state tracking\n * - In-flight promise deduplication to prevent duplicate network calls\n *\n * @remarks\n * - Requests with the same key within the deduplication interval share the same AbortController and in-flight promise.\n * - Supports cancellation of previous requests when a new one with the same key is issued, if `isCancellable` is enabled.\n * - Timeout logic ensures requests are aborted after a specified duration, if enabled.\n * - Internal queue state is managed via a Map, keyed by request identifier.\n * - Polled requests are also marked as \"in-flight\" to prevent duplicate requests.\n */\n\nimport { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { createAbortError, timeNow } from './utils';\n\nexport type InFlightItem = [\n AbortController, // AbortController for the request\n boolean, // Whether timeout is enabled for the request\n number, // Timestamp when the request was marked in-flight\n boolean, // isCancellable - whether the request can be cancelled\n Promise | null, // Optional in-flight promise for deduplication\n];\n\nconst inFlight: Map = 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 {string | null} key - Unique key for the request (e.g. cache key).\n * @param {string} url - The request URL (for error messages/timeouts).\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 {AbortController} - A promise that resolves to an AbortController.\n */\nexport function markInFlight(\n key: string | null,\n url: string,\n timeout: number | undefined,\n dedupeTime: number,\n isCancellable: boolean,\n isTimeoutEnabled: boolean,\n): AbortController {\n if (!key) {\n return new AbortController();\n }\n\n const now = timeNow();\n const item = inFlight.get(key);\n let prevPromise: Promise | null = null;\n\n // Previous request is in-flight, check if we can reuse it\n if (item) {\n const prevController = item[0];\n const prevIsCancellable = item[3];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (\n !prevIsCancellable &&\n now - item[2] < dedupeTime &&\n !prevController.signal.aborted\n ) {\n return prevController;\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 (prevIsCancellable) {\n prevController.abort(\n createAbortError('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n removeTimeout(key);\n prevPromise = item[4];\n }\n\n const controller = new AbortController();\n\n inFlight.set(key, [\n controller,\n isTimeoutEnabled,\n now,\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n createAbortError(url + ' aborted due to timeout', TIMEOUT_ERROR),\n );\n },\n timeout as number,\n );\n }\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param key - Unique key for the request.\n * @param {boolean} error - Optional error to abort the request with. If null, the request is simply removed but no abort sent.\n * @returns {Promise} - A promise that resolves when the request is aborted and removed.\n */\nexport async function abortRequest(\n key: string | null,\n error: DOMException | Error | null | string = null,\n): Promise {\n // If the key is not in the queue, there's nothing to remove\n if (key) {\n const item = inFlight.get(key);\n\n if (item) {\n // If the request is not yet aborted, abort it with the provided error\n if (error) {\n const controller = item[0];\n controller.abort(error);\n }\n\n removeInFlight(key);\n }\n }\n}\n\n/**\n * Removes a request from the in-flight queue without aborting or clearing timeout.\n *\n * @param key - Unique key for the request.\n */\nexport function removeInFlight(key: string | null): void {\n removeTimeout(key!);\n inFlight.delete(key!);\n}\n\n/**\n * Gets the AbortController for a request key.\n *\n * @param key - Unique key for the request.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n key: string,\n): Promise {\n const item = inFlight.get(key);\n\n return item?.[0];\n}\n\n/**\n * Adds helpers for in-flight promise deduplication.\n *\n * @param key - Unique key for the request.\n * @param promise - The promise to store.\n */\nexport function setInFlightPromise(\n key: string,\n promise: Promise,\n): void {\n const item = inFlight.get(key);\n if (item) {\n // store the promise at index 4 — item is already the Map's reference, no need to re-set\n item[4] = promise;\n }\n}\n\n/**\n * Retrieves the in-flight promise for a request key if it exists and is within the dedupeTime interval.\n *\n * @param key - Unique key for the request.\n * @param dedupeTime - Deduplication time in milliseconds.\n * @returns {Promise | null} - The in-flight promise or null.\n */\nexport function getInFlightPromise(\n key: string | null,\n dedupeTime: number,\n): Promise | null {\n if (!key) {\n return null;\n }\n\n const prevReq = inFlight.get(key);\n\n if (\n prevReq &&\n // If the request is in-flight and has a promise\n prevReq[4] &&\n // If the request is cancellable, we will not reuse it\n !prevReq[3] &&\n // If the request is within the dedupeTime\n timeNow() - prevReq[2] < dedupeTime &&\n // If one request is cancelled, ALL deduped requests get cancelled\n !prevReq[0].signal.aborted\n ) {\n return prevReq[4] as Promise;\n }\n\n return null;\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","/**\n * @module revalidator-manager\n *\n * Provides utilities for managing cache revalidation functions, including:\n * - Registering and unregistering revalidators for specific cache keys.\n * - Triggering revalidation for a given key.\n * - Enabling or disabling automatic revalidation on window focus and if user comes back online for specific keys.\n * - Attaching and removing global focus and online event handlers to trigger revalidation.\n *\n * Revalidators are functions that can be registered to revalidate cache entries when needed.\n * They are typically used to refresh data in the cache when the window gains focus or when specific actions occur.\n * @performance O(1) lookup by key makes it blazing fast to register, unregister, and revalidate cache entries.\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n * @remarks\n * - Designed to be used in various environments (Deno, Node.js, Bun, Browser, etc.) to ensure cache consistency and freshness.\n */\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { FetchResponse } from './types';\nimport { isBrowser, noop, timeNow } from './utils';\n\nexport type RevalidatorFn = (\n isStaleRevalidation?: boolean,\n) => Promise;\n\ntype EventType = 'focus' | 'online';\n\ntype RevalidatorEntry = [\n RevalidatorFn, // main revalidator\n number, // lastUsed\n number, // ttl\n number?, // staleTime\n RevalidatorFn?, // bgRevalidator\n boolean?, // refetchOnFocus\n boolean?, // refetchOnReconnect\n];\n\nconst DEFAULT_TTL = 3 * 60 * 1000; // Default TTL of 3 minutes\nconst revalidators = new Map();\n\n/**\n * Stores cleanup functions for active event handlers (browser or custom providers).\n * Each entry removes the corresponding event listener when called.\n * @remarks\n * - Improves performance by reducing the number of event listeners.\n * - Enables efficient O(1) lookup and management of event handlers for revalidation.\n */\nconst eventHandlers = new Map void>();\n\n/** Subscribe to an event and return a cleanup function */\nexport type EventProvider = (handler: () => void) => () => void;\n\nconst customEventProviders = new Map();\n\n/**\n * Registers a custom event provider for 'focus' or 'online' events.\n * Useful for non-browser environments like React Native.\n *\n * @param type - The event type ('focus' or 'online').\n * @param provider - A function that subscribes to the event and returns a cleanup function.\n */\nexport function setEventProvider(\n type: EventType,\n provider: EventProvider,\n): void {\n customEventProviders.set(type, provider);\n\n // Re-register if already active\n if (eventHandlers.has(type)) {\n removeEventHandler(type);\n addEventHandler(type);\n }\n}\n\n/**\n * Triggers revalidation for all registered entries based on the given event type.\n * For example, if it's a 'focus' event, it will revalidate entries that have the `refetchOnFocus` flag set.\n * Updates the timestamp and invokes the revalidator function for each applicable entry.\n *\n * @param type - The type of event that caused the revalidation (e.g., 'focus' or 'online').\n * @param isStaleRevalidation - If `true`, uses background revalidator and doesn't mark as in-flight.\n */\nexport function revalidateAll(\n type: EventType,\n isStaleRevalidation: boolean = true,\n) {\n const flagIndex = type === 'focus' ? 5 : 6;\n const now = timeNow();\n\n revalidators.forEach((entry) => {\n if (!entry[flagIndex]) {\n return;\n }\n\n entry[1] = now;\n\n // If it's a stale revalidation, use the background revalidator function\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n if (revalidator) {\n Promise.resolve(revalidator(isStaleRevalidation)).catch(noop);\n }\n });\n}\n\n/**\n * Revalidates an entry by executing the registered revalidation function.\n *\n * @param key The unique identifier for the cache entry to revalidate. If `null`, no revalidation occurs.\n * @param isStaleRevalidation - If `true`, it does not mark revalidated requests as in-flight.\n * @returns A promise that resolves to the result of the revalidator function, or\n * `null` if no key or revalidator is found, or a `FetchResponse` if applicable.\n */\nexport async function revalidate(\n key: string | null,\n isStaleRevalidation: boolean = false,\n): Promise {\n // If no key is provided, no revalidation occurs\n if (!key) {\n return null;\n }\n\n const entry = revalidators.get(key);\n\n if (entry) {\n // Update only the lastUsed timestamp without resetting the whole array\n entry[1] = timeNow();\n\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n // If no revalidator function is registered, return null\n if (revalidator) {\n return await revalidator(isStaleRevalidation);\n }\n }\n\n // If no revalidator is registered for the key, return null\n return null;\n}\n\n/**\n * Removes all revalidators associated with the specified event type.\n *\n * @param type - The event type whose revalidators should be removed.\n */\nexport function removeRevalidators(type: EventType) {\n removeEventHandler(type);\n\n const flagIndex = type === 'focus' ? 5 : 6;\n\n // Clear all revalidators with this flag\n revalidators.forEach((entry, key) => {\n if (entry[flagIndex]) {\n removeRevalidator(key);\n }\n });\n}\n\n/**\n * Registers a generic revalidation event handler for the specified event type.\n * Supports browser window events and custom event providers (e.g. for React Native).\n * Ensures the handler is only added once.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'online').\n */\nfunction addEventHandler(event: EventType) {\n if (eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n // Priority 1: Custom event provider (works in any environment including React Native)\n const customProvider = customEventProviders.get(event);\n\n if (customProvider) {\n const cleanup = customProvider(handler);\n\n eventHandlers.set(event, cleanup);\n\n return;\n }\n\n // Priority 2: Browser window events\n if (isBrowser()) {\n window.addEventListener(event, handler);\n\n eventHandlers.set(event, () => window.removeEventListener(event, handler));\n }\n}\n\n/**\n * Removes the event handler for the specified event type.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n const cleanup = eventHandlers.get(event);\n\n if (cleanup) {\n cleanup();\n eventHandlers.delete(event);\n }\n}\n\n/**\n * Registers a revalidation functions for a specific cache key.\n *\n * @param {string} key Cache key to utilize\n * @param {RevalidatorFn} revalidatorFn Main revalidation function (marks in-flight requests)\n * @param {number} [ttl] Time to live in milliseconds (default: 3 minutes)\n * @param {number} [staleTime] Time (in seconds) after which the cache entry is considered stale\n * @param {RevalidatorFn} [bgRevalidatorFn] For stale revalidation (does not mark in-flight requests)\n * @param {boolean} [refetchOnFocus] Whether to revalidate on window focus\n * @param {boolean} [refetchOnReconnect] Whether to revalidate on network reconnect\n */\nexport function addRevalidator(\n key: string,\n revalidatorFn: RevalidatorFn, // Main revalidation function (marks in-flight requests)\n ttl?: number,\n staleTime?: number,\n bgRevalidatorFn?: RevalidatorFn, // For stale revalidation (does not mark in-flight requests)\n refetchOnFocus?: boolean,\n refetchOnReconnect?: boolean,\n) {\n const existing = revalidators.get(key);\n\n if (existing) {\n // Update in-place to avoid allocating a new tuple array\n existing[0] = revalidatorFn;\n existing[1] = timeNow();\n existing[2] = ttl ?? DEFAULT_TTL;\n existing[3] = staleTime;\n existing[4] = bgRevalidatorFn;\n existing[5] = refetchOnFocus;\n existing[6] = refetchOnReconnect;\n } else {\n revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\n ]);\n }\n\n if (refetchOnFocus) {\n addEventHandler('focus');\n }\n\n if (refetchOnReconnect) {\n addEventHandler('online');\n }\n\n if (staleTime) {\n addTimeout('s:' + key, revalidate.bind(null, key, true), staleTime * 1000);\n }\n}\n\nexport function removeRevalidator(key: string) {\n revalidators.delete(key);\n\n // Clean up stale timer\n removeTimeout('s:' + key);\n}\n\n/**\n * Periodically cleans up expired revalidators from the registry.\n * Removes any revalidator whose TTL has expired.\n *\n * @param {number} intervalMs How often to run cleanup (default: 3 minutes)\n * @returns {() => void} A function to stop the periodic cleanup\n */\nexport function startRevalidatorCleanup(\n intervalMs: number = DEFAULT_TTL,\n): () => void {\n const intervalId = setInterval(() => {\n const now = timeNow();\n\n revalidators.forEach(\n ([, lastUsed, ttl, , , refetchOnFocus, refetchOnReconnect], key) => {\n // Skip focus-only or reconnect-only revalidators to keep them alive\n if (refetchOnFocus || refetchOnReconnect) {\n return;\n }\n\n if (ttl > 0 && now - lastUsed > ttl) {\n removeRevalidator(key);\n }\n },\n );\n }, intervalMs);\n\n return () => clearInterval(intervalId);\n}\n","/**\n * Manages a set of listeners (subscribers) for arbitrary string keys, allowing cross-context or cross-component\n * cache updates and synchronization. Provides functions to add, remove, and notify listeners, as well as a\n * convenient subscribe/unsubscribe API.\n *\n * @template T - The type of the response object passed to listeners.\n *\n * @remarks\n * - Listeners are grouped by a string key, which typically represents a cache key or resource identifier.\n * - When `notifySubscribers` is called for a key, all listeners registered for that key are invoked with the provided response.\n * - The `subscribe` function returns an unsubscribe function for convenient cleanup.\n *\n * @example\n * ```ts\n * const unsubscribe = subscribe('user:123', (response) => {\n * // handle updated data\n * });\n * // Later, to stop listening:\n * unsubscribe();\n * ```\n */\n\nimport { noop } from './utils';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Listener = (response: T) => void;\n\nconst listeners = new Map>();\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n let set = listeners.get(key);\n\n if (!set) {\n listeners.set(key, (set = new Set()));\n }\n\n set.add(fn);\n}\n\nexport function removeListener(key: string, fn: Listener) {\n const set = listeners.get(key);\n\n if (set) {\n set.delete(fn);\n\n // If the set is empty, remove the key from the listeners map\n if (set.size === 0) {\n listeners.delete(key);\n }\n }\n}\n\nexport function notifySubscribers(key: string, response: T) {\n const fns = listeners.get(key);\n\n if (fns) {\n if (fns.size === 1) {\n // If there's only one listener, call it directly\n const fn = fns.values().next().value;\n fn!(response);\n } else {\n fns.forEach((fn) => fn(response));\n }\n }\n}\n\nexport function subscribe(key: string | null, fn: (response: T) => void) {\n if (!key) {\n // No op if no key is provided\n return noop;\n }\n\n addListener(key, fn);\n\n // Return an unsubscribe function\n return () => {\n removeListener(key, fn);\n };\n}\n","import { processHeaders } from './utils';\nimport {\n GET,\n APPLICATION_JSON,\n HEAD,\n STRING,\n CHARSET_UTF_8,\n CONTENT_TYPE,\n REJECT,\n UNDEFINED,\n APPLICATION_CONTENT_TYPE,\n} from './constants';\nimport type {\n HeadersObject,\n Method,\n RequestConfig,\n} from './types/request-handler';\nimport {\n replaceUrlPathParams,\n appendQueryParams,\n isSearchParams,\n isJSONSerializable,\n isSlowConnection,\n isAbsoluteUrl,\n sanitizeObject,\n isObject,\n} from './utils';\n\nconst defaultTimeoutMs = (isSlowConnection() ? 60 : 30) * 1000;\n\nexport const defaultConfig: RequestConfig = {\n strategy: REJECT,\n timeout: defaultTimeoutMs, // 30 seconds (60 on slow connections)\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n },\n retry: {\n delay: defaultTimeoutMs / 30, // 1 second (2 on slow connections)\n maxDelay: defaultTimeoutMs, // 30 seconds (60 on slow connections)\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 * Overwrites the default configuration with the provided custom configuration.\n *\n * @param {Partial} customConfig - The custom configuration to merge into the default config.\n * @returns {Partial} - The updated default configuration object.\n */\nexport function setDefaultConfig(\n customConfig: Partial,\n): Partial {\n const sanitized = sanitizeObject(customConfig);\n\n // Merge nested retry and headers settings into the current defaults instead of replacing them\n return mergeConfigs(\n { retry: defaultConfig.retry, headers: defaultConfig.headers },\n sanitized,\n defaultConfig,\n );\n}\n\n/**\n * Returns a shallow copy of the current default configuration.\n *\n * @returns {RequestConfig} - The current default configuration.\n */\nexport function getDefaultConfig(): RequestConfig {\n return { ...defaultConfig };\n}\n\n/**\n * Build request configuration from defaults and overrides.\n * This function merges the default configuration with the provided request configuration,\n * @param {string} url - Request url\n * @param {RequestConfig | null | undefined} reqConfig - Request configuration\n * @return {RequestConfig} - Merged request configuration\n */\nexport function buildConfig(\n url: string,\n reqConfig?: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null,\n): RequestConfig {\n // Merging gives the request its own copies of nested objects like headers, so that\n // mutations (e.g. by interceptors) never leak into the global defaults\n const merged = mergeConfigs(\n defaultConfig,\n reqConfig ? sanitizeObject(reqConfig) : {},\n );\n\n return buildFetcherConfig(url, merged);\n}\n\n/**\n * Builds the fetcher configuration by setting the method, body, headers, and URL.\n * It also handles query parameters and path parameters. This fn mutates the passed `requestConfig` object.\n * @param {string} url - The endpoint URL to which the request will be sent.\n * @param {RequestConfig} requestConfig - The request configuration object containing method, body, headers, and other options.\n * @return {RequestConfig} - The modified request configuration object with the URL, method, body, and headers set appropriately.\n **/\nexport function buildFetcherConfig(\n url: string,\n requestConfig: RequestConfig,\n): RequestConfig {\n let method = requestConfig.method as Method;\n method = method ? (method.toUpperCase() as Method) : GET;\n\n let body: RequestConfig['data'] | undefined;\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (method !== GET && method !== HEAD) {\n body = requestConfig.body ?? requestConfig.data;\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (body && typeof body !== STRING && isJSONSerializable(body)) {\n body = JSON.stringify(body);\n }\n }\n\n setContentTypeIfNeeded(requestConfig.headers, body);\n\n // Native fetch compatible settings\n const credentials = requestConfig.withCredentials\n ? 'include'\n : requestConfig.credentials;\n\n // The explicitly passed query params\n const dynamicUrl = replaceUrlPathParams(url, requestConfig.urlPathParams);\n const urlPath = appendQueryParams(dynamicUrl, requestConfig.params);\n const isFullUrl = isAbsoluteUrl(url);\n const baseURL = isFullUrl\n ? ''\n : requestConfig.baseURL || requestConfig.apiUrl || '';\n\n // Join as a path, as plain concatenation could extend the host of the baseURL,\n // e.g. \"https://api.example.com\" + \".evil.com\" would point to another host\n const separator =\n baseURL && urlPath && !baseURL.endsWith('/') && !/^[/?#]/.test(urlPath)\n ? '/'\n : '';\n\n requestConfig.url = baseURL + separator + urlPath;\n requestConfig.method = method;\n requestConfig.credentials = credentials;\n requestConfig.body = body;\n\n return requestConfig;\n}\n\n/**\n * Ensures the `Content-Type` header is set to `application/json; charset=utf-8`\n * if it is not already present and the request method and body meet specific conditions.\n *\n * @param headers - The headers object to modify. Can be an instance of `Headers`\n * or a plain object conforming to `HeadersInit`.\n * @param body - The optional body of the request. If no body is provided and the\n * method is 'GET' or 'HEAD', the function exits without modifying headers.\n */\nfunction setContentTypeIfNeeded(\n headers?: HeadersInit | HeadersObject,\n body?: unknown,\n): void {\n // If no headers are provided, or if the body is not set and the method is PUT or DELETE, do nothing\n if (!headers || !body) {\n return;\n }\n\n // Types that should not have Content-Type set (browser handles these)\n if (\n body instanceof FormData || // Browser automatically sets multipart/form-data with boundary\n (typeof Blob !== UNDEFINED && body instanceof Blob) || // Blob/File already have their own MIME types, don't override\n (typeof File !== UNDEFINED && body instanceof File) ||\n (typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream) // Stream type should be determined by the stream source\n ) {\n return;\n }\n\n let contentTypeValue: string;\n\n if (isSearchParams(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded';\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'octet-stream';\n } else if (isJSONSerializable(body)) {\n contentTypeValue = APPLICATION_JSON + ';' + CHARSET_UTF_8;\n } else {\n // Do not set Content-Type if content is not recognizable\n return;\n }\n\n if (headers instanceof Headers) {\n if (!headers.has(CONTENT_TYPE)) {\n headers.set(CONTENT_TYPE, contentTypeValue);\n }\n } else if (\n isObject(headers) &&\n !Array.isArray(headers) &&\n // Header names are case-insensitive, so check the normalized (lowercase) headers\n !processHeaders(headers as HeadersObject)[CONTENT_TYPE.toLowerCase()]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\n/**\n * Merges two request configurations, applying overrides from the second config to the first.\n * Handles special merging for nested properties like 'retry' and 'headers' (deep merge),\n * and concatenates interceptor arrays for 'onRequest', 'onResponse', and 'onError'.\n * If a target config is provided, it mutates that object; otherwise, creates a new one.\n *\n * @param {RequestConfig} baseConfig - The base configuration object to merge from.\n * @param {RequestConfig} overrideConfig - The override configuration object to apply on top of the base.\n * @param {RequestConfig} [targetConfig={}] - Optional target configuration object to merge into (mutated in place).\n * @returns {RequestConfig} The merged configuration object.\n *\n * @example\n * const base = { timeout: 5000, headers: { 'Accept': 'application/json' } };\n * const override = { timeout: 10000, headers: { 'Authorization': 'Bearer token' } };\n * const merged = mergeConfigs(base, override);\n * // Result: { timeout: 10000, headers: { Accept: 'application/json', Authorization: 'Bearer token' } }\n */\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig = {},\n): RequestConfig {\n Object.assign(targetConfig, baseConfig, overrideConfig);\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', baseConfig, overrideConfig, targetConfig);\n mergeConfig('headers', baseConfig, overrideConfig, targetConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', baseConfig, overrideConfig, targetConfig);\n mergeInterceptors('onResponse', baseConfig, overrideConfig, targetConfig);\n mergeInterceptors('onError', baseConfig, overrideConfig, targetConfig);\n\n return targetConfig;\n}\n\n/**\n * Efficiently merges interceptor functions from base and new configs\n */\nfunction mergeInterceptors<\n K extends 'onRequest' | 'onResponse' | 'onError' | 'onRetry',\n>(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const baseInterceptor = baseConfig[property];\n const newInterceptor = overrideConfig[property];\n\n if (!baseInterceptor && !newInterceptor) {\n return;\n }\n\n if (!baseInterceptor) {\n targetConfig[property] = newInterceptor;\n return;\n }\n\n if (!newInterceptor) {\n targetConfig[property] = baseInterceptor;\n return;\n }\n\n const baseArr = Array.isArray(baseInterceptor)\n ? baseInterceptor\n : [baseInterceptor];\n const newArr = Array.isArray(newInterceptor)\n ? newInterceptor\n : [newInterceptor];\n\n // This is the only LIFO interceptor, so we apply it after the response is prepared\n targetConfig[property] =\n property === 'onResponse' ? newArr.concat(baseArr) : baseArr.concat(newArr);\n}\n\n/**\n * Merges the specified property from the base configuration and the override configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and override configurations. Must be a key of RequestConfig.\n * @param {RequestConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestConfig} overrideConfig - The override configuration object that contains user-specific settings to merge.\n * @param {RequestConfig} targetConfig - The configuration object that will receive the merged properties.\n */\nexport function mergeConfig(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n if (override) {\n if (property === 'headers') {\n // Handle Headers instances which don't expose entries as own enumerable properties\n const isInstance =\n (base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers;\n const merged: HeadersObject = isInstance\n ? processHeaders(base)\n : { ...(base as HeadersObject) };\n const overrides: HeadersObject = isInstance\n ? processHeaders(override)\n : sanitizeObject(override as HeadersObject);\n\n // Header names are case-insensitive, so replace existing entries instead of duplicating them\n for (const key of Object.keys(overrides)) {\n const lowerKey = key.toLowerCase();\n\n for (const existingKey in merged) {\n if (existingKey.toLowerCase() === lowerKey) {\n delete merged[existingKey];\n }\n }\n\n merged[key] = overrides[key];\n }\n\n targetConfig[property] = merged as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...sanitizeObject(override as Record),\n } as RequestConfig[K];\n }\n } else if (\n override === undefined &&\n isObject(base) &&\n !((base as Headers | HeadersObject) instanceof Headers)\n ) {\n // Copy so that mutating the merged config never changes the base config\n targetConfig[property] = { ...base } as RequestConfig[K];\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport type {\n CacheKeyFunction,\n DefaultResponse,\n FetchResponse,\n MutationSettings,\n RequestConfig,\n} from './types/request-handler';\nimport type { CacheEntry } from './types/cache-manager';\nimport { GET, STRING } from './constants';\nimport {\n isJSONSerializable,\n isObject,\n isSearchParams,\n sanitizeObject,\n sortObject,\n timeNow,\n} from './utils';\nimport { revalidate } from './revalidator-manager';\nimport { notifySubscribers } from './pubsub-manager';\nimport type { DefaultPayload, DefaultParams, DefaultUrlParams } from './types';\nimport { removeInFlight } from './inflight-manager';\nimport { addTimeout } from './timeout-wheel';\nimport { defaultConfig } from './config-handler';\nimport { processHeaders } from './utils';\n\nexport const IMMEDIATE_DISCARD_CACHE_TIME = 0; // Use it for cache entries that need to be persistent until unused by components or manually deleted\n\nconst _cache = new Map>();\nconst DELIMITER = '|';\nconst MIN_LENGTH_TO_HASH = 64;\nconst CACHE_KEY_SANITIZE_PATTERN = /[^\\w\\-_|/:@.?=&~%#]/g;\nconst CACHE_KEY_NEEDS_SANITIZE = /[^\\w\\-_|/:@.?=&~%#]/; // Non-global for fast test\n\n/**\n * Headers that may affect HTTP response content and should be included in cache key generation.\n * All header names must be lowercase to match normalized request headers.\n */\nconst CACHE_KEY_HEADER_WHITELIST = new Set([\n // Content negotiation\n 'accept', // Affects response format (e.g. JSON, HTML)\n 'accept-language', // Affects localization of the response\n 'accept-encoding', // Affects response compression (e.g. gzip, br)\n\n // Authentication\n 'authorization', // Affects access to protected resources\n\n // Request body metadata\n 'content-type', // Affects how the request body is interpreted\n\n // Optional headers\n 'referer', // May influence behavior in some APIs\n 'origin', // Relevant in CORS or tenant-specific APIs\n 'user-agent', // Included only for reason if server returns client-specific content\n\n // Cookies — only if server uses session-based responses\n 'cookie', // Can fragment cache heavily; use only if necessary\n\n // Custom headers that may affect response content\n 'x-api-key', // Token-based access, often affects authorization\n 'x-requested-with', // AJAX requests (used historically for distinguishing frontend calls)\n 'x-client-id', // Per-client/partner identity; often used in multi-tenant APIs\n 'x-tenant-id', // Multi-tenant segmentation; often changes response per tenant\n 'x-user-id', // Explicit user context (less common, but may exist)\n\n 'x-app-version', // Used for version-specific behavior (e.g. mobile apps)\n 'x-feature-flag', // Controls feature rollout behavior server-side\n 'x-device-id', // Used when response varies per device/app instance\n 'x-platform', // e.g. 'ios', 'android', 'web' — used in apps that serve different content\n\n 'x-session-id', // Only if backend uses it to affect the response directly (rare)\n 'x-locale', // Sometimes used in addition to or instead of `accept-language`\n]);\n\n/**\n * Generates a unique 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 {RequestConfig} config - 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 {RequestCredentials} [credentials=\"same-origin\"] - Whether to include credentials (include, same-origin, omit).\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @returns {string} - A unique cache key string based on the provided options.\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(\n config: RequestConfig,\n cacheKeyCheck = true,\n): string {\n // This is super fast. Effectively a no-op if cacheKey is\n // a string or a function that returns a string.\n const key = config.cacheKey;\n\n if (key && cacheKeyCheck) {\n return typeof key === STRING\n ? (key as string)\n : (key as CacheKeyFunction)(config);\n }\n\n const {\n url = '',\n method = GET,\n headers = null,\n body = null,\n credentials = 'same-origin',\n } = config;\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 let headersString = '';\n if (headers) {\n let obj: Record;\n\n if (headers instanceof Headers) {\n obj = processHeaders(headers);\n } else {\n obj = headers as Record;\n }\n\n // Filter headers to only include those that affect request identity\n // Include only headers that affect request identity, not execution behavior\n const keys = Object.keys(obj);\n const len = keys.length;\n\n // Sort keys manually for fastest deterministic output\n if (len > 1) {\n keys.sort();\n }\n\n let str = '';\n for (let i = 0; i < len; ++i) {\n if (CACHE_KEY_HEADER_WHITELIST.has(keys[i].toLowerCase())) {\n str += keys[i] + ':' + obj[keys[i]] + ';';\n }\n }\n\n headersString = hash(str);\n }\n\n // For GET requests, return early with shorter cache key\n if (method === GET) {\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString;\n\n return sanitizeCacheKey(cacheStr);\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING || isSearchParams(body)) {\n const str = String(body);\n\n bodyString = str.length < MIN_LENGTH_TO_HASH ? str : hash(str); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Files can't be read synchronously, so they are identified by their object\n bodyString +=\n key +\n '=' +\n (typeof value === STRING ? value : 'F' + getObjectId(value as File)) +\n '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (isObject(body) && !isJSONSerializable(body)) {\n // Blobs, buffers, streams etc. can't be read synchronously, so they are identified by their object.\n // Two different bodies never share a key, while the same body object is still deduplicated.\n bodyString = 'B' + getObjectId(body);\n } else {\n const o = isObject(body)\n ? JSON.stringify(sortObject(body))\n : String(body);\n\n bodyString = o.length > MIN_LENGTH_TO_HASH ? hash(o) : o;\n }\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString +\n DELIMITER +\n bodyString;\n\n return sanitizeCacheKey(cacheStr);\n}\n\nconst objectIds = new WeakMap();\nlet lastObjectId = 0;\n\n/**\n * Returns a unique id for an object, e.g. a request body that can't be serialized.\n *\n * @param {object} obj - The object to identify.\n * @returns {number} - The id of the object.\n */\nfunction getObjectId(obj: object): number {\n let id = objectIds.get(obj);\n\n if (!id) {\n objectIds.set(obj, (id = ++lastObjectId));\n }\n\n return id;\n}\n\n/**\n * Prevents cache poisoning by removal of control chars and unusual characters.\n * When anything is removed, a hash of the original key is appended so that keys\n * differing only in the removed characters (e.g. `?a[]=1` and `?a=1`) don't collide.\n *\n * @param {string} cacheStr - The raw cache key.\n * @returns {string} - The sanitized cache key.\n */\nfunction sanitizeCacheKey(cacheStr: string): string {\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '') +\n DELIMITER +\n hash(cacheStr)\n : cacheStr;\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the expiry time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(entry: CacheEntry): boolean {\n // No expiry time means the entry never expires\n if (!entry.expiry) {\n return false;\n }\n\n return timeNow() > entry.expiry;\n}\n\n/**\n * Retrieves a cached response from the internal cache using the provided key.\n *\n * @param key - The unique key identifying the cached entry. If null, returns null.\n * @returns The cached {@link FetchResponse} if found, otherwise null.\n */\nexport function getCacheData<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n key: string | null,\n): FetchResponse | null {\n if (!key) {\n return null;\n }\n\n const entry = _cache.get(key);\n\n return entry ? entry.data : null;\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 * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string | null,\n):\n | CacheEntry<\n FetchResponse\n >\n | null\n | undefined {\n return _cache.get(key as string);\n}\n\n/**\n * Sets a new cache entry or updates an existing one, with optional TTL (time-to-live).\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {number} [ttl] - Optional TTL in seconds. If not provided, the cache entry will not expire.\n * @param {number} [staleTime] - Optional stale time in seconds. If provided, the cache entry will be considered stale after this time.\n */\nexport function setCache(\n key: string,\n data: T,\n ttl?: number,\n staleTime?: number,\n): void {\n if (ttl === 0) {\n deleteCache(key);\n return;\n }\n\n const time = timeNow();\n const ttlMs = ttl ? ttl * 1000 : 0;\n const staleTimeMs = staleTime ? staleTime * 1000 : 0; // Ensure default value for staleTime\n\n _cache.set(key, {\n data,\n time,\n stale: staleTimeMs > 0 ? time + staleTimeMs : undefined, // Use undefined if staleTime is not set\n expiry: ttl === -1 ? undefined : time + ttlMs,\n });\n\n if (ttlMs > 0) {\n addTimeout(\n 'c:' + key,\n () => {\n deleteCache(key, true);\n },\n ttlMs,\n );\n }\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n * @param {boolean} [removeExpired=false] - If true, only deletes the cache entry if it is expired or stale.\n */\nexport function deleteCache(key: string, removeExpired: boolean = false): void {\n if (removeExpired) {\n const entry = getCache(key);\n\n // If the entry does not exist, or it is neither expired nor stale, do not delete\n if (!entry || !isCacheExpired(entry)) {\n return;\n }\n }\n\n _cache.delete(key);\n}\n\n/**\n * Prunes the cache by removing entries that have expired based on the provided cache time.\n */\nexport function pruneCache(): void {\n _cache.clear();\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string | null} key Cache key to utilize. If null, no mutation occurs.\n * @param {ResponseData} newData - The new data to be cached.\n * @param {MutationSettings|undefined} settings - Mutation settings.\n */\nexport async function mutate<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n key: string | null,\n newData: ResponseData,\n settings?: MutationSettings,\n): Promise | null> {\n // If no key is provided, do nothing\n if (!key) {\n return null;\n }\n\n const entry = getCache(\n key,\n );\n\n if (!entry) {\n return null;\n }\n\n const updatedData = isObject(newData) ? sanitizeObject(newData) : newData;\n\n const updatedResponse = {\n ...entry.data,\n data: updatedData,\n };\n\n const updatedEntry = {\n ...entry,\n data: updatedResponse,\n };\n\n _cache.set(key, updatedEntry);\n notifySubscribers(key, updatedResponse);\n\n if (settings && settings.refetch) {\n return await revalidate(key);\n }\n\n return null;\n}\n\n/**\n * Retrieves a cached response if available and valid, otherwise returns null.\n *\n * @template ResponseData - The type of the response data.\n * @template RequestBody - The type of the request body.\n * @template QueryParams - The type of the query parameters.\n * @template PathParams - The type of the path parameters.\n * @param {string | null} cacheKey - The cache key to look up.\n * @param {number | undefined} cacheTime - The maximum time to cache entry.\n * @param {RequestConfig} requestConfig - The fetcher configuration.\n * @returns {FetchResponse | null} - The cached response or null.\n */\nexport function getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n cacheKey: string | null,\n cacheTime: number | undefined,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): FetchResponse | null {\n // If cache key or time is not provided, return null\n if (!cacheKey || cacheTime === undefined || cacheTime === null) {\n return null;\n }\n\n // Check if cache should be bypassed\n const buster = requestConfig.cacheBuster || defaultConfig.cacheBuster;\n if (buster && buster(requestConfig)) {\n return null;\n }\n\n if (requestConfig.cache && requestConfig.cache === 'reload') {\n return null; // Skip cache lookup entirely\n }\n\n // Retrieve the cached entry\n const entry = getCache(\n cacheKey,\n );\n\n if (!entry) {\n return null;\n }\n\n const isExpired = isCacheExpired(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n const data = entry.data;\n\n // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n // The placeholder stored while a request is in flight is not a response, so treat it as a miss\n return data && data.isFetching ? null : data;\n}\n\n/**\n * Sets or deletes the response cache based on cache settings and notifies subscribers.\n *\n * @param {FetchResponse} output - The response to cache.\n * @param {RequestConfig} requestConfig - The request configuration.\n * @param {boolean} [isError=false] - Whether the response is an error.\n */\nexport function handleResponseCache<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n output: FetchResponse,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n isError: boolean = false,\n): void {\n // It is string as it is called once request is made\n const cacheKey = requestConfig.cacheKey as string;\n\n if (cacheKey) {\n const cacheTime = requestConfig.cacheTime;\n const skipCache = requestConfig.skipCache;\n\n // Fast path: only set cache if cacheTime is positive and not skipping cache\n if (\n cacheTime &&\n (!isError || requestConfig.cacheErrors) &&\n !(skipCache && skipCache(output, requestConfig))\n ) {\n setCache(cacheKey, output, cacheTime, requestConfig.staleTime);\n } else {\n const entry = getCache(cacheKey);\n\n // Don't let the in-flight placeholder outlive a request whose result isn't cached\n if (entry && entry.data && entry.data.isFetching) {\n deleteCache(cacheKey);\n }\n }\n\n notifySubscribers(cacheKey, output);\n removeInFlight(cacheKey);\n\n const prevCacheKey = requestConfig._prevKey;\n\n if (prevCacheKey) {\n removeInFlight(prevCacheKey);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { mutate } from './cache-manager';\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n FUNCTION,\n OBJECT,\n STRING,\n} from './constants';\nimport {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n ResponseError,\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n} from './types';\nimport { flattenData, isObject, processHeaders } from './utils';\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 ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse,\n): Promise {\n // Bail early if response is null or undefined\n if (!response) {\n return null;\n }\n\n // Get the content-type header once\n let contentType = (response as Response).headers?.get(CONTENT_TYPE);\n\n if (contentType) {\n // Lowercase and trim for consistent matching\n contentType = contentType.toLowerCase().trim();\n } else {\n contentType = '';\n }\n\n // Split for mime type without charset\n const mimeType = contentType.split(';', 1)[0];\n\n let data;\n\n try {\n if (mimeType.includes(APPLICATION_JSON) || mimeType.includes('+json')) {\n data = await response.json(); // Parse JSON response\n } else if (\n (mimeType.includes('multipart/form-data') || // Parse as FormData\n mimeType.includes(\n APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded', // Handle URL-encoded forms\n )) &&\n typeof response.formData === FUNCTION\n ) {\n data = await response.formData();\n } else if (/^(image|video|audio)\\/|octet-stream|pdf|zip/.test(mimeType)) {\n data = await response.arrayBuffer(); // Parse as ArrayBuffer for binary types\n } else {\n data = await response.text();\n\n if (typeof data === STRING) {\n const trimmed = data.trim();\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n data = JSON.parse(trimmed);\n } catch {\n // leave as text if parsing fails\n }\n }\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\n/**\n * Prepare response object with additional information.\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} config - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\nexport const prepareResponse = <\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n config: RequestConfig,\n error: ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null,\n): FetchResponse => {\n const defaultResponse = config.defaultResponse;\n const cacheKey = config.cacheKey;\n const mutatator = mutate.bind(null, cacheKey as string) as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >['mutate'];\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 ?? null,\n headers: null,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: false,\n isError: true,\n } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n const isNativeResponse =\n typeof Response === FUNCTION && response instanceof Response;\n\n let data = response.data;\n\n // Set the default response if the provided data is an empty object\n if (\n defaultResponse !== undefined &&\n (data === undefined ||\n data === null ||\n (typeof data === OBJECT && Object.keys(data).length === 0))\n ) {\n response.data = data = defaultResponse;\n }\n\n if (config.flattenResponse) {\n response.data = data = flattenData(data);\n }\n\n if (config.select) {\n response.data = data = config.select(data);\n }\n\n const headers = processHeaders(response.headers);\n\n // Native fetch Response extended by extra information\n if (isNativeResponse) {\n const output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > = {\n body: response.body,\n bodyUsed: response.bodyUsed,\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 // Convert methods to use arrow functions to preserve correct return types\n blob: () =>\n Promise.resolve(\n data instanceof ArrayBuffer ? new Blob([data]) : new Blob(),\n ), // Lazily construct Blob from ArrayBuffer\n json: () => Promise.resolve(data as ResponseData), // Return the already parsed JSON data\n text: () => Promise.resolve(data as string), // Return the already parsed text data\n // The body was already read, so a copy of this response is returned instead of Response.clone()\n clone: () => ({ ...output }),\n arrayBuffer: () =>\n Promise.resolve(\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0),\n ), // Return the ArrayBuffer directly\n formData: () =>\n Promise.resolve(data instanceof FormData ? data : new FormData()), // Return the already parsed FormData\n bytes: () =>\n Promise.resolve(\n new Uint8Array(\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0),\n ),\n ),\n // Enhance the response with extra information\n error,\n data,\n headers,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: response.ok && !error,\n isError: !!error,\n };\n\n return output;\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 (isObject(response)) {\n response.error = error;\n response.headers = headers;\n response.isFetching = false;\n response.mutate = mutatator;\n response.isSuccess = response.ok && !error;\n response.isError = !!error;\n }\n\n return response;\n};\n","import { applyInterceptors } from './interceptor-manager';\nimport type { FetchResponse, RetryConfig, RetryFunction } from './types';\nimport { delayInvocation, timeNow } from './utils';\nimport { generateCacheKey } from './cache-manager';\n\nfunction getMsFromHttpDate(dateString: string): number | null {\n const ms = Date.parse(dateString) - timeNow();\n\n if (!isNaN(ms)) {\n return Math.max(0, Math.floor(ms));\n }\n return null;\n}\n\n/**\n * Calculates the number of milliseconds to wait before retrying a request,\n * based on the `Retry-After` HTTP header in the provided response.\n *\n * The function supports both numeric (seconds) and HTTP-date formats for the `Retry-After` header.\n * - If the header is a number, it is interpreted as seconds and converted to milliseconds.\n * - If the header is a date, the function calculates the difference between the date and the current time.\n *\n * @param extendedResponse - The response object containing headers, or `null`.\n * @returns The number of milliseconds to wait before retrying, or `null` if the header is not present or invalid.\n */\nexport function getRetryAfterMs(\n extendedResponse: FetchResponse | null,\n): number | null {\n if (!extendedResponse) {\n return null;\n }\n\n const headers = extendedResponse.headers || {};\n const retryAfter = headers['retry-after'];\n\n if (retryAfter) {\n // Try parsing as seconds\n const seconds = Number(retryAfter);\n\n if (!isNaN(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n const ms = getMsFromHttpDate(retryAfter);\n\n if (ms !== null) {\n return ms;\n }\n }\n\n // Headers are already in lowercase\n const RATELIMIT_RESET = 'ratelimit-reset';\n\n // Unix timestamp when the rate limit window resets (relative to current time)\n // Fallback to checking 'ratelimit-reset-after' OR 'x-ratelimit-reset-after' headers\n const rateLimitResetAfter =\n headers[RATELIMIT_RESET + '-after'] ||\n headers['x-' + RATELIMIT_RESET + '-after'];\n\n if (rateLimitResetAfter) {\n const seconds = Number(rateLimitResetAfter);\n\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n }\n\n // ISO 8601 datetime when the rate limit resets\n // Fallback to checking 'ratelimit-reset-at' 'x-ratelimit-reset-at' headers\n const rateLimitResetAt =\n headers[RATELIMIT_RESET + '-at'] || headers['x-' + RATELIMIT_RESET + '-at'];\n\n if (rateLimitResetAt) {\n return getMsFromHttpDate(rateLimitResetAt);\n }\n\n return null;\n}\n\n/**\n * Executes a request function with retry logic according to the provided configuration.\n *\n * The function attempts the request up to the specified number of retries, applying delay and backoff strategies.\n * Retries can be triggered based on response status codes, custom logic, or the presence of a `Retry-After` header.\n * Optionally, an `onRetry` interceptor can be invoked before each retry attempt.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param requestFn - The function that performs the request. Receives `isStaleRevalidation` and `attempt` as arguments.\n * @param config - The retry configuration, including retry count, delay, backoff, retry conditions, and hooks.\n * @returns A promise resolving to the fetch response, or rejecting if all retries are exhausted.\n * @throws Error if the maximum number of retries is exceeded or a non-retriable error occurs.\n */\nexport async function withRetry<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation: boolean,\n attempt: number,\n ) => Promise<\n FetchResponse\n >,\n config: RetryConfig,\n): Promise> {\n const {\n retries = 0,\n delay = 0,\n backoff = 1,\n maxDelay,\n retryOn = [],\n shouldRetry,\n } = config;\n\n let attempt = 0;\n let waitTime = delay;\n const maxRetries = retries > 0 ? retries : 0;\n let output: FetchResponse;\n\n while (attempt <= maxRetries) {\n // Subsequent attempts will have output defined, but the first attempt may not.\n // Let's apply onRetry interceptor and regenerate cache key if ot really changes.\n if (attempt > 0 && output!) {\n const cfg = output.config;\n const onRetry = cfg.onRetry;\n\n if (onRetry) {\n await applyInterceptors(onRetry, output, attempt);\n\n // If the key was automatically generated, we need to regenerate it as config may change.\n // We don't detect whether config changed for performance reasons.\n if (cfg._isAutoKey) {\n cfg._prevKey = cfg.cacheKey as string;\n cfg.cacheKey = generateCacheKey(cfg, false);\n }\n }\n }\n\n // Performance optimization: Call the request function with the current attempt number\n // If this is the first attempt, we pass `isStaleRevalidation` as `false`,\n // otherwise we pass `true` to indicate that this is a stale revalidation (no cache hit).\n output = await requestFn(attempt > 0, attempt);\n const error = output.error;\n\n // Check if we should retry based on successful response\n if (!error) {\n if (shouldRetry && attempt < maxRetries) {\n const shouldRetryResult = await shouldRetry(output, attempt);\n\n if (shouldRetryResult) {\n await delayInvocation(waitTime);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n continue;\n }\n }\n\n break;\n }\n\n // Determine if we should stop retrying\n const shouldStopRetrying = await getShouldStopRetrying(\n output,\n attempt,\n maxRetries,\n shouldRetry,\n retryOn,\n );\n\n if (shouldStopRetrying) {\n break;\n }\n\n // If we should not stop retrying, continue to the next attempt\n // Handle rate limiting if the error status is 429 (Too Many Requests) or 503 (Service Unavailable)\n if (error.status === 429 || error.status === 503) {\n // Try to extract the \"Retry-After\" value from the response headers\n const retryAfterMs = getRetryAfterMs(output);\n\n // If a valid retry-after value is found, override the wait time before next retry\n // Cap it with maxDelay so that a server can't make the client wait indefinitely\n if (retryAfterMs !== null) {\n waitTime = Math.min(retryAfterMs, maxDelay || retryAfterMs);\n }\n }\n\n await delayInvocation(waitTime);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n }\n\n return output!;\n}\n\n/**\n * Determines whether to stop retrying based on the error, current attempt count, and retry configuration.\n *\n * This function checks:\n * - If the maximum number of retries has been reached.\n * - If a custom `shouldRetry` callback is provided, its result is used to decide.\n * - If no custom logic is provided, falls back to checking if the error status is included in the `retryOn` list.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param output - The response object containing the error and request configuration.\n * @param attempt - The current retry attempt number.\n * @param maxRetries - The maximum number of retry attempts allowed.\n * @param shouldRetry - Optional custom function to determine if a retry should occur.\n * @param retryOn - Optional list of HTTP status codes that should trigger a retry.\n * @returns A promise resolving to `true` if retrying should stop, or `false` to continue retrying.\n */\nexport async function getShouldStopRetrying<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n output: FetchResponse,\n attempt: number,\n maxRetries: number,\n shouldRetry?: RetryFunction<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n retryOn: number[] = [],\n): Promise {\n // Safety first: always respect max retries\n // We check retries provided regardless of the shouldRetry being provided so to avoid infinite loops.\n // It is a fail-safe so to prevent excessive retry attempts even if custom retry logic suggests a retry.\n if (attempt === maxRetries) {\n return true;\n }\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n\n if (result !== null) {\n return !result;\n }\n }\n\n return !(retryOn || []).includes(output.error?.status ?? 0);\n}\n","import type { RequestConfig, FetchResponse } from './types';\nimport { delayInvocation } from './utils';\n\n/**\n * Executes a request function with polling, stopping when shouldStopPolling returns true,\n * pollingInterval is not set, or maxAttempts is reached.\n *\n * @template Output The type of the output returned by the request function.\n * @param requestFn - The function that performs a single request (with retries).\n * @param pollingInterval - Interval in ms between polling attempts.\n * @param shouldStopPolling - Function to determine if polling should stop.\n * @param maxAttempts - Maximum number of polling attempts, default: 0 (unlimited).\n * @param pollingDelay - Delay in ms before each polling attempt, default: 0.\n * @returns The final output from the last request.\n */\nexport async function withPolling<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation?: boolean,\n attempt?: number,\n ) => Promise<\n FetchResponse\n >,\n pollingInterval?: RequestConfig['pollingInterval'],\n shouldStopPolling?: RequestConfig['shouldStopPolling'],\n maxAttempts = 0,\n pollingDelay = 0,\n): Promise> {\n if (!pollingInterval) {\n return requestFn();\n }\n\n let pollingAttempt = 0;\n let output: FetchResponse;\n\n while (maxAttempts === 0 || pollingAttempt < maxAttempts) {\n if (pollingDelay > 0) {\n await delayInvocation(pollingDelay);\n }\n\n output = await requestFn();\n\n pollingAttempt++;\n\n if (\n (maxAttempts > 0 && pollingAttempt >= maxAttempts) ||\n !pollingInterval ||\n (shouldStopPolling && shouldStopPolling(output, pollingAttempt))\n ) {\n break;\n }\n\n await delayInvocation(pollingInterval);\n }\n\n return output!;\n}\n","import type { ResponseError } from './errors/response-error';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n} from './types/request-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { handleResponseCache } from './cache-manager';\nimport { ABORT_ERROR, REJECT } from './constants';\nimport {\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n HeadersObject,\n} from './types';\nimport { processHeaders } from './utils';\n\n/**\n * Handles final processing for both success and error responses\n * Applies error interceptors, caching, notifications, and error strategy\n */\nexport async function withErrorHandling<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n isStaleRevalidation: boolean,\n requestFn: (\n isStaleRevalidation: boolean,\n ) => Promise<\n FetchResponse\n >,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): Promise> {\n const output = await requestFn(isStaleRevalidation);\n const error = output.error;\n\n if (!error) {\n // SUCCESS PATH\n handleResponseCache(output, requestConfig);\n\n return output;\n }\n\n // ERROR PATH\n\n if (requestConfig.onError) {\n await applyInterceptors(requestConfig.onError, error);\n }\n\n // Timeouts and request cancellations using AbortController do not throw any errors unless rejectCancelled is true.\n // Only handle the error if the request was not cancelled, or if it was cancelled and rejectCancelled is true.\n const isCancelled = error.isCancelled;\n\n if (!isCancelled && requestConfig.logger?.warn) {\n requestConfig.logger.warn(\n 'FETCH ERROR',\n redactError(error as ResponseError),\n );\n }\n\n // The defaultResponse strategy returns the default response in place of the error data.\n // The original data stays available through error.response.\n if (requestConfig.strategy === 'defaultResponse') {\n output.data = (requestConfig.defaultResponse ?? null) as typeof output.data;\n }\n\n // Handle cache and notifications FIRST (before strategy)\n handleResponseCache(output, requestConfig, true);\n\n // handle error strategy as the last part\n const shouldHandleError = !isCancelled || requestConfig.rejectCancelled;\n\n if (shouldHandleError) {\n const strategy = requestConfig.strategy;\n // Reject the promise\n if (strategy === REJECT) {\n return Promise.reject(error);\n }\n\n // Hang the promise\n if (strategy === 'silent') {\n await new Promise(() => null);\n }\n }\n\n return output;\n}\n\n// Credential headers that must not end up in logs\nconst SENSITIVE_HEADERS = [\n 'authorization',\n 'proxy-authorization',\n 'cookie',\n 'x-api-key',\n];\n\n/**\n * Creates a copy of the error for logging, with credential headers masked and the request body removed.\n * The error itself is left untouched.\n */\nfunction redactError(error: ResponseError): ResponseError {\n // Cache keys are dropped too, as they can contain short request bodies\n const config = {\n ...error.config,\n body: undefined,\n data: undefined,\n cacheKey: undefined,\n _prevKey: undefined,\n headers: processHeaders(error.config.headers as HeadersObject),\n };\n\n for (const name of SENSITIVE_HEADERS) {\n if (config.headers[name]) {\n config.headers[name] = '[REDACTED]';\n }\n }\n\n const copy = Object.assign(new Error(error.message), error, {\n config,\n request: config,\n response: error.response && { ...error.response, config },\n });\n\n copy.name = error.name;\n copy.stack = error.stack;\n\n return copy;\n}\n\nexport function enhanceError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): void {\n error.status = error.status || response?.status || 0;\n error.statusText = error.statusText || response?.statusText || '';\n error.config = error.request = requestConfig;\n error.response = response;\n error.isCancelled = error.name === ABORT_ERROR;\n}\n","import type {\n DefaultResponse,\n RequestConfig,\n FetchResponse,\n} from './types/request-handler';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n} from './types/api-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { ResponseError } from './errors/response-error';\nimport { isObject } from './utils';\nimport {\n markInFlight,\n setInFlightPromise,\n getInFlightPromise,\n} from './inflight-manager';\nimport { parseResponseData, prepareResponse } from './response-parser';\nimport { generateCacheKey, getCachedResponse, setCache } from './cache-manager';\nimport { withRetry } from './retry-handler';\nimport { withPolling } from './polling-handler';\nimport { notifySubscribers } from './pubsub-manager';\nimport { addRevalidator } from './revalidator-manager';\nimport { enhanceError, withErrorHandling } from './error-handler';\nimport { FUNCTION } from './constants';\nimport { buildConfig } from './config-handler';\n\nconst inFlightResponse = Object.freeze({\n isFetching: true,\n});\n\n/**\n * Sends an HTTP request to the specified URL using the provided configuration and returns a typed response.\n *\n * @typeParam ResponseData - The expected shape of the response data. Defaults to `DefaultResponse`.\n * @typeParam RequestBody - The type of the request payload/body. Defaults to `DefaultPayload`.\n * @typeParam QueryParams - The type of the query parameters. Defaults to `DefaultParams`.\n * @typeParam PathParams - The type of the path parameters. Defaults to `DefaultUrlParams`.\n *\n * @param url - The endpoint URL to which the request will be sent.\n * @param config - Optional configuration object for the request, including headers, method, body, query, and path parameters.\n *\n * @returns A promise that resolves to a `FetchResponse` containing the typed response data and request metadata.\n *\n * @example\n * ```typescript\n * const { data } = await fetchf('/api/user', { method: 'GET' });\n * console.log(data);\n * ```\n */\nexport async function fetchf<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n): Promise> {\n // Ultra-fast early cache check if cacheKey is provided as a string\n // For workloads dominated by repeated requests, this string caching optimization\n // can potentially support millions of requests per second with minimal CPU overhead\n if (reqConfig && typeof reqConfig.cacheKey === 'string') {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(reqConfig.cacheKey, reqConfig.cacheTime, reqConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n const fetcherConfig = buildConfig<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(url, reqConfig);\n\n const {\n timeout,\n cancellable,\n cacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n refetchOnFocus,\n refetchOnReconnect,\n pollingInterval = 0,\n } = fetcherConfig;\n const isCacheEnabled = cacheTime !== undefined || staleTime !== undefined;\n\n const needsCacheKey = !!(\n cacheKey ||\n timeout ||\n dedupeTime ||\n isCacheEnabled ||\n cancellable ||\n refetchOnFocus ||\n refetchOnReconnect\n );\n\n let _cacheKey: string | null = null;\n\n // Generate cache key if required\n if (needsCacheKey) {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n // Cache handling logic\n if (_cacheKey && isCacheEnabled) {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(_cacheKey, cacheTime, fetcherConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n // Deduplication logic\n if (_cacheKey && dedupeTime) {\n const inflight = getInFlightPromise<\n FetchResponse\n >(_cacheKey, dedupeTime);\n\n if (inflight) {\n return inflight;\n }\n }\n\n const retryConfig = fetcherConfig.retry || {};\n const { retries = 0, resetTimeout } = retryConfig;\n\n // The actual request logic as a function (one poll attempt, with retries)\n const doRequestOnce = async (isStaleRevalidation: boolean, attempt = 0) => {\n // If cache key is specified, we will handle optimistic updates\n // and mark the request as in-flight, so to catch \"fetching\" state.\n // This is useful for Optimistic UI updates (e.g., showing loading spinners).\n if (!attempt) {\n if (_cacheKey && !isStaleRevalidation) {\n if (staleTime) {\n const existingCache = getCachedResponse(\n _cacheKey,\n cacheTime,\n fetcherConfig,\n );\n\n // Don't notify subscribers when cache exists\n // Let them continue showing stale data during background revalidation\n if (!existingCache) {\n setCache(_cacheKey, inFlightResponse, cacheTime, staleTime);\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n } else {\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n }\n\n // Attach cache key so that it can be reused in interceptors or in the final response\n fetcherConfig.cacheKey = _cacheKey;\n }\n\n const url = fetcherConfig.url as string;\n\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = markInFlight(\n _cacheKey,\n url,\n timeout,\n dedupeTime || 0,\n !!cancellable,\n // Enable timeout either by default or when retries & resetTimeout are enabled\n !!(timeout && (!attempt || resetTimeout)),\n );\n\n // Do not create a shallow copy to maintain idempotency here.\n // This ensures the original object is mutated by interceptors whenever needed, including retry logic.\n const requestConfig = fetcherConfig;\n\n requestConfig.signal = controller.signal;\n\n let output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n let response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n try {\n if (fetcherConfig.onRequest) {\n // Zero-allocation yield to microtask queue so the outer fetchf() can call setInFlightPromise()\n // before onRequest interceptors run. This ensures that if onRequest triggers\n // another fetchf() with the same cacheKey, getInFlightPromise() finds item[4].\n // On retries (attempt > 0), setInFlightPromise() was already called during the first attempt.\n // The promise stored in item[4] is the outer doRequestPromise which covers all retries.\n // So the race only matters on the very first attempt when the outer scope hasn't had a chance to call setInFlightPromise() yet.\n if (_cacheKey && dedupeTime && !attempt) {\n await null;\n }\n\n await applyInterceptors(fetcherConfig.onRequest, requestConfig);\n }\n\n // Custom fetcher\n const fn = fetcherConfig.fetcher;\n\n response = (fn\n ? await fn(\n url,\n requestConfig,\n )\n : await fetch(\n url,\n requestConfig as RequestInit,\n )) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Custom fetcher may return a raw data object instead of a Response instance\n if (isObject(response)) {\n // Case 1: Native Response instance\n if (typeof Response === FUNCTION && response instanceof Response) {\n response.data = requestConfig.parser\n ? await requestConfig.parser(response)\n : await parseResponseData(response);\n } else if (fn) {\n // Case 2: Custom fetcher that returns a response object\n if (!('data' in response && 'body' in response)) {\n // Case 3: Raw data, wrap it\n response = { data: response } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n }\n\n // Attach config and data to the response\n // This is useful for custom fetchers that do not return a Response instance\n // and for interceptors that may need to access the request config\n response.config = requestConfig;\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n // This is the pattern for fetch responses as per spec, but custom fetchers may not follow it so we check for `ok` property\n if (response.ok !== undefined && !response.ok) {\n throw new ResponseError(\n requestConfig.method +\n ' to ' +\n url +\n ' failed! Status: ' +\n (response.status || null),\n requestConfig,\n response,\n );\n }\n }\n\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig);\n\n const onResponse = fetcherConfig.onResponse;\n\n if (onResponse) {\n await applyInterceptors(onResponse, output);\n }\n } catch (_error) {\n const error = _error as ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Append additional information to Network, CORS or any other fetch() errors\n enhanceError(\n error,\n response,\n requestConfig,\n );\n\n // Prepare Extended Response\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig, error);\n }\n\n return output;\n };\n\n // Inline and minimize function wrappers for performance\n // When retries are enabled, forward isStaleRevalidation so the first attempt\n // of a background SWR revalidation doesn't incorrectly mark the request as in-flight\n const baseRequest =\n retries > 0\n ? (isStaleRevalidation: boolean) =>\n withRetry(\n (_, attempt) => doRequestOnce(isStaleRevalidation, attempt),\n retryConfig,\n )\n : doRequestOnce;\n\n const requestWithErrorHandling = (isStaleRevalidation = false) =>\n withErrorHandling(\n isStaleRevalidation,\n baseRequest,\n fetcherConfig,\n );\n\n // Avoid unnecessary function wrapping if polling is not enabled\n const doRequestPromise = pollingInterval\n ? withPolling(\n requestWithErrorHandling,\n pollingInterval,\n fetcherConfig.shouldStopPolling,\n fetcherConfig.maxPollingAttempts,\n fetcherConfig.pollingDelay,\n )\n : requestWithErrorHandling();\n\n // If deduplication is enabled, store the in-flight promise immediately\n if (_cacheKey) {\n if (dedupeTime) {\n setInFlightPromise(_cacheKey, doRequestPromise);\n }\n\n // Only register revalidator when revalidation features are actually requested\n if (staleTime || refetchOnFocus || refetchOnReconnect) {\n addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\n );\n }\n }\n\n return doRequestPromise;\n}\n","import type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n RequestConfigUrlRequired,\n} from './types/api-handler';\nimport { fetchf } from '.';\nimport { mergeConfigs } from './config-handler';\nimport { hasOwn } from './utils';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if passed as \"fetcher\".\n * @see https://github.com/MattCCC/fetchff#configuration\n *\n * @param {Object} config - Configuration object for the API fetcher (see link above for full options).\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {string} [config.baseURL] - The base URL for the API.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\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 EndpointTypes extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\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 const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\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 endpointName - The name of the API endpoint to call.\n * @param requestConfig - Additional configuration for the request.\n * @returns A promise that resolves with the response from the API provider.\n */\n async request(endpointName, requestConfig = {}) {\n // Use global and per-endpoint settings\n // Only own properties are endpoints, not ones inherited like \"constructor\"\n const endpointConfig = hasOwn(endpoints, endpointName as string)\n ? endpoints[endpointName]\n : undefined;\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // URL parsers ignore leading control characters and spaces, drop tabs and newlines,\n // and treat backslashes like slashes, so check the URL the way it will be resolved\n const resolvedUrl = url\n .replace(/[\\t\\n\\r]/g, '')\n // eslint-disable-next-line no-control-regex -- matching control characters is the point\n .replace(/^[\\x00-\\x20]+/, '');\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (/^[/\\\\]{2}/.test(resolvedUrl)) {\n throw new Error('Protocol-relative URLs not allowed.');\n }\n\n // Prevent potential Server-Side Request Forgery attack and leakage of credentials when same instance is used for external requests\n // Any scheme counts here, as e.g. \"http:\\\\host\" or \"http:host\" can also point to another host\n const mergedConfig = /^[a-z][a-z\\d+\\-.]*:/i.test(resolvedUrl)\n ? // Merge endpoints configs for absolute URLs only if urls match\n endpointConfig?.url === url\n ? mergeConfigs(_endpointConfig, requestConfig)\n : requestConfig\n : mergeConfigs(mergeConfigs(config, _endpointConfig), requestConfig);\n\n // We prevent potential Server-Side Request Forgery attack and leakage of credentials as the same instance is not used for external requests\n // Retrigger fetch to ensure completely new instance of handler being triggered for external URLs\n return fetchf(url, mergedConfig);\n },\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 | symbol) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Symbols (e.g. inspection hooks) are never endpoints, and returning a function\n // for \"then\" would make the instance a thenable that never settles when awaited\n if (typeof prop === 'symbol' || prop === 'then') {\n return undefined;\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (hasOwn(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"]} \ No newline at end of file +{"version":3,"sources":["../../src/constants.ts","../../src/utils.ts","../../src/interceptor-manager.ts","../../src/errors/fetch-error.ts","../../src/errors/response-error.ts","../../src/timeout-wheel.ts","../../src/inflight-manager.ts","../../src/hash.ts","../../src/revalidator-manager.ts","../../src/pubsub-manager.ts","../../src/config-handler.ts","../../src/cache-manager.ts","../../src/response-parser.ts","../../src/retry-handler.ts","../../src/polling-handler.ts","../../src/upload-progress.ts","../../src/download-progress.ts","../../src/error-handler.ts","../../src/request-handler.ts","../../src/api-handler.ts"],"names":["APPLICATION_CONTENT_TYPE","APPLICATION_JSON","CHARSET_UTF_8","CONTENT_TYPE","UNDEFINED","OBJECT","STRING","FUNCTION","ABORT_ERROR","TIMEOUT_ERROR","GET","HEAD","REJECT","MAX_DELAY_MS","MAX_DEPTH","hasOwn","o","k","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","key","sortObject","sortedObj","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","v","buildParams","prefix","depth","i","len","replaceUrlPathParams","urlPathParams","match","colonKey","braceKey","encoded","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","signal","resolve","done","timer","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","isPageHidden","isOffline","applyInterceptors","interceptors","args","merge","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","wheel","keyMap","position","lastTick","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","now","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","customEventProviders","setEventProvider","type","provider","removeEventHandler","addEventHandler","revalidateAll","isStaleRevalidation","isThrottled","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeRevalidator","event","handler","customProvider","cleanup","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","focusThrottleInterval","listeners","addListener","fn","set","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","merged","buildFetcherConfig","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","separator","contentTypeValue","INTERCEPTORS","baseConfig","overrideConfig","targetConfig","mergeConfig","property","mergeInterceptors","baseInterceptor","newInterceptor","base","override","isInstance","overrides","lowerKey","existingKey","_cache","stores","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADERS","generateCacheKey","config","cacheKeyCheck","headersString","keys","cacheStr","sanitizeCacheKey","bodyString","getObjectId","objectIds","lastObjectId","id","isCacheExpired","getCacheData","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","scheduleExpiry","removeExpired","store","callStore","persistCache","status","statusText","getStoredCache","isCacheBypassed","restoreCache","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","buster","getCachedResponse","cacheKey","cacheTime","handleResponseCache","output","isError","skipCache","prevCacheKey","parseResponseData","responseType","contentType","mimeType","trimmed","prepareResponse","defaultResponse","mutatator","isNativeResponse","getMsFromHttpDate","dateString","getRetryAfterMs","extendedResponse","retryAfter","RATELIMIT_RESET","rateLimitResetAfter","rateLimitResetAt","withRetry","requestFn","retries","delay","backoff","maxDelay","retryOn","shouldRetry","jitter","methods","attempt","waitTime","maxRetries","cfg","onRetry","getShouldStopRetrying","retryDelay","withJitter","retryAfterMs","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","refreshWhenHidden","refreshWhenOffline","pollingAttempt","NULL_BODY_STATUSES","FORBIDDEN_HEADERS","isStream","toProgress","loaded","total","fetchWithUploadProgress","sendWithXhr","sendStreamed","reject","xhr","abort","settle","line","index","onAbort","stream","blob","chunk","withDownloadProgress","onDownloadProgress","counted","withErrorHandling","isCancelled","logger","redactError","strategy","SENSITIVE_HEADERS","copy","enhanceError","inFlightResponse","fetchf","cached","fetcherConfig","cancellable","isCacheEnabled","isETagEnabled","needsCacheKey","_cacheKey","initialResponse","stored","restored","toResponse","inflight","retryConfig","resetTimeout","userSignal","doRequestOnce","init","withETag","onResponse","_error","baseRequest","_","onLoadingSlow","loadingTimeout","requestWithErrorHandling","doRequestPromise","etag","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","resolvedUrl","mergedConfig","_target","prop"],"mappings":"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","file":"index.js","sourcesContent":["export const APPLICATION_CONTENT_TYPE = 'application/';\n\nexport const APPLICATION_JSON = APPLICATION_CONTENT_TYPE + 'json';\nexport const CHARSET_UTF_8 = 'charset=utf-8';\nexport const CONTENT_TYPE = 'Content-Type';\n\nexport const UNDEFINED = 'undefined';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\nexport const FUNCTION = 'function';\n\nexport const ABORT_ERROR = 'AbortError';\nexport const TIMEOUT_ERROR = 'TimeoutError';\n\nexport const GET = 'GET';\nexport const HEAD = 'HEAD';\n\nexport const REJECT = 'reject';\n\n// Larger timer delays overflow and fire immediately in browsers and Node.js (~24.8 days)\nexport const MAX_DELAY_MS = 2147483647;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, MAX_DELAY_MS, OBJECT, STRING, UNDEFINED } from './constants';\nimport type {\n DefaultUrlParams,\n HeadersObject,\n QueryParams,\n UrlPathParams,\n} from './types';\n\n// Prevent stack overflow with recursion depth limit\nconst MAX_DEPTH = 10;\n\nexport const hasOwn = (o: any, k: string) =>\n Object.prototype.hasOwnProperty.call(o, k);\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 (hasOwn(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function checks for dangerous properties like '__proto__', 'constructor',\n * and 'prototype'. If none are present, the object is returned as-is (zero-copy fast path).\n * Otherwise, a shallow copy is created with the dangerous properties removed.\n *\n * @param obj - The object to sanitize\n * @returns A safe object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const hasProto = hasOwn(obj, '__proto__');\n const hasCtor = hasOwn(obj, 'constructor');\n const hasPrototype = hasOwn(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n // Copy key by key, as a spread compiled to assignments would let \"__proto__\" set the prototype\n const safeObj = {} as Record;\n\n for (const key of Object.keys(obj)) {\n if (key !== '__proto__' && key !== 'constructor' && key !== 'prototype') {\n safeObj[key] = obj[key];\n }\n }\n\n return safeObj as T;\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 // Without a prototype, a \"__proto__\" key is kept as a regular property instead of setting the prototype\n const sortedObj = Object.create(null) as Record;\n\n Object.keys(obj)\n .sort()\n .forEach((k) => (sortedObj[k] = obj[k]));\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 + (baseUrl.includes('?') ? '&' : '?') + 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, depth = 0) => {\n // Stop recursion if maximum depth is reached\n if (depth >= MAX_DEPTH) {\n return s;\n }\n\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 depth + 1,\n );\n }\n } else if (isObject(obj)) {\n for (key in obj) {\n buildParams(prefix + '[' + key + ']', obj[key], depth + 1);\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], depth + 1);\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 // This is for compatibility with server frameworks that expect the literal notation\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 `:` or `{}` (like in OpenAPI paths), where `` is a key in `urlPathParams`.\n *\n * @param {string} url - The URL string containing placeholders in the format `:` or `{}`.\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 || (url.indexOf(':') === -1 && url.indexOf('{') === -1)) {\n return url;\n }\n\n // Use a single RegExp and avoid unnecessary casts and function calls\n // Precompute keys for faster lookup\n const params = urlPathParams as DefaultUrlParams;\n\n // Use a replacer function that avoids extra work\n return url.replace(/:(\\w+)|\\{(\\w+)\\}/g, (match, colonKey, braceKey) => {\n const key = colonKey || braceKey;\n\n // Use hasOwnProperty for strict key existence check\n if (hasOwn(params, key)) {\n const value = params[key];\n\n // Only replace if value is not undefined or null\n if (value !== undefined && value !== null) {\n const encoded = encodeURIComponent(String(value));\n\n // These can't be encoded, and URL parsers would move the request to another path\n if (encoded === '.' || encoded === '..') {\n throw new Error('Path params \".\" and \"..\" not allowed.');\n }\n\n return encoded;\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL starts with a scheme (e.g., \"http://\", \"https://\").\n * A \"://\" appearing later, e.g. in a query string, does not make the URL absolute.\n *\n * @param url - The URL string to check.\n * @returns `true` if the URL is absolute, otherwise `false`.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n}\n\nexport const timeNow = () => Date.now();\n\nexport const noop = () => {};\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 (value === 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 (\n typeof globalThis !== UNDEFINED &&\n typeof globalThis.Buffer !== UNDEFINED &&\n globalThis.Buffer.isBuffer(value)\n ) {\n return false;\n }\n\n if (value instanceof Date || isSearchParams(value)) {\n return false;\n }\n\n if (isObject(value)) {\n const proto = Object.getPrototypeOf(value);\n\n // Check if the prototype is `Object.prototype` (plain object)\n if (proto === Object.prototype) {\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\n/**\n * Waits for the given time. When a signal is passed, the wait ends early once it is aborted.\n *\n * @param {number} ms - The time to wait in milliseconds.\n * @param {AbortSignal} [signal] - An optional signal that ends the wait when aborted.\n * @returns {Promise} - A promise that resolves with `true` once the wait is over.\n */\nexport const delayInvocation = (\n ms: number,\n signal?: AbortSignal,\n): Promise =>\n new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n if (signal) {\n signal.removeEventListener('abort', done);\n }\n resolve(true);\n };\n const timer = setTimeout(done, Math.min(ms, MAX_DELAY_MS));\n\n if (signal) {\n if (signal.aborted) {\n done();\n } else {\n signal.addEventListener('abort', done);\n }\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, depth = 0): any {\n if (depth >= MAX_DEPTH) {\n return data;\n }\n\n if (data && isObject(data) && typeof data.data !== UNDEFINED) {\n return flattenData(data.data, depth + 1);\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 // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key.toLowerCase()] = value;\n });\n } else {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n // Assigning \"__proto__\" would set the prototype of the result\n if (hasOwn(headers, key) && key !== '__proto__') {\n headersObject[key.toLowerCase()] = headers[key];\n }\n }\n }\n\n return headersObject;\n}\n\n/**\n * Determines if the current environment is a browser.\n *\n * @returns {boolean} - True if running in a browser environment, false otherwise.\n */\nexport function isBrowser(): boolean {\n // For node and some mobile frameworks like React Native, `add/removeEventListener` doesn't exist on window!\n return (\n typeof window !== UNDEFINED && typeof window.addEventListener === FUNCTION\n );\n}\n\n/**\n * Creates an abort/timeout error compatible with all JS runtimes.\n * Falls back to a plain Error with the correct `name` when DOMException is unavailable (e.g. React Native).\n *\n * @param {string} message - The error message.\n * @param {string} name - The error name (e.g. 'AbortError', 'TimeoutError').\n * @returns {DOMException | Error} - An error object with the specified name.\n */\nexport function createAbortError(\n message: string,\n name: string,\n): DOMException | Error {\n if (typeof DOMException !== UNDEFINED) {\n return new DOMException(message, name);\n }\n\n const error = new Error(message);\n error.name = name;\n\n return error;\n}\n\n/**\n * Detects if the user is on a slow network connection\n * @returns {boolean} True if connection is slow, false otherwise or if detection unavailable\n */\nexport const isSlowConnection = (): boolean => {\n const conn = typeof navigator !== UNDEFINED && (navigator as any).connection;\n\n return conn && ['slow-2g', '2g', '3g'].includes(conn.effectiveType);\n};\n\n/**\n * Detects if the page is hidden, e.g. when its tab is in the background or the window is minimized\n * @returns {boolean} True if the page is hidden, false otherwise or outside browsers\n */\nexport const isPageHidden = (): boolean =>\n typeof document !== UNDEFINED && document.visibilityState === 'hidden';\n\n/**\n * Detects if the browser is offline\n * @returns {boolean} True if the browser is offline, false otherwise or if the connection state is unknown\n */\nexport const isOffline = (): boolean =>\n typeof navigator !== UNDEFINED && navigator.onLine === false;\n","import { FUNCTION } from './constants';\nimport type { InterceptorFunction } from './types/interceptor-manager';\nimport { isObject, sanitizeObject } from './utils';\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 Args - Type of additional arguments.\n * @template I - Type of interceptors.\n *\n * @param {InterceptorFunction | InterceptorFunction[]} [interceptors] - Interceptor function(s).\n * @param {T} data - The data object to process.\n * @param {...Args} args - Additional arguments to pass to interceptors.\n *\n * @returns {Promise} - Nothing as the function is non-idempotent.\n */\nexport async function applyInterceptors<\n T extends object,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Args extends any[] = any[],\n I = InterceptorFunction | InterceptorFunction[],\n>(interceptors: I | undefined, data: T, ...args: Args): Promise {\n if (!interceptors) {\n return;\n }\n\n const merge = (v: unknown) =>\n v &&\n isObject(data) &&\n isObject(v) &&\n Object.assign(data, sanitizeObject(v));\n\n if (typeof interceptors === FUNCTION) {\n merge(await (interceptors as InterceptorFunction)(data, ...args));\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n merge(await interceptor(data, ...args));\n }\n }\n}\n","import type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\n/**\n * This is a base error class\n */\nexport class FetchError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends Error {\n // Declared only, and set in the constructor, as class fields would need a helper in the ES2018 bundle\n declare status: number;\n declare statusText: string;\n declare config: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >;\n declare isCancelled: boolean;\n declare request: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >;\n declare response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null;\n\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message);\n\n this.request = request;\n this.response = response;\n this.status = response ? response.status : 0;\n this.statusText = response ? response.statusText : '';\n this.config = request;\n this.isCancelled = false;\n this.name = 'FetchError';\n }\n}\n","import { FetchError } from './fetch-error';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '../types';\n\nexport class ResponseError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n> extends FetchError {\n constructor(\n message: string,\n request: RequestConfig,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n ) {\n super(message, request, response);\n\n this.name = 'ResponseError';\n }\n}\n","/**\n * @module timeout-wheel\n * @description\n * Ultra-minimal timing wheel implementation optimized for max performance & many requests.\n * For most of the cases it's 4-100x faster than setTimeout and setInterval alone.\n * Provides efficient scheduling and cancellation of timeouts using a circular array.\n *\n * Position 0 → 1 → 2 → ... → 599 → 0 → 1 → 2 ...\n * Time: 0s 1s 2s 599s 600s 601s 602s\n *\n * The timing wheel consists of 600 slots (one per second for 10 min).\n * Each slot contains a list of timeout items, each associated with a unique key and callback.\n * Timeouts are scheduled by placing them in the appropriate slot based on the delay in seconds.\n * The wheel advances every second, executing and removing callbacks as their timeouts expire.\n * Defaults to setTimeout if the delay doesn't fit in the wheel (~10 minutes) or is not divisible by 1000.\n *\n * @remarks\n * - Designed for minimal footprint and simplicity.\n * - Only supports second-level granularity (minimum timeout: 1 second).\n * - Timeouts never fire early, but may fire up to 1 second late.\n * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { MAX_DELAY_MS } from './constants';\nimport { noop, timeNow } from './utils';\n\ntype TimeoutCallback = () => unknown | Promise;\ntype TimeoutItem = [string, TimeoutCallback]; // [key, callback]\n\nconst WHEEL_SIZE = 600; // 600 slots for 10 min (1 slot per second)\nconst SECOND = 1000; // 1 second in milliseconds\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\nlet lastTick = 0; // Time when the wheel last advanced (or started)\nlet timer: NodeJS.Timeout | null = null;\n\nconst handleCallback = ([key, callback]: TimeoutItem): void => {\n keyMap.delete(key);\n\n try {\n const result = callback();\n if (result && result instanceof Promise) {\n // Silently ignore async errors to prevent wheel from stopping\n result.catch(noop);\n }\n } catch {\n // Ignore callback errors to prevent wheel from stopping\n }\n};\n\nexport const addTimeout = (\n key: string,\n cb: TimeoutCallback,\n ms: number,\n): void => {\n removeTimeout(key);\n\n // A running wheel is already part-way through its current second, so the timeout\n // waits one more slot to never fire early. A new wheel starts its first second now.\n const seconds = ms / SECOND + (timer && timeNow() !== lastTick ? 1 : 0);\n\n // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || seconds >= WHEEL_SIZE || ms % SECOND !== 0) {\n keyMap.set(key, [\n setTimeout(\n handleCallback.bind(null, [key, cb]),\n Math.min(ms, MAX_DELAY_MS),\n ),\n ]); // Store timeout ID instead of slot\n\n return;\n }\n\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n lastTick = timeNow();\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n lastTick = timeNow();\n const slot = wheel[position];\n\n // Use slot.length directly (not cached) so mid-iteration mutations\n // from callbacks (e.g. removeTimeout) are handled correctly\n for (let i = 0; i < slot.length; i++) {\n handleCallback(slot[i]);\n }\n\n slot.length = 0; // Reuse array, avoid GC allocation\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }, SECOND);\n }\n};\n\nexport const removeTimeout = (key: string): void => {\n const slotOrTimeout = keyMap.get(key);\n\n if (slotOrTimeout !== undefined) {\n // It's a Timeout object from setTimeout\n if (Array.isArray(slotOrTimeout)) {\n clearTimeout(slotOrTimeout[0]);\n } else {\n const slotArr = wheel[slotOrTimeout];\n\n for (let i = 0; i < slotArr.length; i++) {\n if (slotArr[i][0] === key) {\n slotArr.splice(i, 1);\n break;\n }\n }\n }\n\n keyMap.delete(key);\n\n if (!keyMap.size && timer) {\n clearInterval(timer);\n timer = null;\n }\n }\n};\n\nexport const clearAllTimeouts = () => {\n // Clear native setTimeout timeouts first!\n keyMap.forEach((value) => {\n if (Array.isArray(value)) {\n clearTimeout(value[0]);\n }\n });\n\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n\n keyMap.clear();\n\n for (let i = 0; i < WHEEL_SIZE; i++) {\n wheel[i].length = 0;\n }\n\n position = 0;\n};\n","/**\n * @module inflight-manager\n *\n * Manages in-flight asynchronous requests using unique keys to enable deduplication and cancellation.\n *\n * Provides utilities for:\n * - Deduplication of requests within a configurable time window (`dedupeTime`)\n * - Timeout management and automatic request abortion\n * - AbortController lifecycle and cancellation logic\n * - Concurrency control and request state tracking\n * - In-flight promise deduplication to prevent duplicate network calls\n *\n * @remarks\n * - Requests with the same key within the deduplication interval share the same AbortController and in-flight promise.\n * - Supports cancellation of previous requests when a new one with the same key is issued, if `isCancellable` is enabled.\n * - Timeout logic ensures requests are aborted after a specified duration, if enabled.\n * - Internal queue state is managed via a Map, keyed by request identifier.\n * - Polled requests are also marked as \"in-flight\" to prevent duplicate requests.\n */\n\nimport { ABORT_ERROR, TIMEOUT_ERROR } from './constants';\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { createAbortError, timeNow } from './utils';\n\nexport type InFlightItem = [\n AbortController, // AbortController for the request\n boolean, // Whether timeout is enabled for the request\n number, // Timestamp when the request was marked in-flight\n boolean, // isCancellable - whether the request can be cancelled\n Promise | null, // Optional in-flight promise for deduplication\n];\n\nconst inFlight: Map = 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 {string | null} key - Unique key for the request (e.g. cache key).\n * @param {string} url - The request URL (for error messages/timeouts).\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 {AbortController} - A promise that resolves to an AbortController.\n */\nexport function markInFlight(\n key: string | null,\n url: string,\n timeout: number | undefined,\n dedupeTime: number,\n isCancellable: boolean,\n isTimeoutEnabled: boolean,\n): AbortController {\n if (!key) {\n return new AbortController();\n }\n\n const now = timeNow();\n const item = inFlight.get(key);\n let prevPromise: Promise | null = null;\n\n // Previous request is in-flight, check if we can reuse it\n if (item) {\n const prevController = item[0];\n const prevIsCancellable = item[3];\n\n // If the request is already in the queue and within the dedupeTime, reuse the existing controller\n if (\n !prevIsCancellable &&\n now - item[2] < dedupeTime &&\n !prevController.signal.aborted\n ) {\n return prevController;\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 (prevIsCancellable) {\n prevController.abort(\n createAbortError('Aborted due to new request', ABORT_ERROR),\n );\n }\n\n removeTimeout(key);\n prevPromise = item[4];\n }\n\n const controller = new AbortController();\n\n inFlight.set(key, [\n controller,\n isTimeoutEnabled,\n now,\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n createAbortError(url + ' aborted due to timeout', TIMEOUT_ERROR),\n );\n },\n timeout as number,\n );\n }\n\n return controller;\n}\n\n/**\n * Removes a request from the queue and clears its timeout.\n *\n * @param key - Unique key for the request.\n * @param {boolean} error - Optional error to abort the request with. If null, the request is simply removed but no abort sent.\n * @returns {Promise} - A promise that resolves when the request is aborted and removed.\n */\nexport async function abortRequest(\n key: string | null,\n error: DOMException | Error | null | string = null,\n): Promise {\n // If the key is not in the queue, there's nothing to remove\n if (key) {\n const item = inFlight.get(key);\n\n if (item) {\n // If the request is not yet aborted, abort it with the provided error\n if (error) {\n const controller = item[0];\n controller.abort(error);\n }\n\n removeInFlight(key);\n }\n }\n}\n\n/**\n * Removes a request from the in-flight queue without aborting or clearing timeout.\n *\n * @param key - Unique key for the request.\n */\nexport function removeInFlight(key: string | null): void {\n removeTimeout(key!);\n inFlight.delete(key!);\n}\n\n/**\n * Gets the AbortController for a request key.\n *\n * @param key - Unique key for the request.\n * @returns {AbortController | undefined} - The AbortController or undefined.\n */\nexport async function getController(\n key: string,\n): Promise {\n const item = inFlight.get(key);\n\n return item && item[0];\n}\n\n/**\n * Adds helpers for in-flight promise deduplication.\n *\n * @param key - Unique key for the request.\n * @param promise - The promise to store.\n */\nexport function setInFlightPromise(\n key: string,\n promise: Promise,\n): void {\n const item = inFlight.get(key);\n if (item) {\n // store the promise at index 4 — item is already the Map's reference, no need to re-set\n item[4] = promise;\n }\n}\n\n/**\n * Retrieves the in-flight promise for a request key if it exists and is within the dedupeTime interval.\n *\n * @param key - Unique key for the request.\n * @param dedupeTime - Deduplication time in milliseconds.\n * @returns {Promise | null} - The in-flight promise or null.\n */\nexport function getInFlightPromise(\n key: string | null,\n dedupeTime: number,\n): Promise | null {\n if (!key) {\n return null;\n }\n\n const prevReq = inFlight.get(key);\n\n if (\n prevReq &&\n // If the request is in-flight and has a promise\n prevReq[4] &&\n // If the request is cancellable, we will not reuse it\n !prevReq[3] &&\n // If the request is within the dedupeTime\n timeNow() - prevReq[2] < dedupeTime &&\n // If one request is cancelled, ALL deduped requests get cancelled\n !prevReq[0].signal.aborted\n ) {\n return prevReq[4] as Promise;\n }\n\n return null;\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","/**\n * @module revalidator-manager\n *\n * Provides utilities for managing cache revalidation functions, including:\n * - Registering and unregistering revalidators for specific cache keys.\n * - Triggering revalidation for a given key.\n * - Enabling or disabling automatic revalidation on window focus and if user comes back online for specific keys.\n * - Attaching and removing global focus and online event handlers to trigger revalidation.\n *\n * Revalidators are functions that can be registered to revalidate cache entries when needed.\n * They are typically used to refresh data in the cache when the window gains focus or when specific actions occur.\n * @performance O(1) lookup by key makes it blazing fast to register, unregister, and revalidate cache entries.\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n * @remarks\n * - Designed to be used in various environments (Deno, Node.js, Bun, Browser, etc.) to ensure cache consistency and freshness.\n */\nimport { addTimeout, removeTimeout } from './timeout-wheel';\nimport { FetchResponse } from './types';\nimport { isBrowser, noop, timeNow } from './utils';\n\nexport type RevalidatorFn = (\n isStaleRevalidation?: boolean,\n) => Promise;\n\ntype EventType = 'focus' | 'online';\n\ntype RevalidatorEntry = [\n RevalidatorFn, // main revalidator\n number, // lastUsed\n number, // ttl\n number?, // staleTime\n RevalidatorFn?, // bgRevalidator\n boolean?, // refetchOnFocus\n boolean?, // refetchOnReconnect\n number?, // focusThrottleInterval\n];\n\nconst DEFAULT_TTL = 3 * 60 * 1000; // Default TTL of 3 minutes\nconst revalidators = new Map();\n\n/**\n * Stores cleanup functions for active event handlers (browser or custom providers).\n * Each entry removes the corresponding event listener when called.\n * @remarks\n * - Improves performance by reducing the number of event listeners.\n * - Enables efficient O(1) lookup and management of event handlers for revalidation.\n */\nconst eventHandlers = new Map void>();\n\n/** Subscribe to an event and return a cleanup function */\nexport type EventProvider = (handler: () => void) => () => void;\n\nconst customEventProviders = new Map();\n\n/**\n * Registers a custom event provider for 'focus' or 'online' events.\n * Useful for non-browser environments like React Native.\n *\n * @param type - The event type ('focus' or 'online').\n * @param provider - A function that subscribes to the event and returns a cleanup function.\n */\nexport function setEventProvider(\n type: EventType,\n provider: EventProvider,\n): void {\n customEventProviders.set(type, provider);\n\n // Re-register if already active\n if (eventHandlers.has(type)) {\n removeEventHandler(type);\n addEventHandler(type);\n }\n}\n\n/**\n * Triggers revalidation for all registered entries based on the given event type.\n * For example, if it's a 'focus' event, it will revalidate entries that have the `refetchOnFocus` flag set.\n * Updates the timestamp and invokes the revalidator function for each applicable entry.\n *\n * @param type - The type of event that caused the revalidation (e.g., 'focus' or 'online').\n * @param isStaleRevalidation - If `true`, uses background revalidator and doesn't mark as in-flight.\n * @param isThrottled - If `true`, skips entries that were requested or revalidated within their `focusThrottleInterval`.\n */\nexport function revalidateAll(\n type: EventType,\n isStaleRevalidation: boolean = true,\n isThrottled: boolean = false,\n) {\n const flagIndex = type === 'focus' ? 5 : 6;\n const now = timeNow();\n\n revalidators.forEach((entry) => {\n if (!entry[flagIndex] || (isThrottled && now - entry[1] < entry[7]!)) {\n return;\n }\n\n entry[1] = now;\n\n // If it's a stale revalidation, use the background revalidator function\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n if (revalidator) {\n Promise.resolve(revalidator(isStaleRevalidation)).catch(noop);\n }\n });\n}\n\n/**\n * Revalidates an entry by executing the registered revalidation function.\n *\n * @param key The unique identifier for the cache entry to revalidate. If `null`, no revalidation occurs.\n * @param isStaleRevalidation - If `true`, it does not mark revalidated requests as in-flight.\n * @returns A promise that resolves to the result of the revalidator function, or\n * `null` if no key or revalidator is found, or a `FetchResponse` if applicable.\n */\nexport async function revalidate(\n key: string | null,\n isStaleRevalidation: boolean = false,\n): Promise {\n // If no key is provided, no revalidation occurs\n if (!key) {\n return null;\n }\n\n const entry = revalidators.get(key);\n\n if (entry) {\n // Update only the lastUsed timestamp without resetting the whole array\n entry[1] = timeNow();\n\n const revalidator = isStaleRevalidation ? entry[4] : entry[0];\n\n // If no revalidator function is registered, return null\n if (revalidator) {\n return await revalidator(isStaleRevalidation);\n }\n }\n\n // If no revalidator is registered for the key, return null\n return null;\n}\n\n/**\n * Removes all revalidators associated with the specified event type.\n *\n * @param type - The event type whose revalidators should be removed.\n */\nexport function removeRevalidators(type: EventType) {\n removeEventHandler(type);\n\n const flagIndex = type === 'focus' ? 5 : 6;\n\n // Clear all revalidators with this flag\n revalidators.forEach((entry, key) => {\n if (entry[flagIndex]) {\n removeRevalidator(key);\n }\n });\n}\n\n/**\n * Registers a generic revalidation event handler for the specified event type.\n * Supports browser window events and custom event providers (e.g. for React Native).\n * Ensures the handler is only added once.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'online').\n */\nfunction addEventHandler(event: EventType) {\n if (eventHandlers.has(event)) {\n return;\n }\n\n // Focus events are throttled, so that e.g. switching between tabs quickly doesn't revalidate every time\n const handler = revalidateAll.bind(null, event, true, event === 'focus');\n\n // Priority 1: Custom event provider (works in any environment including React Native)\n const customProvider = customEventProviders.get(event);\n\n if (customProvider) {\n const cleanup = customProvider(handler);\n\n eventHandlers.set(event, cleanup);\n\n return;\n }\n\n // Priority 2: Browser window events\n if (isBrowser()) {\n window.addEventListener(event, handler);\n\n eventHandlers.set(event, () => window.removeEventListener(event, handler));\n }\n}\n\n/**\n * Removes the event handler for the specified event type.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n const cleanup = eventHandlers.get(event);\n\n if (cleanup) {\n cleanup();\n eventHandlers.delete(event);\n }\n}\n\n/**\n * Registers a revalidation functions for a specific cache key.\n *\n * @param {string} key Cache key to utilize\n * @param {RevalidatorFn} revalidatorFn Main revalidation function (marks in-flight requests)\n * @param {number} [ttl] Time to live in milliseconds (default: 3 minutes)\n * @param {number} [staleTime] Time (in seconds) after which the cache entry is considered stale\n * @param {RevalidatorFn} [bgRevalidatorFn] For stale revalidation (does not mark in-flight requests)\n * @param {boolean} [refetchOnFocus] Whether to revalidate on window focus\n * @param {boolean} [refetchOnReconnect] Whether to revalidate on network reconnect\n * @param {number} [focusThrottleInterval] Time (in milliseconds) after a request or revalidation during which focus events don't revalidate it\n */\nexport function addRevalidator(\n key: string,\n revalidatorFn: RevalidatorFn, // Main revalidation function (marks in-flight requests)\n ttl?: number,\n staleTime?: number,\n bgRevalidatorFn?: RevalidatorFn, // For stale revalidation (does not mark in-flight requests)\n refetchOnFocus?: boolean,\n refetchOnReconnect?: boolean,\n focusThrottleInterval?: number,\n) {\n // Existing entries are updated in place\n const entry = revalidators.get(key) || ([] as unknown as RevalidatorEntry);\n\n entry[0] = revalidatorFn;\n entry[1] = timeNow();\n entry[2] = ttl ?? DEFAULT_TTL;\n entry[3] = staleTime;\n entry[4] = bgRevalidatorFn;\n entry[5] = refetchOnFocus;\n entry[6] = refetchOnReconnect;\n entry[7] = focusThrottleInterval;\n\n revalidators.set(key, entry);\n\n if (refetchOnFocus) {\n addEventHandler('focus');\n }\n\n if (refetchOnReconnect) {\n addEventHandler('online');\n }\n\n if (staleTime) {\n addTimeout('s:' + key, revalidate.bind(null, key, true), staleTime * 1000);\n }\n}\n\nexport function removeRevalidator(key: string) {\n revalidators.delete(key);\n\n // Clean up stale timer\n removeTimeout('s:' + key);\n}\n\n/**\n * Periodically cleans up expired revalidators from the registry.\n * Removes any revalidator whose TTL has expired.\n *\n * @param {number} intervalMs How often to run cleanup (default: 3 minutes)\n * @returns {() => void} A function to stop the periodic cleanup\n */\nexport function startRevalidatorCleanup(\n intervalMs: number = DEFAULT_TTL,\n): () => void {\n const intervalId = setInterval(() => {\n const now = timeNow();\n\n revalidators.forEach(\n ([, lastUsed, ttl, , , refetchOnFocus, refetchOnReconnect], key) => {\n // Skip focus-only or reconnect-only revalidators to keep them alive\n if (refetchOnFocus || refetchOnReconnect) {\n return;\n }\n\n if (ttl > 0 && now - lastUsed > ttl) {\n removeRevalidator(key);\n }\n },\n );\n }, intervalMs);\n\n return () => clearInterval(intervalId);\n}\n","/**\n * Manages a set of listeners (subscribers) for arbitrary string keys, allowing cross-context or cross-component\n * cache updates and synchronization. Provides functions to add, remove, and notify listeners, as well as a\n * convenient subscribe/unsubscribe API.\n *\n * @template T - The type of the response object passed to listeners.\n *\n * @remarks\n * - Listeners are grouped by a string key, which typically represents a cache key or resource identifier.\n * - When `notifySubscribers` is called for a key, all listeners registered for that key are invoked with the provided response.\n * - The `subscribe` function returns an unsubscribe function for convenient cleanup.\n *\n * @example\n * ```ts\n * const unsubscribe = subscribe('user:123', (response) => {\n * // handle updated data\n * });\n * // Later, to stop listening:\n * unsubscribe();\n * ```\n */\n\nimport { noop } from './utils';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Listener = (response: T) => void;\n\nconst listeners = new Map>();\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n let set = listeners.get(key);\n\n if (!set) {\n listeners.set(key, (set = new Set()));\n }\n\n set.add(fn);\n}\n\nexport function removeListener(key: string, fn: Listener) {\n const set = listeners.get(key);\n\n if (set) {\n set.delete(fn);\n\n // If the set is empty, remove the key from the listeners map\n if (set.size === 0) {\n listeners.delete(key);\n }\n }\n}\n\nexport function notifySubscribers(key: string, response: T) {\n const fns = listeners.get(key);\n\n if (fns) {\n if (fns.size === 1) {\n // If there's only one listener, call it directly\n const fn = fns.values().next().value;\n fn!(response);\n } else {\n fns.forEach((fn) => fn(response));\n }\n }\n}\n\nexport function subscribe(key: string | null, fn: (response: T) => void) {\n if (!key) {\n // No op if no key is provided\n return noop;\n }\n\n addListener(key, fn);\n\n // Return an unsubscribe function\n return () => {\n removeListener(key, fn);\n };\n}\n","import { processHeaders } from './utils';\nimport {\n GET,\n APPLICATION_JSON,\n HEAD,\n STRING,\n CHARSET_UTF_8,\n CONTENT_TYPE,\n REJECT,\n UNDEFINED,\n APPLICATION_CONTENT_TYPE,\n} from './constants';\nimport type {\n HeadersObject,\n Method,\n RequestConfig,\n} from './types/request-handler';\nimport {\n replaceUrlPathParams,\n appendQueryParams,\n isSearchParams,\n isJSONSerializable,\n isSlowConnection,\n isAbsoluteUrl,\n sanitizeObject,\n isObject,\n} from './utils';\n\nconst defaultTimeoutMs = (isSlowConnection() ? 60 : 30) * 1000;\n\nexport const defaultConfig: RequestConfig = {\n strategy: REJECT,\n timeout: defaultTimeoutMs, // 30 seconds (60 on slow connections)\n loadingTimeout: defaultTimeoutMs / 10, // 3 seconds (6 on slow connections)\n focusThrottleInterval: 5000, // 5 seconds\n headers: {\n Accept: APPLICATION_JSON + ', text/plain, */*',\n 'Accept-Encoding': 'gzip, deflate, br',\n },\n retry: {\n delay: defaultTimeoutMs / 30, // 1 second (2 on slow connections)\n maxDelay: defaultTimeoutMs, // 30 seconds (60 on slow connections)\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 // Idempotent methods, which can be repeated safely, unlike e.g. POST requests that create resources\n methods: [GET, HEAD, 'PUT', 'DELETE', 'OPTIONS', 'TRACE'],\n },\n};\n\n/**\n * Overwrites the default configuration with the provided custom configuration.\n *\n * @param {Partial} customConfig - The custom configuration to merge into the default config.\n * @returns {Partial} - The updated default configuration object.\n */\nexport function setDefaultConfig(\n customConfig: Partial,\n): Partial {\n const sanitized = sanitizeObject(customConfig);\n\n // Merge nested retry and headers settings into the current defaults instead of replacing them\n return mergeConfigs(\n { retry: defaultConfig.retry, headers: defaultConfig.headers },\n sanitized,\n defaultConfig,\n );\n}\n\n/**\n * Returns a shallow copy of the current default configuration.\n *\n * @returns {RequestConfig} - The current default configuration.\n */\nexport function getDefaultConfig(): RequestConfig {\n return { ...defaultConfig };\n}\n\n/**\n * Build request configuration from defaults and overrides.\n * This function merges the default configuration with the provided request configuration,\n * @param {string} url - Request url\n * @param {RequestConfig | null | undefined} reqConfig - Request configuration\n * @return {RequestConfig} - Merged request configuration\n */\nexport function buildConfig(\n url: string,\n reqConfig?: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null,\n): RequestConfig {\n // Merging gives the request its own copies of nested objects like headers, so that\n // mutations (e.g. by interceptors) never leak into the global defaults\n const merged = mergeConfigs(\n defaultConfig,\n reqConfig ? sanitizeObject(reqConfig) : {},\n );\n\n return buildFetcherConfig(url, merged);\n}\n\n/**\n * Builds the fetcher configuration by setting the method, body, headers, and URL.\n * It also handles query parameters and path parameters. This fn mutates the passed `requestConfig` object.\n * @param {string} url - The endpoint URL to which the request will be sent.\n * @param {RequestConfig} requestConfig - The request configuration object containing method, body, headers, and other options.\n * @return {RequestConfig} - The modified request configuration object with the URL, method, body, and headers set appropriately.\n **/\nexport function buildFetcherConfig(\n url: string,\n requestConfig: RequestConfig,\n): RequestConfig {\n let method = requestConfig.method as Method;\n method = method ? (method.toUpperCase() as Method) : GET;\n\n let body: RequestConfig['data'] | undefined;\n\n // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n if (method !== GET && method !== HEAD) {\n body = requestConfig.body ?? requestConfig.data;\n\n // Automatically stringify request body, if possible and when not dealing with strings\n if (body && typeof body !== STRING && isJSONSerializable(body)) {\n body = JSON.stringify(body);\n }\n }\n\n setContentTypeIfNeeded(requestConfig.headers, body);\n\n // Native fetch compatible settings\n const credentials = requestConfig.withCredentials\n ? 'include'\n : requestConfig.credentials;\n\n // The explicitly passed query params\n const dynamicUrl = replaceUrlPathParams(url, requestConfig.urlPathParams);\n const urlPath = appendQueryParams(dynamicUrl, requestConfig.params);\n const isFullUrl = isAbsoluteUrl(url);\n const baseURL = isFullUrl\n ? ''\n : requestConfig.baseURL || requestConfig.apiUrl || '';\n\n // Join as a path, as plain concatenation could extend the host of the baseURL,\n // e.g. \"https://api.example.com\" + \".evil.com\" would point to another host\n const separator =\n baseURL && urlPath && !baseURL.endsWith('/') && !/^[/?#]/.test(urlPath)\n ? '/'\n : '';\n\n requestConfig.url = baseURL + separator + urlPath;\n requestConfig.method = method;\n requestConfig.credentials = credentials;\n requestConfig.body = body;\n\n return requestConfig;\n}\n\n/**\n * Ensures the `Content-Type` header is set to `application/json; charset=utf-8`\n * if it is not already present and the request method and body meet specific conditions.\n *\n * @param headers - The headers object to modify. Can be an instance of `Headers`\n * or a plain object conforming to `HeadersInit`.\n * @param body - The optional body of the request. If no body is provided and the\n * method is 'GET' or 'HEAD', the function exits without modifying headers.\n */\nfunction setContentTypeIfNeeded(\n headers?: HeadersInit | HeadersObject,\n body?: unknown,\n): void {\n // If no headers are provided, or if the body is not set and the method is PUT or DELETE, do nothing\n if (!headers || !body) {\n return;\n }\n\n // Types that should not have Content-Type set (browser handles these)\n if (\n body instanceof FormData || // Browser automatically sets multipart/form-data with boundary\n (typeof Blob !== UNDEFINED && body instanceof Blob) || // Blob/File (a File is a Blob) already have their own MIME types, don't override\n (typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream) // Stream type should be determined by the stream source\n ) {\n return;\n }\n\n let contentTypeValue: string;\n\n if (isSearchParams(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded';\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n contentTypeValue = APPLICATION_CONTENT_TYPE + 'octet-stream';\n } else if (isJSONSerializable(body)) {\n contentTypeValue = APPLICATION_JSON + ';' + CHARSET_UTF_8;\n } else {\n // Do not set Content-Type if content is not recognizable\n return;\n }\n\n if (headers instanceof Headers) {\n if (!headers.has(CONTENT_TYPE)) {\n headers.set(CONTENT_TYPE, contentTypeValue);\n }\n } else if (\n isObject(headers) &&\n !Array.isArray(headers) &&\n // Header names are case-insensitive, so check the normalized (lowercase) headers\n !processHeaders(headers as HeadersObject)[CONTENT_TYPE.toLowerCase()]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\n// The interceptors that are merged instead of replaced\nconst INTERCEPTORS = [\n 'onRequest',\n 'onResponse',\n 'onError',\n 'onLoadingSlow',\n] as const;\n\n/**\n * Merges two request configurations, applying overrides from the second config to the first.\n * Handles special merging for nested properties like 'retry' and 'headers' (deep merge),\n * and concatenates interceptor arrays for 'onRequest', 'onResponse', 'onError' and 'onLoadingSlow'.\n * If a target config is provided, it mutates that object; otherwise, creates a new one.\n *\n * @param {RequestConfig} baseConfig - The base configuration object to merge from.\n * @param {RequestConfig} overrideConfig - The override configuration object to apply on top of the base.\n * @param {RequestConfig} [targetConfig={}] - Optional target configuration object to merge into (mutated in place).\n * @returns {RequestConfig} The merged configuration object.\n *\n * @example\n * const base = { timeout: 5000, headers: { 'Accept': 'application/json' } };\n * const override = { timeout: 10000, headers: { 'Authorization': 'Bearer token' } };\n * const merged = mergeConfigs(base, override);\n * // Result: { timeout: 10000, headers: { Accept: 'application/json', Authorization: 'Bearer token' } }\n */\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig = {},\n): RequestConfig {\n Object.assign(targetConfig, baseConfig, overrideConfig);\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', baseConfig, overrideConfig, targetConfig);\n mergeConfig('headers', baseConfig, overrideConfig, targetConfig);\n\n // Merge interceptors efficiently\n for (const property of INTERCEPTORS) {\n mergeInterceptors(property, baseConfig, overrideConfig, targetConfig);\n }\n\n return targetConfig;\n}\n\n/**\n * Efficiently merges interceptor functions from base and new configs\n */\nfunction mergeInterceptors<\n K extends\n 'onRequest' | 'onResponse' | 'onError' | 'onRetry' | 'onLoadingSlow',\n>(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const baseInterceptor = baseConfig[property];\n const newInterceptor = overrideConfig[property];\n\n if (baseInterceptor && newInterceptor) {\n // This is the only LIFO interceptor, so we apply it after the response is prepared\n targetConfig[property] = (\n property === 'onResponse'\n ? [].concat(newInterceptor as never, baseInterceptor as never)\n : [].concat(baseInterceptor as never, newInterceptor as never)\n ) as RequestConfig[K];\n } else if (baseInterceptor || newInterceptor) {\n targetConfig[property] = baseInterceptor || newInterceptor;\n }\n}\n\n/**\n * Merges the specified property from the base configuration and the override configuration into the target configuration.\n *\n * @param {K} property - The property key to merge from the base and override configurations. Must be a key of RequestConfig.\n * @param {RequestConfig} baseConfig - The base configuration object that provides default values.\n * @param {RequestConfig} overrideConfig - The override configuration object that contains user-specific settings to merge.\n * @param {RequestConfig} targetConfig - The configuration object that will receive the merged properties.\n */\nexport function mergeConfig(\n property: K,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n targetConfig: RequestConfig,\n): void {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n if (override) {\n if (property === 'headers') {\n // Handle Headers instances which don't expose entries as own enumerable properties\n const isInstance =\n (base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers;\n const merged: HeadersObject = isInstance\n ? processHeaders(base)\n : { ...(base as HeadersObject) };\n const overrides: HeadersObject = isInstance\n ? processHeaders(override)\n : sanitizeObject(override as HeadersObject);\n\n // Header names are case-insensitive, so replace existing entries instead of duplicating them\n for (const key of Object.keys(overrides)) {\n const lowerKey = key.toLowerCase();\n\n for (const existingKey in merged) {\n if (existingKey.toLowerCase() === lowerKey) {\n delete merged[existingKey];\n }\n }\n\n merged[key] = overrides[key];\n }\n\n targetConfig[property] = merged as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...sanitizeObject(override as Record),\n } as RequestConfig[K];\n }\n } else if (\n override === undefined &&\n isObject(base) &&\n !((base as Headers | HeadersObject) instanceof Headers)\n ) {\n // Copy so that mutating the merged config never changes the base config\n targetConfig[property] = { ...base } as RequestConfig[K];\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hash } from './hash';\nimport type {\n CacheKeyFunction,\n DefaultResponse,\n FetchResponse,\n MutationSettings,\n RequestConfig,\n} from './types/request-handler';\nimport type {\n CacheEntry,\n CacheStore,\n StoredResponse,\n} from './types/cache-manager';\nimport { GET, STRING } from './constants';\nimport {\n isJSONSerializable,\n isObject,\n isSearchParams,\n noop,\n sanitizeObject,\n sortObject,\n timeNow,\n} from './utils';\nimport { revalidate } from './revalidator-manager';\nimport { notifySubscribers } from './pubsub-manager';\nimport type { DefaultPayload, DefaultParams, DefaultUrlParams } from './types';\nimport { removeInFlight } from './inflight-manager';\nimport { addTimeout } from './timeout-wheel';\nimport { defaultConfig } from './config-handler';\nimport { processHeaders } from './utils';\n\nexport const IMMEDIATE_DISCARD_CACHE_TIME = 0; // Use it for cache entries that need to be persistent until unused by components or manually deleted\n\nconst _cache = new Map>();\n// The cache stores that keep copies of cache entries, by cache key\nconst stores = new Map();\nconst DELIMITER = '|';\nconst MIN_LENGTH_TO_HASH = 64;\nconst CACHE_KEY_SANITIZE_PATTERN = /[^\\w\\-_|/:@.?=&~%#]/g;\nconst CACHE_KEY_NEEDS_SANITIZE = /[^\\w\\-_|/:@.?=&~%#]/; // Non-global for fast test\n\n/**\n * Headers that may affect HTTP response content and should be included in cache key generation.\n * Header names are matched case-insensitively.\n *\n * - Content negotiation: accept (response format, e.g. JSON or HTML), accept-language (localization), accept-encoding (compression)\n * - Authentication: authorization (access to protected resources)\n * - Request body metadata: content-type (how the request body is interpreted)\n * - Optional: referer (may influence behavior in some APIs), origin (CORS or tenant-specific APIs),\n * user-agent (if the server returns client-specific content), cookie (session-based responses; can fragment the cache heavily)\n * - Custom headers that may affect response content: x-api-key (token-based access), x-requested-with (AJAX requests),\n * x-client-id (per-client/partner identity), x-tenant-id (multi-tenant segmentation), x-user-id (explicit user context),\n * x-app-version (version-specific behavior), x-feature-flag (feature rollout), x-device-id (per device/app instance),\n * x-platform (e.g. 'ios', 'android', 'web'), x-session-id (if it affects the response directly), x-locale (like accept-language)\n */\nconst CACHE_KEY_HEADERS =\n /^(accept(-language|-encoding)?|authorization|content-type|referer|origin|user-agent|cookie|x-(api-key|requested-with|client-id|tenant-id|user-id|app-version|feature-flag|device-id|platform|session-id|locale))$/i;\n\n/**\n * Generates a unique 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 {RequestConfig} config - 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 {RequestCredentials} [credentials=\"same-origin\"] - Whether to include credentials (include, same-origin, omit).\n * @property {RequestCache} [cache=\"default\"] - The cache mode (e.g., default, no-store, reload).\n * @returns {string} - A unique cache key string based on the provided options.\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(\n config: RequestConfig,\n cacheKeyCheck = true,\n): string {\n // This is super fast. Effectively a no-op if cacheKey is\n // a string or a function that returns a string.\n const key = config.cacheKey;\n\n if (key && cacheKeyCheck) {\n return typeof key === STRING\n ? (key as string)\n : (key as CacheKeyFunction)(config);\n }\n\n const {\n url = '',\n method = GET,\n headers = null,\n body = null,\n credentials = 'same-origin',\n } = config;\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 let headersString = '';\n if (headers) {\n let obj: Record;\n\n if (headers instanceof Headers) {\n obj = processHeaders(headers);\n } else {\n obj = headers as Record;\n }\n\n // Filter headers to only include those that affect request identity\n // Include only headers that affect request identity, not execution behavior\n const keys = Object.keys(obj);\n const len = keys.length;\n\n // Sort keys manually for fastest deterministic output\n if (len > 1) {\n keys.sort();\n }\n\n let str = '';\n for (let i = 0; i < len; ++i) {\n if (CACHE_KEY_HEADERS.test(keys[i])) {\n str += keys[i] + ':' + obj[keys[i]] + ';';\n }\n }\n\n headersString = hash(str);\n }\n\n // Concatenate all key parts into a cache key string\n // Template literals are apparently slower\n const cacheStr =\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString;\n\n // For GET requests, return early with shorter cache key\n if (method === GET) {\n return sanitizeCacheKey(cacheStr);\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING || isSearchParams(body)) {\n const str = String(body);\n\n bodyString = str.length < MIN_LENGTH_TO_HASH ? str : hash(str); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Files can't be read synchronously, so they are identified by their object\n bodyString +=\n key +\n '=' +\n (typeof value === STRING ? value : 'F' + getObjectId(value as File)) +\n '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (isObject(body) && !isJSONSerializable(body)) {\n // Blobs, buffers, streams etc. can't be read synchronously, so they are identified by their object.\n // Two different bodies never share a key, while the same body object is still deduplicated.\n bodyString = 'B' + getObjectId(body);\n } else {\n const o = isObject(body)\n ? JSON.stringify(sortObject(body))\n : String(body);\n\n bodyString = o.length > MIN_LENGTH_TO_HASH ? hash(o) : o;\n }\n }\n\n return sanitizeCacheKey(cacheStr + DELIMITER + bodyString);\n}\n\nconst objectIds = new WeakMap();\nlet lastObjectId = 0;\n\n/**\n * Returns a unique id for an object, e.g. a request body that can't be serialized.\n *\n * @param {object} obj - The object to identify.\n * @returns {number} - The id of the object.\n */\nfunction getObjectId(obj: object): number {\n let id = objectIds.get(obj);\n\n if (!id) {\n objectIds.set(obj, (id = ++lastObjectId));\n }\n\n return id;\n}\n\n/**\n * Prevents cache poisoning by removal of control chars and unusual characters.\n * When anything is removed, a hash of the original key is appended so that keys\n * differing only in the removed characters (e.g. `?a[]=1` and `?a=1`) don't collide.\n *\n * @param {string} cacheStr - The raw cache key.\n * @returns {string} - The sanitized cache key.\n */\nfunction sanitizeCacheKey(cacheStr: string): string {\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '') +\n DELIMITER +\n hash(cacheStr)\n : cacheStr;\n}\n\n/**\n * Checks if the cache entry is expired based on its timestamp and the expiry time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is expired, false otherwise.\n */\nfunction isCacheExpired(entry: CacheEntry): boolean {\n // No expiry time means the entry never expires\n if (!entry.expiry) {\n return false;\n }\n\n return timeNow() > entry.expiry;\n}\n\n/**\n * Retrieves a cached response from the internal cache using the provided key.\n *\n * @param key - The unique key identifying the cached entry. If null, returns null.\n * @returns The cached {@link FetchResponse} if found, otherwise null.\n */\nexport function getCacheData<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n key: string | null,\n): FetchResponse | null {\n if (!key) {\n return null;\n }\n\n const entry = _cache.get(key);\n\n return entry ? entry.data : null;\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 * @returns {CacheEntry | null} - The cache entry if it exists and is not expired, null otherwise.\n */\nexport function getCache(\n key: string | null,\n):\n | CacheEntry<\n FetchResponse\n >\n | null\n | undefined {\n return _cache.get(key as string);\n}\n\n/**\n * Sets a new cache entry or updates an existing one, with optional TTL (time-to-live).\n *\n * @param {string} key Cache key to utilize\n * @param {T} data - The data to be cached.\n * @param {number} [ttl] - Optional TTL in seconds. If not provided, the cache entry will not expire.\n * @param {number} [staleTime] - Optional stale time in seconds. If provided, the cache entry will be considered stale after this time.\n */\nexport function setCache(\n key: string,\n data: T,\n ttl?: number,\n staleTime?: number,\n): void {\n if (ttl === 0) {\n deleteCache(key);\n return;\n }\n\n const time = timeNow();\n const ttlMs = ttl ? ttl * 1000 : 0;\n const staleTimeMs = staleTime ? staleTime * 1000 : 0; // Ensure default value for staleTime\n\n _cache.set(key, {\n data,\n time,\n stale: staleTimeMs > 0 ? time + staleTimeMs : undefined, // Use undefined if staleTime is not set\n expiry: ttl === -1 ? undefined : time + ttlMs,\n });\n\n if (ttlMs > 0) {\n scheduleExpiry(key, ttlMs);\n }\n}\n\n/**\n * Deletes a cache entry once it expires.\n *\n * @param {string} key Cache key to utilize\n * @param {number} ms - The time until the entry expires, in milliseconds.\n */\nfunction scheduleExpiry(key: string, ms: number): void {\n addTimeout('c:' + key, () => deleteCache(key, true), ms);\n}\n\n/**\n * Invalidates (deletes) a cache entry.\n *\n * @param {string} key Cache key to utilize\n * @param {boolean} [removeExpired=false] - If true, only deletes the cache entry if it is expired or stale.\n */\nexport function deleteCache(key: string, removeExpired: boolean = false): void {\n if (removeExpired) {\n const entry = getCache(key);\n\n // If the entry does not exist, or it is neither expired nor stale, do not delete\n if (!entry || !isCacheExpired(entry)) {\n return;\n }\n }\n\n _cache.delete(key);\n\n const store = stores.get(key);\n\n if (store) {\n stores.delete(key);\n callStore(() => store.delete(key));\n }\n}\n\n/**\n * Prunes the cache by removing entries that have expired based on the provided cache time.\n */\nexport function pruneCache(): void {\n _cache.clear();\n stores.clear();\n}\n\n/**\n * Calls a cache store method. Store errors, e.g. of a full localStorage, are ignored so that they can't break requests.\n *\n * @param {() => unknown} fn - The function calling the store.\n */\nfunction callStore(fn: () => unknown): void {\n try {\n Promise.resolve(fn()).catch(noop);\n } catch {\n // Ignored\n }\n}\n\n/**\n * Saves a copy of a cached response in a cache store, so that it can be restored later, e.g. after a page reload.\n *\n * @param {string} key Cache key to utilize\n * @param {CacheStore} [store] - The cache store. If not provided, nothing is saved.\n */\nfunction persistCache(key: string, store?: CacheStore): void {\n const entry = _cache.get(key);\n\n if (store && entry) {\n const { data, status, statusText, headers } = entry.data as FetchResponse;\n\n stores.set(key, store);\n callStore(() =>\n store.set(key, { ...entry, data: { data, status, statusText, headers } }),\n );\n }\n}\n\n/**\n * Reads the entry of a cache key from the cache store of a request, e.g. one saved during a previous page load.\n * Expired entries are deleted from the store.\n *\n * @param {string} key Cache key to utilize\n * @param {RequestConfig} requestConfig - The request configuration.\n * @returns {Promise | null>} - The stored entry, or null if there is no valid one or the in-memory cache has an entry already.\n */\nexport async function getStoredCache(\n key: string,\n requestConfig: RequestConfig,\n): Promise | null> {\n const store = requestConfig.cacheStore;\n\n if (!store || isCacheBypassed(requestConfig)) {\n return null;\n }\n\n let entry: CacheEntry | null | undefined;\n\n try {\n entry = await store.get(key);\n } catch {\n // A failing store is treated like an empty one\n return null;\n }\n\n // Another request may have cached a response in the meantime\n if (!entry || _cache.has(key)) {\n return null;\n }\n\n if (isCacheExpired(entry)) {\n callStore(() => store.delete(key));\n\n return null;\n }\n\n return entry;\n}\n\n/**\n * Caches a response restored from a cache store in memory, keeping its original stale and expiry times.\n *\n * @param {string} key Cache key to utilize\n * @param {CacheEntry} entry - The cache entry with the restored response.\n * @param {CacheStore} store - The cache store that the response was restored from.\n * @returns {boolean} - True if the restored response is fresh, false if it's stale.\n */\nexport function restoreCache(\n key: string,\n entry: CacheEntry,\n store: CacheStore,\n): boolean {\n _cache.set(key, entry);\n stores.set(key, store);\n\n if (entry.expiry) {\n scheduleExpiry(key, entry.expiry - timeNow());\n }\n\n notifySubscribers(key, entry.data);\n\n return !entry.stale || timeNow() < entry.stale;\n}\n\n/**\n * Mutates a cache entry with new data and optionally revalidates it.\n *\n * @param {string | null} key Cache key to utilize. If null, no mutation occurs.\n * @param {ResponseData} newData - The new data to be cached.\n * @param {MutationSettings|undefined} settings - Mutation settings.\n */\nexport async function mutate<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n key: string | null,\n newData: ResponseData,\n settings?: MutationSettings,\n): Promise | null> {\n // If no key is provided, do nothing\n if (!key) {\n return null;\n }\n\n const entry = getCache(\n key,\n );\n\n if (!entry) {\n return null;\n }\n\n const updatedData = isObject(newData) ? sanitizeObject(newData) : newData;\n\n const updatedResponse = {\n ...entry.data,\n data: updatedData,\n };\n\n // The ETag belongs to the original data, so the changed data must not be revalidated with it\n const headers = updatedResponse.headers;\n\n if (headers && headers.etag) {\n updatedResponse.headers = { ...headers };\n delete updatedResponse.headers.etag;\n }\n\n const updatedEntry = {\n ...entry,\n data: updatedResponse,\n };\n\n _cache.set(key, updatedEntry);\n persistCache(key, stores.get(key));\n notifySubscribers(key, updatedResponse);\n\n if (settings && settings.refetch) {\n return await revalidate(key);\n }\n\n return null;\n}\n\n/**\n * Checks whether a request should bypass the cache, because of its cache buster or `cache: 'reload'`.\n *\n * @param {RequestConfig} requestConfig - The request configuration.\n * @returns {boolean} - True if the cache should be bypassed.\n */\nexport function isCacheBypassed(requestConfig: RequestConfig): boolean {\n const buster = requestConfig.cacheBuster || defaultConfig.cacheBuster;\n\n return (\n !!(buster && buster(requestConfig)) || requestConfig.cache === 'reload'\n );\n}\n\n/**\n * Retrieves a cached response if available and valid, otherwise returns null.\n *\n * @template ResponseData - The type of the response data.\n * @template RequestBody - The type of the request body.\n * @template QueryParams - The type of the query parameters.\n * @template PathParams - The type of the path parameters.\n * @param {string | null} cacheKey - The cache key to look up.\n * @param {number | undefined} cacheTime - The maximum time to cache entry.\n * @param {RequestConfig} requestConfig - The fetcher configuration.\n * @returns {FetchResponse | null} - The cached response or null.\n */\nexport function getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n cacheKey: string | null,\n cacheTime: number | undefined,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): FetchResponse | null {\n // If cache key or time is not provided, return null\n if (!cacheKey || cacheTime === undefined || cacheTime === null) {\n return null;\n }\n\n if (isCacheBypassed(requestConfig)) {\n return null;\n }\n\n // Retrieve the cached entry\n const entry = getCache(\n cacheKey,\n );\n\n if (!entry) {\n return null;\n }\n\n const isExpired = isCacheExpired(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n const data = entry.data;\n\n // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n // The placeholder stored while a request is in flight is not a response, so treat it as a miss\n return data && data.isFetching ? null : data;\n}\n\n/**\n * Sets or deletes the response cache based on cache settings and notifies subscribers.\n *\n * @param {FetchResponse} output - The response to cache.\n * @param {RequestConfig} requestConfig - The request configuration.\n * @param {boolean} [isError=false] - Whether the response is an error.\n */\nexport function handleResponseCache<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n output: FetchResponse,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n isError: boolean = false,\n): void {\n // It is string as it is called once request is made\n const cacheKey = requestConfig.cacheKey as string;\n\n if (cacheKey) {\n const cacheTime = requestConfig.cacheTime;\n const skipCache = requestConfig.skipCache;\n\n // Fast path: only set cache if cacheTime is positive and not skipping cache\n if (\n cacheTime &&\n (!isError || requestConfig.cacheErrors) &&\n !(skipCache && skipCache(output, requestConfig))\n ) {\n setCache(cacheKey, output, cacheTime, requestConfig.staleTime);\n\n // Error responses are only cached in memory\n if (!isError) {\n persistCache(cacheKey, requestConfig.cacheStore);\n }\n } else {\n const entry = getCache(cacheKey);\n\n // Don't let the in-flight placeholder outlive a request whose result isn't cached\n if (entry && entry.data && entry.data.isFetching) {\n deleteCache(cacheKey);\n }\n }\n\n notifySubscribers(cacheKey, output);\n removeInFlight(cacheKey);\n\n const prevCacheKey = requestConfig._prevKey;\n\n if (prevCacheKey) {\n removeInFlight(prevCacheKey);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { mutate } from './cache-manager';\nimport {\n APPLICATION_CONTENT_TYPE,\n APPLICATION_JSON,\n CONTENT_TYPE,\n FUNCTION,\n STRING,\n} from './constants';\nimport {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n ResponseError,\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n} from './types';\nimport { flattenData, isObject, processHeaders } from './utils';\n\n/**\n * Parses the response data based on the Content-Type header, or reads it as the given response type.\n *\n * @param response - The Response object to parse.\n * @param responseType - How to read the body regardless of its Content-Type, e.g. as a Blob, or `'stream'` to leave it unread.\n * @returns A Promise that resolves to the parsed data.\n */\nexport async function parseResponseData<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse,\n responseType?: RequestConfig['responseType'],\n): Promise {\n // Bail early if response is null or undefined\n if (!response) {\n return null;\n }\n\n // Get the content-type header once\n const headers = (response as Response).headers;\n let contentType = headers && headers.get(CONTENT_TYPE);\n\n if (contentType) {\n // Lowercase and trim for consistent matching\n contentType = contentType.toLowerCase().trim();\n } else {\n contentType = '';\n }\n\n // Split for mime type without charset\n const mimeType = contentType.split(';', 1)[0];\n\n let data;\n\n try {\n if (responseType) {\n // The body is read as requested, or left unread as a stream to be read by the caller\n data =\n responseType === 'stream'\n ? response.body\n : await response[responseType]();\n } else if (\n mimeType.includes(APPLICATION_JSON) ||\n mimeType.includes('+json')\n ) {\n data = await response.json(); // Parse JSON response\n } else if (\n (mimeType.includes('multipart/form-data') || // Parse as FormData\n mimeType.includes(\n APPLICATION_CONTENT_TYPE + 'x-www-form-urlencoded', // Handle URL-encoded forms\n )) &&\n typeof response.formData === FUNCTION\n ) {\n data = await response.formData();\n } else if (/^(image|video|audio)\\/|octet-stream|pdf|zip/.test(mimeType)) {\n data = await response.arrayBuffer(); // Parse as ArrayBuffer for binary types\n } else {\n data = await response.text();\n\n if (typeof data === STRING) {\n const trimmed = data.trim();\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n data = JSON.parse(trimmed);\n } catch {\n // leave as text if parsing fails\n }\n }\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\n/**\n * Prepare response object with additional information.\n *\n * @param Response. It may be \"null\" in case of request being aborted.\n * @param {RequestConfig} config - Request config\n * @param error - whether the response is erroneous\n * @returns {FetchResponse} Response data\n */\nexport const prepareResponse = <\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n config: RequestConfig,\n error: ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null,\n): FetchResponse => {\n const defaultResponse = config.defaultResponse;\n const cacheKey = config.cacheKey;\n const mutatator = mutate.bind(null, cacheKey as string) as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >['mutate'];\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 ?? null,\n headers: null,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: false,\n isError: true,\n } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n const isNativeResponse =\n typeof Response === FUNCTION && response instanceof Response;\n\n let data = response.data;\n\n // Set the default response if the provided data is an empty object or array\n // Other objects, e.g. Blobs, buffers and streams, have no keys either, but aren't empty\n if (\n defaultResponse !== undefined &&\n (data === undefined ||\n data === null ||\n (/^\\[object (Object|Array)\\]$/.test(\n Object.prototype.toString.call(data),\n ) &&\n Object.keys(data).length === 0))\n ) {\n response.data = data = defaultResponse;\n }\n\n if (config.flattenResponse) {\n response.data = data = flattenData(data);\n }\n\n if (config.select) {\n response.data = data = config.select(data);\n }\n\n const headers = processHeaders(response.headers);\n\n // Native fetch Response extended by extra information\n if (isNativeResponse) {\n const output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > = {\n body: response.body,\n bodyUsed: response.bodyUsed,\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 // Convert methods to use arrow functions to preserve correct return types\n // Lazily construct Blob from ArrayBuffer\n blob: async () =>\n data instanceof ArrayBuffer ? new Blob([data]) : new Blob(),\n json: async () => data as ResponseData, // Return the already parsed JSON data\n text: async () => data as string, // Return the already parsed text data\n // The body was already read, so a copy of this response is returned instead of Response.clone()\n clone: () => ({ ...output }),\n arrayBuffer: async () =>\n data instanceof ArrayBuffer ? data : new ArrayBuffer(0), // Return the ArrayBuffer directly\n formData: async () => (data instanceof FormData ? data : new FormData()), // Return the already parsed FormData\n bytes: async () =>\n new Uint8Array(data instanceof ArrayBuffer ? data : new ArrayBuffer(0)),\n // Enhance the response with extra information\n error,\n data,\n headers,\n config,\n mutate: mutatator,\n isFetching: false,\n isSuccess: response.ok && !error,\n isError: !!error,\n };\n\n return output;\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 (isObject(response)) {\n // Assigned one by one, as Object.assign() with an object literal is measurably slower here\n response.error = error;\n response.headers = headers;\n response.isFetching = false;\n response.mutate = mutatator;\n response.isSuccess = response.ok && !error;\n response.isError = !!error;\n }\n\n return response;\n};\n","import { applyInterceptors } from './interceptor-manager';\nimport type { FetchResponse, RetryConfig, RetryFunction } from './types';\nimport { delayInvocation, timeNow } from './utils';\nimport { generateCacheKey } from './cache-manager';\nimport { FUNCTION } from './constants';\n\nfunction getMsFromHttpDate(dateString: string): number | null {\n const ms = Date.parse(dateString) - timeNow();\n\n if (!isNaN(ms)) {\n return Math.max(0, Math.floor(ms));\n }\n return null;\n}\n\n/**\n * Calculates the number of milliseconds to wait before retrying a request,\n * based on the `Retry-After` HTTP header in the provided response.\n *\n * The function supports both numeric (seconds) and HTTP-date formats for the `Retry-After` header.\n * - If the header is a number, it is interpreted as seconds and converted to milliseconds.\n * - If the header is a date, the function calculates the difference between the date and the current time.\n *\n * @param extendedResponse - The response object containing headers, or `null`.\n * @returns The number of milliseconds to wait before retrying, or `null` if the header is not present or invalid.\n */\nexport function getRetryAfterMs(\n extendedResponse: FetchResponse | null,\n): number | null {\n if (!extendedResponse) {\n return null;\n }\n\n const headers = extendedResponse.headers || {};\n const retryAfter = headers['retry-after'];\n\n if (retryAfter) {\n // Try parsing as seconds\n const seconds = Number(retryAfter);\n\n if (!isNaN(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n const ms = getMsFromHttpDate(retryAfter);\n\n if (ms !== null) {\n return ms;\n }\n }\n\n // Headers are already in lowercase\n const RATELIMIT_RESET = 'ratelimit-reset';\n\n // Unix timestamp when the rate limit window resets (relative to current time)\n // Fallback to checking 'ratelimit-reset-after' OR 'x-ratelimit-reset-after' headers\n const rateLimitResetAfter =\n headers[RATELIMIT_RESET + '-after'] ||\n headers['x-' + RATELIMIT_RESET + '-after'];\n\n if (rateLimitResetAfter) {\n const seconds = Number(rateLimitResetAfter);\n\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n }\n\n // ISO 8601 datetime when the rate limit resets\n // Fallback to checking 'ratelimit-reset-at' 'x-ratelimit-reset-at' headers\n const rateLimitResetAt =\n headers[RATELIMIT_RESET + '-at'] || headers['x-' + RATELIMIT_RESET + '-at'];\n\n if (rateLimitResetAt) {\n return getMsFromHttpDate(rateLimitResetAt);\n }\n\n return null;\n}\n\n/**\n * Executes a request function with retry logic according to the provided configuration.\n *\n * The function attempts the request up to the specified number of retries, applying delay and backoff strategies.\n * Retries can be triggered based on response status codes, custom logic, or the presence of a `Retry-After` header.\n * Optionally, an `onRetry` interceptor can be invoked before each retry attempt.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param requestFn - The function that performs the request. Receives `isStaleRevalidation` and `attempt` as arguments.\n * @param config - The retry configuration, including retry count, delay, backoff, retry conditions, and hooks.\n * @returns A promise resolving to the fetch response, or rejecting if all retries are exhausted.\n * @throws Error if the maximum number of retries is exceeded or a non-retriable error occurs.\n */\nexport async function withRetry<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation: boolean,\n attempt: number,\n ) => Promise<\n FetchResponse\n >,\n config: RetryConfig,\n): Promise> {\n const {\n retries = 0,\n delay = 0,\n backoff = 1,\n maxDelay,\n retryOn = [],\n shouldRetry,\n jitter,\n methods,\n } = config;\n\n let attempt = 0;\n let waitTime = delay;\n const maxRetries = retries > 0 ? retries : 0;\n let output: FetchResponse;\n\n while (attempt <= maxRetries) {\n // Subsequent attempts will have output defined, but the first attempt may not.\n // Let's apply onRetry interceptor and regenerate cache key if ot really changes.\n if (attempt > 0 && output!) {\n const cfg = output.config;\n const onRetry = cfg.onRetry;\n\n if (onRetry) {\n await applyInterceptors(onRetry, output, attempt);\n\n // If the key was automatically generated, we need to regenerate it as config may change.\n // We don't detect whether config changed for performance reasons.\n if (cfg._isAutoKey) {\n cfg._prevKey = cfg.cacheKey as string;\n cfg.cacheKey = generateCacheKey(cfg, false);\n }\n }\n }\n\n // Performance optimization: Call the request function with the current attempt number\n // If this is the first attempt, we pass `isStaleRevalidation` as `false`,\n // otherwise we pass `true` to indicate that this is a stale revalidation (no cache hit).\n output = await requestFn(attempt > 0, attempt);\n const error = output.error;\n\n // Stop unless a failed response should be retried according to the retry settings,\n // or a successful one according to shouldRetry\n if (\n error\n ? await getShouldStopRetrying(\n output,\n attempt,\n maxRetries,\n shouldRetry,\n retryOn,\n methods,\n )\n : !(\n shouldRetry &&\n attempt < maxRetries &&\n (await shouldRetry(output, attempt))\n )\n ) {\n break;\n }\n\n // The delay before the next retry, randomized with jitter unless the server asks for one below\n let retryDelay = withJitter(waitTime, jitter);\n\n // Handle rate limiting if the error status is 429 (Too Many Requests) or 503 (Service Unavailable)\n if (error && (error.status === 429 || error.status === 503)) {\n // Try to extract the \"Retry-After\" value from the response headers\n const retryAfterMs = getRetryAfterMs(output);\n\n // If a valid retry-after value is found, override the wait time before next retry\n // Cap it with maxDelay so that a server can't make the client wait indefinitely\n if (retryAfterMs !== null) {\n retryDelay = waitTime = Math.min(\n retryAfterMs,\n maxDelay || retryAfterMs,\n );\n }\n }\n\n await delayInvocation(retryDelay);\n waitTime *= backoff || 1;\n waitTime = Math.min(waitTime, maxDelay || waitTime);\n attempt++;\n }\n\n return output!;\n}\n\n/**\n * Determines whether to stop retrying based on the error, current attempt count, and retry configuration.\n *\n * This function checks:\n * - If the maximum number of retries has been reached.\n * - If the request was aborted, e.g. with its signal or by a newer request. Aborted requests are never retried.\n * - If a custom `shouldRetry` callback is provided, its result is used to decide.\n * - If no custom logic is provided, falls back to checking if the error status is included in the `retryOn` list,\n * and the request method in the `methods` list, if any.\n *\n * @typeParam ResponseData - The type of the response data.\n * @typeParam RequestBody - The type of the request body.\n * @typeParam QueryParams - The type of the query parameters.\n * @typeParam PathParams - The type of the path parameters.\n * @param output - The response object containing the error and request configuration.\n * @param attempt - The current retry attempt number.\n * @param maxRetries - The maximum number of retry attempts allowed.\n * @param shouldRetry - Optional custom function to determine if a retry should occur.\n * @param retryOn - Optional list of HTTP status codes that should trigger a retry.\n * @param methods - Optional list of request methods that are retried on the `retryOn` statuses. All methods are retried without it.\n * @returns A promise resolving to `true` if retrying should stop, or `false` to continue retrying.\n */\nexport async function getShouldStopRetrying<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n output: FetchResponse,\n attempt: number,\n maxRetries: number,\n shouldRetry?: RetryFunction<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n retryOn: number[] = [],\n methods?: string[],\n): Promise {\n // Safety first: always respect max retries\n // We check retries provided regardless of the shouldRetry being provided so to avoid infinite loops.\n // It is a fail-safe so to prevent excessive retry attempts even if custom retry logic suggests a retry.\n if (attempt === maxRetries) {\n return true;\n }\n\n // Aborted requests are never retried, as e.g. a retry of one cancelled by a newer request would cancel the newer one\n if (output.error?.isCancelled) {\n return true;\n }\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n\n if (result !== null) {\n return !result;\n }\n }\n\n return !(\n (retryOn || []).includes(output.error?.status ?? 0) &&\n (!methods ||\n methods.some((method) => method.toUpperCase() === output.config.method))\n );\n}\n\n/**\n * Randomizes a retry delay with jitter, so that clients that failed at the same time, e.g. during an outage, don't retry all at once.\n *\n * @param delay - The delay computed from the `delay`, `backoff` and `maxDelay` settings, in milliseconds.\n * @param jitter - `true` for a random delay between 0 and the computed one (\"full jitter\"), or a function that returns the delay to use.\n * @returns The delay to wait before the retry, in milliseconds.\n */\nfunction withJitter(delay: number, jitter: RetryConfig['jitter']): number {\n return typeof jitter === FUNCTION\n ? (jitter as (delay: number) => number)(delay)\n : jitter\n ? Math.random() * delay\n : delay;\n}\n","import type { RequestConfig, FetchResponse } from './types';\nimport { delayInvocation, isOffline, isPageHidden } from './utils';\n\n/**\n * Executes a request function with polling, stopping when shouldStopPolling returns true,\n * pollingInterval is not set, or maxAttempts is reached.\n * Polling pauses while the page is hidden or the browser is offline, unless allowed by refreshWhenHidden or refreshWhenOffline.\n *\n * @template Output The type of the output returned by the request function.\n * @param requestFn - The function that performs a single request (with retries).\n * @param pollingInterval - Interval in ms between polling attempts.\n * @param shouldStopPolling - Function to determine if polling should stop.\n * @param maxAttempts - Maximum number of polling attempts, default: 0 (unlimited).\n * @param pollingDelay - Delay in ms before each polling attempt, default: 0.\n * @param refreshWhenHidden - Whether to keep polling while the page is hidden, default: false.\n * @param refreshWhenOffline - Whether to keep polling while the browser is offline, default: false.\n * @param signal - The signal passed to the request. Polling stops once it is aborted.\n * @returns The final output from the last request.\n */\nexport async function withPolling<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams,\n>(\n requestFn: (\n isStaleRevalidation?: boolean,\n attempt?: number,\n ) => Promise<\n FetchResponse\n >,\n pollingInterval?: RequestConfig['pollingInterval'],\n shouldStopPolling?: RequestConfig['shouldStopPolling'],\n maxAttempts = 0,\n pollingDelay = 0,\n refreshWhenHidden = false,\n refreshWhenOffline = false,\n signal?: AbortSignal,\n): Promise> {\n if (!pollingInterval) {\n return requestFn();\n }\n\n let pollingAttempt = 0;\n let output: FetchResponse;\n\n while (maxAttempts === 0 || pollingAttempt < maxAttempts) {\n if (pollingDelay > 0) {\n await delayInvocation(pollingDelay, signal);\n }\n\n output = await requestFn();\n\n pollingAttempt++;\n\n if (\n (maxAttempts > 0 && pollingAttempt >= maxAttempts) ||\n !pollingInterval ||\n (shouldStopPolling && shouldStopPolling(output, pollingAttempt))\n ) {\n break;\n }\n\n // Wait for the next attempt, and keep waiting while polling is paused\n do {\n await delayInvocation(pollingInterval, signal);\n\n // Aborting the signal of the request stops polling\n if (signal && signal.aborted) {\n return output;\n }\n } while (\n (!refreshWhenHidden && isPageHidden()) ||\n (!refreshWhenOffline && isOffline())\n );\n }\n\n return output!;\n}\n","import { ABORT_ERROR, UNDEFINED } from './constants';\nimport type { RequestConfig, UploadProgress } from './types';\nimport { createAbortError } from './utils';\n\n// Responses with these statuses can't have a body\nconst NULL_BODY_STATUSES = [204, 205, 304];\n\n// Headers that browsers don't let requests set. fetch() skips them silently, while\n// XMLHttpRequest logs errors for them, so they are skipped before sending.\nconst FORBIDDEN_HEADERS =\n /^(accept-charset|accept-encoding|connection|content-length|cookie2?|date|dnt|expect|host|keep-alive|origin|referer|set-cookie|te|trailer|transfer-encoding|upgrade|via)$|^(proxy-|sec-|access-control-request-)/;\n\n// ReadableStream is missing in some environments, e.g. React Native\nconst isStream = (body: unknown): body is ReadableStream =>\n typeof ReadableStream !== UNDEFINED && body instanceof ReadableStream;\n\nexport const toProgress = (loaded: number, total?: number): UploadProgress => ({\n loaded,\n total,\n progress: total ? loaded / total : undefined,\n});\n\n/**\n * Sends a request and reports the upload progress of its body to `onUploadProgress`.\n * Browsers and React Native don't report the upload progress of fetch(), so XMLHttpRequest is used there.\n * Elsewhere, e.g. in Node.js, the body is streamed with fetch() and counted while it is sent.\n *\n * @param {string} url - The request URL.\n * @param {RequestConfig} config - The request configuration, with a body and `onUploadProgress`.\n * @returns {Promise} - The response.\n */\nexport function fetchWithUploadProgress(\n url: string,\n config: RequestConfig,\n): Promise {\n const body = config.body as BodyInit;\n\n return typeof XMLHttpRequest !== UNDEFINED && !isStream(body)\n ? sendWithXhr(url, config, body)\n : sendStreamed(url, config, body);\n}\n\nfunction sendWithXhr(\n url: string,\n config: RequestConfig,\n body: BodyInit,\n): Promise {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n // fetchf() always sets the signal, as it handles timeouts and cancellation with it\n const signal = config.signal!;\n const abort = () => xhr.abort();\n\n const settle = (fn: () => void) => {\n signal.removeEventListener('abort', abort);\n\n try {\n fn();\n } catch (error) {\n reject(error);\n }\n };\n\n xhr.open(config.method as string, url);\n xhr.responseType = 'blob';\n xhr.withCredentials = config.credentials === 'include';\n\n new Headers(config.headers).forEach(\n (value, name) =>\n FORBIDDEN_HEADERS.test(name) || xhr.setRequestHeader(name, value),\n );\n\n xhr.upload.onprogress = (event) =>\n config.onUploadProgress!(\n toProgress(\n event.loaded,\n event.lengthComputable ? event.total : undefined,\n ),\n );\n\n xhr.onload = () =>\n settle(() => {\n const headers = new Headers();\n\n for (const line of xhr.getAllResponseHeaders().split(/\\r?\\n/)) {\n const index = line.indexOf(':');\n\n if (index > 0) {\n headers.append(line.slice(0, index), line.slice(index + 1).trim());\n }\n }\n\n const response = new Response(\n NULL_BODY_STATUSES.includes(xhr.status) ? null : xhr.response,\n { status: xhr.status, statusText: xhr.statusText, headers },\n );\n\n // Like fetch(), the response tells its final URL, e.g. after redirects\n Object.defineProperty(response, 'url', { value: xhr.responseURL });\n\n resolve(response);\n });\n\n xhr.onerror = () =>\n settle(() => reject(new TypeError('Network request failed')));\n\n // Like fetch(), aborted requests reject with the reason of the abort signal\n const onAbort = () =>\n settle(() =>\n reject(\n signal.reason ||\n createAbortError('The request was aborted', ABORT_ERROR),\n ),\n );\n\n xhr.onabort = onAbort;\n\n if (signal.aborted) {\n return onAbort();\n }\n\n signal.addEventListener('abort', abort);\n\n xhr.send(body as XMLHttpRequestBodyInit);\n });\n}\n\nasync function sendStreamed(\n url: string,\n config: RequestConfig,\n body: BodyInit,\n): Promise {\n const headers = new Headers(config.headers);\n let stream = body as ReadableStream;\n let total: number | undefined;\n\n if (!isStream(body)) {\n // Serialize the body like fetch() would, to know its size and content type\n const blob = body instanceof Blob ? body : await new Response(body).blob();\n\n total = blob.size;\n stream = blob.stream();\n\n if (blob.type && !headers.has('content-type')) {\n headers.set('content-type', blob.type);\n }\n }\n\n let loaded = 0;\n\n return fetch(url, {\n ...config,\n headers,\n body: stream.pipeThrough(\n new TransformStream({\n transform(chunk, controller) {\n loaded += chunk.byteLength;\n config.onUploadProgress!(toProgress(loaded, total));\n controller.enqueue(chunk);\n },\n }),\n ),\n // Required by fetch() to send a stream\n duplex: 'half',\n } as RequestInit);\n}\n","import { FUNCTION } from './constants';\nimport type { DownloadProgress } from './types';\nimport { toProgress } from './upload-progress';\n\n/**\n * Reports the download progress of a response body to `onDownloadProgress` while the body is read.\n * The body is counted as it arrives, so the progress follows the download.\n *\n * @param {T} response - The response. Other than native responses with a body, e.g. responses of HEAD requests or custom fetchers, are returned as they are.\n * @param {Function} [onDownloadProgress] - The function called with the progress. Without it, the response is returned as it is.\n * @returns {T} - A copy of the response, whose body is counted while it's read.\n */\nexport function withDownloadProgress(\n response: T,\n onDownloadProgress?: (progress: DownloadProgress) => void,\n): T {\n // Response is missing in some environments, and response bodies e.g. in React Native\n if (\n !onDownloadProgress ||\n typeof Response !== FUNCTION ||\n !(response instanceof Response) ||\n !response.body\n ) {\n return response;\n }\n\n const headers = response.headers;\n // Content-Length is the size of the compressed body, so the size of a compressed one is unknown\n const total = headers.has('content-encoding')\n ? undefined\n : Number(headers.get('content-length')) || undefined;\n let loaded = 0;\n\n const counted = new Response(\n response.body.pipeThrough(\n new TransformStream({\n transform(chunk, controller) {\n loaded += chunk.byteLength;\n // Browsers may hide the Content-Encoding header of cross-origin responses, so the progress is capped at 1\n onDownloadProgress(\n toProgress(loaded, total && Math.max(total, loaded)),\n );\n controller.enqueue(chunk);\n },\n }),\n ),\n response,\n );\n\n // Like the original response, the copy tells its final URL, whether it was redirected and its type\n for (const key of ['url', 'redirected', 'type'] as const) {\n Object.defineProperty(counted, key, { value: response[key] });\n }\n\n return counted as T;\n}\n","import type { ResponseError } from './errors/response-error';\nimport type {\n DefaultResponse,\n FetchResponse,\n RequestConfig,\n} from './types/request-handler';\nimport { applyInterceptors } from './interceptor-manager';\nimport { handleResponseCache } from './cache-manager';\nimport { ABORT_ERROR, REJECT } from './constants';\nimport {\n DefaultParams,\n DefaultUrlParams,\n DefaultPayload,\n HeadersObject,\n} from './types';\nimport { processHeaders } from './utils';\n\n/**\n * Handles final processing for both success and error responses\n * Applies error interceptors, caching, notifications, and error strategy\n */\nexport async function withErrorHandling<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n isStaleRevalidation: boolean,\n requestFn: (\n isStaleRevalidation: boolean,\n ) => Promise<\n FetchResponse\n >,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): Promise> {\n const output = await requestFn(isStaleRevalidation);\n const error = output.error;\n\n if (!error) {\n // SUCCESS PATH\n handleResponseCache(output, requestConfig);\n\n return output;\n }\n\n // ERROR PATH\n\n if (requestConfig.onError) {\n await applyInterceptors(requestConfig.onError, error);\n }\n\n // Timeouts and request cancellations using AbortController do not throw any errors unless rejectCancelled is true.\n // Only handle the error if the request was not cancelled, or if it was cancelled and rejectCancelled is true.\n const isCancelled = error.isCancelled;\n\n const logger = requestConfig.logger;\n\n if (!isCancelled && logger && logger.warn) {\n logger.warn('FETCH ERROR', redactError(error as ResponseError));\n }\n\n // The defaultResponse strategy returns the default response in place of the error data.\n // The original data stays available through error.response.\n if (requestConfig.strategy === 'defaultResponse') {\n output.data = (requestConfig.defaultResponse ?? null) as typeof output.data;\n }\n\n // Handle cache and notifications FIRST (before strategy)\n handleResponseCache(output, requestConfig, true);\n\n // handle error strategy as the last part\n const shouldHandleError = !isCancelled || requestConfig.rejectCancelled;\n\n if (shouldHandleError) {\n const strategy = requestConfig.strategy;\n // Reject the promise\n if (strategy === REJECT) {\n throw error;\n }\n\n // Hang the promise\n if (strategy === 'silent') {\n await new Promise(() => null);\n }\n }\n\n return output;\n}\n\n// Credential headers that must not end up in logs\nconst SENSITIVE_HEADERS = [\n 'authorization',\n 'proxy-authorization',\n 'cookie',\n 'x-api-key',\n];\n\n/**\n * Creates a copy of the error for logging, with credential headers masked and the request body removed.\n * The error itself is left untouched.\n */\nfunction redactError(error: ResponseError): ResponseError {\n // Cache keys are dropped too, as they can contain short request bodies\n const config = {\n ...error.config,\n body: undefined,\n data: undefined,\n cacheKey: undefined,\n _prevKey: undefined,\n headers: processHeaders(error.config.headers as HeadersObject),\n };\n\n for (const name of SENSITIVE_HEADERS) {\n if (config.headers[name]) {\n config.headers[name] = '[REDACTED]';\n }\n }\n\n const copy = Object.assign(new Error(error.message), error, {\n config,\n request: config,\n response: error.response && { ...error.response, config },\n });\n\n copy.name = error.name;\n copy.stack = error.stack;\n\n return copy;\n}\n\nexport function enhanceError<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null,\n requestConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n >,\n): void {\n error.status = error.status || (response && response.status) || 0;\n error.statusText =\n error.statusText || (response && response.statusText) || '';\n error.config = error.request = requestConfig;\n error.response = response;\n error.isCancelled = error.name === ABORT_ERROR;\n}\n","import type {\n DefaultResponse,\n RequestConfig,\n FetchResponse,\n HeadersObject,\n} from './types/request-handler';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultUrlParams,\n} from './types/api-handler';\nimport type { StoredResponse } from './types/cache-manager';\nimport { applyInterceptors } from './interceptor-manager';\nimport { ResponseError } from './errors/response-error';\nimport { isObject, noop, processHeaders } from './utils';\nimport {\n markInFlight,\n setInFlightPromise,\n getInFlightPromise,\n} from './inflight-manager';\nimport { parseResponseData, prepareResponse } from './response-parser';\nimport {\n generateCacheKey,\n getCacheData,\n getCachedResponse,\n getStoredCache,\n isCacheBypassed,\n restoreCache,\n setCache,\n} from './cache-manager';\nimport { withRetry } from './retry-handler';\nimport { withPolling } from './polling-handler';\nimport { fetchWithUploadProgress } from './upload-progress';\nimport { withDownloadProgress } from './download-progress';\nimport { notifySubscribers } from './pubsub-manager';\nimport { addRevalidator } from './revalidator-manager';\nimport { enhanceError, withErrorHandling } from './error-handler';\nimport { FUNCTION, GET, HEAD } from './constants';\nimport { buildConfig } from './config-handler';\n\nconst inFlightResponse = Object.freeze({\n isFetching: true,\n});\n\n/**\n * Sends an HTTP request to the specified URL using the provided configuration and returns a typed response.\n *\n * @typeParam ResponseData - The expected shape of the response data. Defaults to `DefaultResponse`.\n * @typeParam RequestBody - The type of the request payload/body. Defaults to `DefaultPayload`.\n * @typeParam QueryParams - The type of the query parameters. Defaults to `DefaultParams`.\n * @typeParam PathParams - The type of the path parameters. Defaults to `DefaultUrlParams`.\n *\n * @param url - The endpoint URL to which the request will be sent.\n * @param config - Optional configuration object for the request, including headers, method, body, query, and path parameters.\n *\n * @returns A promise that resolves to a `FetchResponse` containing the typed response data and request metadata.\n *\n * @example\n * ```typescript\n * const { data } = await fetchf('/api/user', { method: 'GET' });\n * console.log(data);\n * ```\n */\nexport async function fetchf<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string,\n reqConfig: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > | null = null,\n): Promise> {\n // Ultra-fast early cache check if cacheKey is provided as a string\n // For workloads dominated by repeated requests, this string caching optimization\n // can potentially support millions of requests per second with minimal CPU overhead\n if (reqConfig && typeof reqConfig.cacheKey === 'string') {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(reqConfig.cacheKey, reqConfig.cacheTime, reqConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n const fetcherConfig = buildConfig<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(url, reqConfig);\n\n const {\n timeout,\n cancellable,\n cacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n refetchOnFocus,\n refetchOnReconnect,\n pollingInterval = 0,\n } = fetcherConfig;\n const isCacheEnabled = cacheTime !== undefined || staleTime !== undefined;\n const method = fetcherConfig.method;\n\n // Cached responses of GET and HEAD requests are revalidated with their ETag.\n // Custom fetchers may not handle 304 responses, so they only send it when it's enabled for them.\n const isETagEnabled =\n isCacheEnabled &&\n (method === GET || method === HEAD) &&\n (fetcherConfig.etag ?? !fetcherConfig.fetcher);\n\n const needsCacheKey = !!(\n cacheKey ||\n timeout ||\n dedupeTime ||\n isCacheEnabled ||\n cancellable ||\n refetchOnFocus ||\n refetchOnReconnect\n );\n\n let _cacheKey: string | null = null;\n\n // Generate cache key if required\n if (needsCacheKey) {\n _cacheKey = generateCacheKey(fetcherConfig);\n }\n\n // The initial data, which is used as the first response instead of sending the request\n let initialResponse: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n // Cache handling logic\n if (_cacheKey && isCacheEnabled) {\n const cached = getCachedResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(_cacheKey, cacheTime, fetcherConfig);\n\n if (cached) {\n return cached;\n }\n\n // Restore the response from the cache store, e.g. one saved during a previous page load\n if (fetcherConfig.cacheStore) {\n const stored = await getStoredCache(_cacheKey, fetcherConfig);\n const restored =\n stored &&\n toResponse(\n stored.data,\n _cacheKey,\n fetcherConfig,\n );\n\n // A stale response is shown until the request below revalidates it\n if (\n restored &&\n restoreCache(\n _cacheKey,\n { ...stored, data: restored },\n fetcherConfig.cacheStore,\n )\n ) {\n return restored;\n }\n }\n\n // While there's no cached response, the initial data, e.g. data rendered on the server, is cached as the response\n if (\n fetcherConfig.initialData !== undefined &&\n !getCacheData(_cacheKey) &&\n !isCacheBypassed(fetcherConfig)\n ) {\n initialResponse = toResponse(\n {\n data: fetcherConfig.initialData,\n status: 200,\n statusText: '',\n headers: {},\n },\n _cacheKey,\n fetcherConfig,\n );\n }\n }\n\n // Deduplication logic\n if (_cacheKey && dedupeTime) {\n const inflight = getInFlightPromise<\n FetchResponse\n >(_cacheKey, dedupeTime);\n\n if (inflight) {\n return inflight;\n }\n }\n\n const retryConfig = fetcherConfig.retry || {};\n const { retries = 0, resetTimeout } = retryConfig;\n\n // The signal passed to the request. Each attempt replaces it in the config with a signal of its own.\n const userSignal = fetcherConfig.signal;\n\n // The actual request logic as a function (one poll attempt, with retries)\n const doRequestOnce = async (isStaleRevalidation: boolean, attempt = 0) => {\n // The cached response to revalidate. It's read before the cache is marked as fetching below.\n const cached =\n isETagEnabled &&\n getCacheData(\n _cacheKey,\n );\n\n // If cache key is specified, we will handle optimistic updates\n // and mark the request as in-flight, so to catch \"fetching\" state.\n // This is useful for Optimistic UI updates (e.g., showing loading spinners).\n if (!attempt) {\n // The initial data is only used once, as the first response\n if (initialResponse) {\n const response = initialResponse;\n\n initialResponse = null;\n\n return response;\n }\n\n if (_cacheKey && !isStaleRevalidation) {\n if (staleTime) {\n const existingCache = getCachedResponse(\n _cacheKey,\n cacheTime,\n fetcherConfig,\n );\n\n // Don't notify subscribers when cache exists\n // Let them continue showing stale data during background revalidation\n if (!existingCache) {\n setCache(_cacheKey, inFlightResponse, cacheTime, staleTime);\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n } else {\n notifySubscribers(_cacheKey, inFlightResponse);\n }\n }\n\n // Attach cache key so that it can be reused in interceptors or in the final response\n fetcherConfig.cacheKey = _cacheKey;\n }\n\n const url = fetcherConfig.url as string;\n\n // Add the request to the queue. Make sure to handle deduplication, cancellation, timeouts in accordance to retry settings\n const controller = markInFlight(\n _cacheKey,\n url,\n timeout,\n dedupeTime || 0,\n !!cancellable,\n // Enable timeout either by default or when retries & resetTimeout are enabled\n !!(timeout && (!attempt || resetTimeout)),\n );\n\n // Do not create a shallow copy to maintain idempotency here.\n // This ensures the original object is mutated by interceptors whenever needed, including retry logic.\n const requestConfig = fetcherConfig;\n\n requestConfig.signal = controller.signal;\n\n // The request is aborted along with the signal passed to it, which may have been aborted already\n const abort = () => controller.abort(userSignal!.reason);\n\n if (userSignal) {\n if (userSignal.aborted) {\n abort();\n } else {\n userSignal.addEventListener('abort', abort);\n }\n }\n\n let output: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n let response: FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n > | null = null;\n\n try {\n if (fetcherConfig.onRequest) {\n // Zero-allocation yield to microtask queue so the outer fetchf() can call setInFlightPromise()\n // before onRequest interceptors run. This ensures that if onRequest triggers\n // another fetchf() with the same cacheKey, getInFlightPromise() finds item[4].\n // On retries (attempt > 0), setInFlightPromise() was already called during the first attempt.\n // The promise stored in item[4] is the outer doRequestPromise which covers all retries.\n // So the race only matters on the very first attempt when the outer scope hasn't had a chance to call setInFlightPromise() yet.\n if (_cacheKey && dedupeTime && !attempt) {\n await null;\n }\n\n await applyInterceptors(fetcherConfig.onRequest, requestConfig);\n }\n\n // Custom fetcher\n const fn = fetcherConfig.fetcher;\n const init = withETag(requestConfig, cached);\n\n response = (fn\n ? await fn(\n url,\n init,\n )\n : // Uploads with onUploadProgress are sent in a way that reports their progress\n await (requestConfig.onUploadProgress && requestConfig.body\n ? fetchWithUploadProgress(url, requestConfig)\n : fetch(url, init as RequestInit))) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Reports the download progress while the body is read\n response = withDownloadProgress(\n response,\n requestConfig.onDownloadProgress,\n );\n\n // Custom fetcher may return a raw data object instead of a Response instance\n if (isObject(response)) {\n // The server answered that the cached response is still valid, so it's reused instead of being sent again.\n // Like other cached responses, it has been parsed and transformed already.\n if (init !== requestConfig && response.status === 304) {\n return cached as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n // Case 1: Native Response instance\n if (typeof Response === FUNCTION && response instanceof Response) {\n response.data = requestConfig.parser\n ? await requestConfig.parser(response)\n : await parseResponseData(response, requestConfig.responseType);\n } else if (fn) {\n // Case 2: Custom fetcher that returns a response object\n if (!('data' in response && 'body' in response)) {\n // Case 3: Raw data, wrap it\n response = { data: response } as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n }\n\n // Attach config and data to the response\n // This is useful for custom fetchers that do not return a Response instance\n // and for interceptors that may need to access the request config\n response.config = requestConfig;\n\n // Check if the response status is not outside the range 200-299 and if so, output error\n // This is the pattern for fetch responses as per spec, but custom fetchers may not follow it so we check for `ok` property\n if (response.ok !== undefined && !response.ok) {\n throw new ResponseError(\n requestConfig.method +\n ' to ' +\n url +\n ' failed! Status: ' +\n (response.status || null),\n requestConfig,\n response,\n );\n }\n }\n\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig);\n\n const onResponse = fetcherConfig.onResponse;\n\n if (onResponse) {\n await applyInterceptors(onResponse, output);\n }\n } catch (_error) {\n const error = _error as ResponseError<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n // Append additional information to Network, CORS or any other fetch() errors\n enhanceError(\n error,\n response,\n requestConfig,\n );\n\n // Prepare Extended Response\n output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, requestConfig, error);\n } finally {\n if (userSignal) {\n userSignal.removeEventListener('abort', abort);\n }\n }\n\n return output;\n };\n\n // Inline and minimize function wrappers for performance\n // When retries are enabled, forward isStaleRevalidation so the first attempt\n // of a background SWR revalidation doesn't incorrectly mark the request as in-flight\n const baseRequest =\n retries > 0\n ? (isStaleRevalidation: boolean) =>\n withRetry(\n (_, attempt) => doRequestOnce(isStaleRevalidation, attempt),\n retryConfig,\n )\n : doRequestOnce;\n\n const { onLoadingSlow, loadingTimeout } = fetcherConfig;\n\n // Calls onLoadingSlow once a request, including its retries, is still pending after loadingTimeout.\n // Background revalidations don't show a loading state, so they are never considered slow.\n const request =\n onLoadingSlow && loadingTimeout\n ? async (isStaleRevalidation: boolean) => {\n if (isStaleRevalidation) {\n return baseRequest(isStaleRevalidation);\n }\n\n const timer = setTimeout(\n () => applyInterceptors(onLoadingSlow, fetcherConfig).catch(noop),\n loadingTimeout,\n );\n\n try {\n return await baseRequest(isStaleRevalidation);\n } finally {\n clearTimeout(timer);\n }\n }\n : baseRequest;\n\n const requestWithErrorHandling = (isStaleRevalidation = false) =>\n withErrorHandling(\n isStaleRevalidation,\n request,\n fetcherConfig,\n );\n\n // Avoid unnecessary function wrapping if polling is not enabled\n const doRequestPromise = pollingInterval\n ? withPolling(\n requestWithErrorHandling,\n pollingInterval,\n fetcherConfig.shouldStopPolling,\n fetcherConfig.maxPollingAttempts,\n fetcherConfig.pollingDelay,\n fetcherConfig.refreshWhenHidden,\n fetcherConfig.refreshWhenOffline,\n userSignal,\n )\n : requestWithErrorHandling();\n\n // If deduplication is enabled, store the in-flight promise immediately\n if (_cacheKey) {\n if (dedupeTime) {\n setInFlightPromise(_cacheKey, doRequestPromise);\n }\n\n // Only register revalidator when revalidation features are actually requested\n if (staleTime || refetchOnFocus || refetchOnReconnect) {\n addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\n fetcherConfig.focusThrottleInterval,\n );\n }\n }\n\n return doRequestPromise;\n}\n\n/**\n * Recreates a response from its copy in a cache store.\n * The data was transformed before it was stored, so it isn't transformed again.\n *\n * @param stored - The stored copy of the response.\n * @param cacheKey - The cache key of the request.\n * @param config - The request configuration.\n * @returns The response, or null if the stored copy is invalid, e.g. has an unknown status.\n */\nfunction toResponse(\n stored: StoredResponse,\n cacheKey: string,\n config: RequestConfig,\n): FetchResponse | null {\n try {\n // Without the Fetch API (e.g. with a custom fetcher in tests), a plain response object is used\n const response = (typeof Response === FUNCTION\n ? new Response(null, stored)\n : {\n ok: true,\n status: stored.status,\n statusText: stored.statusText,\n headers: stored.headers,\n }) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n\n response.data = stored.data as typeof response.data;\n config.cacheKey = cacheKey;\n\n const output = prepareResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >(response, {\n ...config,\n select: undefined,\n flattenResponse: false,\n defaultResponse: undefined,\n });\n\n output.config = config;\n\n return output;\n } catch {\n return null;\n }\n}\n\n/**\n * Asks the server whether a cached response is still valid, by sending its ETag in the If-None-Match header.\n * Then the server can answer 304 Not Modified instead of sending the response again.\n * Requests with an If-None-Match header of their own are sent as they are.\n *\n * @param config - The request configuration.\n * @param cached - The cached response of the request, if any.\n * @returns A copy of the configuration with the If-None-Match header, or the configuration itself if the cached response has no ETag.\n */\nfunction withETag(\n config: RequestConfig,\n cached: FetchResponse | null | false,\n): RequestConfig {\n const etag = cached && !cached.error && cached.headers && cached.headers.etag;\n const headers = etag && processHeaders(config.headers as HeadersObject);\n\n return headers && !headers['if-none-match']\n ? { ...config, headers: { ...headers, 'if-none-match': etag } }\n : config;\n}\n","import type {\n ApiHandlerConfig,\n ApiHandlerDefaultMethods,\n ApiHandlerMethods,\n RequestConfigUrlRequired,\n} from './types/api-handler';\nimport { fetchf } from '.';\nimport { mergeConfigs } from './config-handler';\nimport { hasOwn } from './utils';\n\n/**\n * Creates an instance of API Handler.\n * It creates an API fetcher function using native fetch() or a custom fetcher if passed as \"fetcher\".\n * @see https://github.com/MattCCC/fetchff#configuration\n *\n * @param {Object} config - Configuration object for the API fetcher (see link above for full options).\n * @param {Object} config.endpoints - An object containing endpoint definitions.\n * @param {string} [config.baseURL] - The base URL for the API.\n * @param {Object} [config.headers] - Optional default headers to include in every request.\n * @param {Function} [config.onError] - Optional callback function for handling errors.\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 EndpointTypes extends object,\n EndpointsSettings = never,\n>(config: ApiHandlerConfig) {\n const endpoints = config.endpoints;\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param endpointName Endpoint Name\n * @returns {Promise}\n */\n async function handleNonImplemented(endpointName: string): Promise {\n console.error('Add ' + endpointName + \" to 'endpoints'.\");\n\n return null;\n }\n\n const apiHandler: ApiHandlerDefaultMethods = {\n config,\n endpoints,\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 endpointName - The name of the API endpoint to call.\n * @param requestConfig - Additional configuration for the request.\n * @returns A promise that resolves with the response from the API provider.\n */\n async request(endpointName, requestConfig = {}) {\n // Use global and per-endpoint settings\n // Only own properties are endpoints, not ones inherited like \"constructor\"\n const endpointConfig = hasOwn(endpoints, endpointName as string)\n ? endpoints[endpointName]\n : undefined;\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // URL parsers ignore leading control characters and spaces, drop tabs and newlines,\n // and treat backslashes like slashes, so check the URL the way it will be resolved\n const resolvedUrl = url\n .replace(/[\\t\\n\\r]/g, '')\n // eslint-disable-next-line no-control-regex -- matching control characters is the point\n .replace(/^[\\x00-\\x20]+/, '');\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (/^[/\\\\]{2}/.test(resolvedUrl)) {\n throw new Error('Protocol-relative URLs not allowed.');\n }\n\n // Prevent potential Server-Side Request Forgery attack and leakage of credentials when same instance is used for external requests\n // Any scheme counts here, as e.g. \"http:\\\\host\" or \"http:host\" can also point to another host\n const mergedConfig = /^[a-z][a-z\\d+\\-.]*:/i.test(resolvedUrl)\n ? // Merge endpoints configs for absolute URLs only if urls match\n endpointConfig && endpointConfig.url === url\n ? mergeConfigs(_endpointConfig, requestConfig)\n : requestConfig\n : mergeConfigs(mergeConfigs(config, _endpointConfig), requestConfig);\n\n // We prevent potential Server-Side Request Forgery attack and leakage of credentials as the same instance is not used for external requests\n // Retrigger fetch to ensure completely new instance of handler being triggered for external URLs\n return fetchf(url, mergedConfig);\n },\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 | symbol) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Symbols (e.g. inspection hooks) are never endpoints, and returning a function\n // for \"then\" would make the instance a thenable that never settles when awaited\n if (typeof prop === 'symbol' || prop === 'then') {\n return undefined;\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (hasOwn(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"]} \ No newline at end of file diff --git a/dist/react/index.js b/dist/react/index.js index cb75527..daecb58 100644 --- a/dist/react/index.js +++ b/dist/react/index.js @@ -1,2 +1,2 @@ -'use strict';var react=require('react'),fetchff=require('fetchff');var F=-1,y=2e3,m=new Map,S=e=>{e&&m.set(e,(m.get(e)||0)+1);},q=(e,t,r,o)=>{if(!e)return;let a=f(e);if(!a)return;let i=a-1;i<=0?(m.delete(e),t===F&&fetchff.addTimeout("r:"+e,()=>{fetchff.abortRequest(e,fetchff.createAbortError("Request to "+o+" aborted","AbortError")),f(e)||fetchff.deleteCache(e,true);},r!=null?r:y)):m.set(e,i);},f=e=>e&&m.get(e)||0;var Z=300,B=Object.freeze({data:null,error:null,isFetching:false,mutate:()=>Promise.resolve(null),config:{},headers:{}}),K=Object.freeze({...B,isFetching:true}),$=[null,{},null],k=new Set(["GET","HEAD","get","head"]);function ne(e,t={}){var b,U,_;let r=react.useMemo(()=>e===null?null:fetchff.generateCacheKey(fetchff.buildConfig(e,t)),[t.cacheKey,e,t.url,t.method,t.headers,t.body,t.params,t.urlPathParams,t.apiUrl,t.baseURL,t.withCredentials,t.credentials]),o=(b=t.dedupeTime)!=null?b:y,a=t.cacheTime||F,i=(U=t.staleTime)!=null?U:Z,R=(_=t.immediate)!=null?_:k.has(t.method||"GET"),P=react.useRef($);P.current=[e,t,r];let g=react.useCallback(()=>{let s=fetchff.getCache(r);if(t.strategy==="reject"&&r&&(!s||!s.data.data&&!s.data.error)){let h=fetchff.getInFlightPromise(r,o);if(h)throw h;if(!s){let[u,c,l]=P.current;if(u)throw fetchff.fetchf(u,{...c,cacheKey:l,dedupeTime:o,cacheTime:a,staleTime:i,strategy:"softFail",cacheErrors:true,_isAutoKey:!c.cacheKey})}}return s?s.data.isFetching&&!t.keepPreviousData?K:s.data:R?K:B},[r]),L=react.useCallback(s=>{S(r),R&&e&&r&&f(r)===1&&(fetchff.getCachedResponse(r,a,t)||C(false));let u=fetchff.subscribe(r,s);return ()=>{q(r,a,o,e),u();}},[r,R,e,o,a]),n=react.useSyncExternalStore(L,g,g),C=react.useCallback(async(s=true,h={})=>{let[u,c,l]=P.current;if(!u)return Promise.resolve(null);let E=!!s;if(!E&&l){let A=fetchff.getCachedResponse(l,a,c);if(A)return Promise.resolve(A)}let Q=E?()=>true:c.cacheBuster;return fetchff.fetchf(u,{...c,cacheKey:l,...h,dedupeTime:o,cacheTime:a,staleTime:i,cacheBuster:Q,strategy:"softFail",cacheErrors:true,_isAutoKey:!c.cacheKey})},[a,o]),T=n.data,p=!T&&!n.error,d=!!e&&(n.isFetching||p&&R),x=d&&p,w=d&&!p;return {data:T,error:n.error,config:n.config,headers:n.headers,isFirstFetch:x,isFetching:d,isLoading:d,isRefetching:w,isError:n.isError,isSuccess:n.isSuccess,mutate:n.mutate,refetch:C}}exports.useFetcher=ne;//# sourceMappingURL=index.js.map +'use strict';var react=require('react'),fetchff=require('fetchff');var F=-1,y=2e3,m=new Map,I=t=>{t&&m.set(t,(m.get(t)||0)+1);},M=(t,e,s,o)=>{if(!t)return;let a=f(t);if(!a)return;let i=a-1;i<=0?(m.delete(t),e===F&&fetchff.addTimeout("r:"+t,()=>{fetchff.abortRequest(t,fetchff.createAbortError("Request to "+o+" aborted","AbortError")),f(t)||fetchff.deleteCache(t,true);},s!=null?s:y)):m.set(t,i);},f=t=>t&&m.get(t)||0;var $=300,C=Object.freeze({data:null,error:null,isFetching:false,mutate:async()=>null,config:{},headers:{}}),w=Object.freeze({...C,isFetching:true}),k=[null,{},null],ee=new Set(["GET","HEAD","get","head"]);function oe(t,e={}){var _,q,A;let s=react.useMemo(()=>t===null?null:fetchff.generateCacheKey(fetchff.buildConfig(t,e)),[e.cacheKey,t,e.url,e.method,e.headers,e.body,e.params,e.urlPathParams,e.apiUrl,e.baseURL,e.withCredentials,e.credentials]),o=(_=e.dedupeTime)!=null?_:y,a=e.cacheTime||F,i=(q=e.staleTime)!=null?q:$,R=(A=e.immediate)!=null?A:ee.has(e.method||"GET"),P=react.useRef(k);P.current=[t,e,s];let b=react.useMemo(()=>e.initialData===void 0?null:Object.freeze({...C,data:e.initialData}),[s]),T=react.useCallback(()=>{let r=fetchff.getCache(s);if(!r&&b)return b;if(e.strategy==="reject"&&s&&(!r||!r.data.data&&!r.data.error)){let h=fetchff.getInFlightPromise(s,o);if(h)throw h;if(!r){let[u,c,l]=P.current;if(u)throw fetchff.fetchf(u,{...c,cacheKey:l,dedupeTime:o,cacheTime:a,staleTime:i,strategy:"softFail",cacheErrors:true,_isAutoKey:!c.cacheKey})}}return r?r.data.isFetching&&!e.keepPreviousData?w:r.data:R?w:C},[s]),x=react.useCallback(r=>{I(s),R&&t&&s&&f(s)===1&&(fetchff.getCachedResponse(s,a,e)||g(false));let u=fetchff.subscribe(s,r);return ()=>{M(s,a,o,t),u();}},[s,R,t,o,a]),n=react.useSyncExternalStore(x,T,T),g=react.useCallback(async(r=true,h={})=>{let[u,c,l]=P.current;if(!u)return null;let E=!!r;if(!E&&l){let S=fetchff.getCachedResponse(l,a,c);if(S)return S}let N=E?()=>true:c.cacheBuster;return fetchff.fetchf(u,{...c,cacheKey:l,...h,dedupeTime:o,cacheTime:a,staleTime:i,cacheBuster:N,strategy:"softFail",cacheErrors:true,_isAutoKey:!c.cacheKey})},[a,o]),U=n.data,p=!U&&!n.error,d=!!t&&(n.isFetching||p&&R),Q=d&&p,H=d&&!p;return {data:U,error:n.error,config:n.config,headers:n.headers,isFirstFetch:Q,isFetching:d,isLoading:d,isRefetching:H,isError:n.isError,isSuccess:n.isSuccess,mutate:n.mutate,refetch:g}}exports.useFetcher=oe;//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/react/index.js.map b/dist/react/index.js.map index 511bf20..2a2aa51 100644 --- a/dist/react/index.js.map +++ b/dist/react/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/react/cache-ref.ts","../../src/react/index.ts"],"names":["INFINITE_CACHE_TIME","DEFAULT_DEDUPE_TIME_MS","refs","incrementRef","key","decrementRef","cacheTime","dedupeTime","url","current","getRefCount","newCount","addTimeout","abortRequest","createAbortError","deleteCache","DEFAULT_STALE_TIME","DEFAULT_RESULT","FETCHING_RESULT","DEFAULT_REF","SAFE_METHODS","useFetcher","config","_a","_b","_c","cacheKey","useMemo","generateCacheKey","buildConfig","staleTime","shouldTriggerOnMount","currentValuesRef","useRef","getSnapshot","useCallback","cached","getCache","pendingPromise","getInFlightPromise","currUrl","currConfig","currCacheKey","fetchf","doSubscribe","cb","getCachedResponse","refetch","unsubscribe","subscribe","state","useSyncExternalStore","forceRefresh","requestConfig","shouldRefresh","cacheBuster","data","isUnresolved","isFetching","isFirstFetch","isRefetching"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module cache-ref\n *\n * Provides reference counting utilities for cache management in React applications.\n *\n * This module maintains an internal reference count for cache keys, allowing for\n * precise control over when cache entries should be deleted. It exports functions\n * to increment and decrement reference counts, retrieve the current count, and clear\n * all reference counts. When a reference count drops to zero and certain conditions\n * are met, the corresponding cache entry is scheduled for deletion.\n *\n * @see deleteCache\n */\n\nimport {\n addTimeout,\n abortRequest,\n deleteCache,\n createAbortError,\n} from 'fetchff';\n\nexport const INFINITE_CACHE_TIME = -1;\nexport const DEFAULT_DEDUPE_TIME_MS = 2000;\n\nconst refs = new Map();\n\nexport const incrementRef = (key: string | null) => {\n if (key) {\n refs.set(key, (refs.get(key) || 0) + 1);\n }\n};\n\nexport const decrementRef = (\n key: string | null,\n cacheTime?: number,\n dedupeTime?: number,\n url?: string | null,\n) => {\n if (!key) {\n return;\n }\n\n const current = getRefCount(key);\n\n if (!current) {\n return;\n }\n\n const newCount = current - 1;\n\n // If the current reference count is less than 2, we can consider deleting the global cache entry\n // The infinite cache time is a special case where we never delete the cache entry unless the reference count drops to zero.\n // This allows for long-lived cache entries that are only deleted when explicitly no longer needed.\n if (newCount <= 0) {\n refs.delete(key);\n\n if (cacheTime && cacheTime === INFINITE_CACHE_TIME) {\n // Delay to ensure all operations are complete before deletion\n addTimeout(\n 'r:' + key,\n () => {\n // Abort any ongoing requests associated with this cache key\n abortRequest(\n key,\n createAbortError('Request to ' + url + ' aborted', 'AbortError'),\n );\n\n // Check if the reference count is still zero before deleting the cache as it might have been incremented again\n // This is to ensure that if another increment happens during the timeout, we don't delete the cache prematurely\n // This is particularly useful in scenarios where multiple components might be using the same cache\n // entry and we want to avoid unnecessary cache deletions.\n if (!getRefCount(key)) {\n deleteCache(key, true);\n }\n },\n dedupeTime ?? DEFAULT_DEDUPE_TIME_MS,\n );\n }\n } else {\n refs.set(key, newCount);\n }\n};\n\nexport const getRefCount = (key: string | null): number => {\n if (!key) {\n return 0;\n }\n\n return refs.get(key) || 0;\n};\n\nexport const getRefs = (): Map => {\n return refs;\n};\n\nexport const clearRefCache = () => {\n refs.clear();\n};\n","import { useCallback, useSyncExternalStore, useMemo, useRef } from 'react';\nimport {\n fetchf,\n subscribe,\n buildConfig,\n generateCacheKey,\n getCachedResponse,\n getInFlightPromise,\n getCache,\n} from 'fetchff';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '..';\nimport type { RefetchFunction, UseFetcherResult } from '../types/react-hooks';\n\nimport {\n decrementRef,\n DEFAULT_DEDUPE_TIME_MS,\n getRefCount,\n incrementRef,\n INFINITE_CACHE_TIME,\n} from './cache-ref';\n\n// In React, we use a default stale time of 5 minutes (SWR)\nconst DEFAULT_STALE_TIME = 300; // 5 minutes\n\n// Pre-allocate objects to avoid GC pressure\nconst DEFAULT_RESULT = Object.freeze({\n data: null,\n error: null,\n isFetching: false,\n mutate: () => Promise.resolve(null),\n config: {},\n headers: {},\n});\n\nconst FETCHING_RESULT = Object.freeze({\n ...DEFAULT_RESULT,\n isFetching: true,\n});\n\nconst DEFAULT_REF = [null, {}, null] as [\n string | null,\n RequestConfig,\n string | null,\n];\n\n// RFC 7231: GET and HEAD are \"safe methods\" with no side effects\nconst SAFE_METHODS = new Set(['GET', 'HEAD', 'get', 'head']);\n\n/**\n * High-performance React hook for fetching data with caching, deduplication, revalidation etc.\n *\n * @template ResponseData - The expected response data type.\n * @template RequestBody - The request payload type.\n * @template QueryParams - The query parameters type.\n * @template PathParams - The URL path parameters type.\n *\n * @param {string|null} url - The endpoint URL to fetch data from. Pass null to skip fetching.\n * If the URL is null, the hook will not perform any fetch operation.\n * If the URL is an empty string, it will default to the base URL configured in fetchff.\n * If the URL is a full URL, it will be used as is.\n * @param {RequestConfig} [config={}] - fetchff and native fetch compatible configuration.\n *\n * @returns {UseFetcherResult} An object containing:\n * - `data`: The fetched data or `null` if not yet available.\n * - `error`: Any error encountered during fetching or `null`.\n * - `isLoading`: Boolean indicating if the request is in progress.\n * - `mutate`: Function to update the cached data and optionally trigger revalidation.\n *\n * @remarks\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n *\n * @example\n * ```tsx\n * const { data, error, isLoading, mutate } = useFetcher('/api/data', {\n * refetchOnFocus: true,\n * cacheTime: 5,\n * dedupeTime: 2000,\n * cacheKey: (config) => `custom-cache-key-${config.url}`,\n * });\n * ```\n */\nexport function useFetcher<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string | null,\n config: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > = {},\n): UseFetcherResult {\n // Efficient cache key generation based on URL and request parameters.\n // Optimized for speed: minimizes unnecessary function calls when possible\n const cacheKey = useMemo(\n () => (url === null ? null : generateCacheKey(buildConfig(url, config))),\n [\n config.cacheKey,\n url,\n config.url,\n config.method,\n config.headers,\n config.body,\n config.params,\n config.urlPathParams,\n config.apiUrl,\n config.baseURL,\n config.withCredentials,\n config.credentials,\n ],\n );\n const dedupeTime = config.dedupeTime ?? DEFAULT_DEDUPE_TIME_MS;\n const cacheTime = config.cacheTime || INFINITE_CACHE_TIME;\n const staleTime = config.staleTime ?? DEFAULT_STALE_TIME;\n\n // Determine if the fetch should be triggered immediately on mount\n const shouldTriggerOnMount =\n config.immediate ?? SAFE_METHODS.has(config.method || 'GET');\n\n const currentValuesRef = useRef(DEFAULT_REF);\n currentValuesRef.current = [url, config, cacheKey];\n\n // Attempt to get the cached response immediately and if not available, return null\n const getSnapshot = useCallback(() => {\n const cached = getCache(\n cacheKey,\n );\n\n // Only throw for Suspense if we're in 'reject' mode and have no data\n if (\n config.strategy === 'reject' &&\n cacheKey &&\n (!cached || (!cached.data.data && !cached.data.error))\n ) {\n const pendingPromise = getInFlightPromise(cacheKey, dedupeTime);\n\n if (pendingPromise) {\n throw pendingPromise;\n }\n\n // If no pending promise but we need to fetch, start fetch and throw the promise\n if (!cached) {\n const [currUrl, currConfig, currCacheKey] = currentValuesRef.current;\n\n if (currUrl) {\n const fetchPromise = fetchf(currUrl, {\n ...currConfig,\n cacheKey: currCacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n strategy: 'softFail',\n cacheErrors: true,\n _isAutoKey: !currConfig.cacheKey,\n });\n\n throw fetchPromise;\n }\n }\n }\n\n if (cached) {\n return cached.data.isFetching && !config.keepPreviousData\n ? (FETCHING_RESULT as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >)\n : cached.data;\n }\n\n return (shouldTriggerOnMount\n ? FETCHING_RESULT\n : DEFAULT_RESULT) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }, [cacheKey]);\n\n // Subscribe to cache updates for the specific cache key\n const doSubscribe = useCallback(\n (cb: () => void) => {\n incrementRef(cacheKey);\n\n // When the component mounts, we want to fetch data if:\n // 1. URL is provided\n // 2. shouldTriggerOnMount is true (so the \"immediate\" isn't specified or is true)\n // 3. There is no cached data\n // 4. There is no error\n // 5. There is no ongoing fetch operation\n const shouldFetch =\n shouldTriggerOnMount && url && cacheKey && getRefCount(cacheKey) === 1; // Check if no existing refs\n\n // Initial fetch logic\n if (shouldFetch) {\n // Stale-While-Revalidate Pattern: Check for both fresh and stale data\n const cached = getCachedResponse(cacheKey, cacheTime, config);\n\n if (!cached) {\n refetch(false);\n }\n }\n\n const unsubscribe = subscribe(cacheKey, cb);\n\n return () => {\n decrementRef(cacheKey, cacheTime, dedupeTime, url);\n unsubscribe();\n };\n },\n [cacheKey, shouldTriggerOnMount, url, dedupeTime, cacheTime],\n );\n\n const state = useSyncExternalStore<\n FetchResponse\n >(doSubscribe, getSnapshot, getSnapshot);\n\n const refetch = useCallback<\n RefetchFunction\n >(\n async (forceRefresh = true, requestConfig = {}) => {\n const [currUrl, currConfig, currCacheKey] = currentValuesRef.current;\n\n if (!currUrl) {\n return Promise.resolve(null);\n }\n\n // Truthy check for forceRefresh to ensure it's a boolean. It is useful in onClick handlers so to avoid additional annonymous function calls.\n const shouldRefresh = !!forceRefresh;\n\n // Fast path: check cache first if not forcing refresh\n if (!shouldRefresh && currCacheKey) {\n const cached = getCachedResponse(currCacheKey, cacheTime, currConfig);\n\n if (cached) {\n return Promise.resolve(cached);\n }\n }\n\n // When manual refetch is triggered, we want to ensure that the cache is busted\n // This can be disabled by passing `refetch(false)`\n const cacheBuster = shouldRefresh ? () => true : currConfig.cacheBuster;\n\n return fetchf(currUrl, {\n ...currConfig,\n cacheKey: currCacheKey,\n ...requestConfig,\n dedupeTime,\n cacheTime,\n staleTime,\n cacheBuster,\n // Ensure that errors are handled gracefully and not thrown by default\n strategy: 'softFail',\n cacheErrors: true,\n _isAutoKey: !currConfig.cacheKey,\n });\n },\n [cacheTime, dedupeTime],\n );\n\n const data = state.data;\n const isUnresolved = !data && !state.error;\n\n // This indicates if the request is in progress or if it is about to start on first mount\n // It is true when:\n // - The request is currently ongoing, and it is not background revalidation\n // - The request is unresolved (no data and no error) and shouldTriggerOnMount\n // is true (which means the request is about to start on mount)\n const isFetching =\n !!url && (state.isFetching || (isUnresolved && shouldTriggerOnMount));\n const isFirstFetch = isFetching && isUnresolved;\n const isRefetching = isFetching && !isUnresolved;\n\n // Consumers always destructure the return value and use the fields directly, so\n // memoizing the object doesn't change rerender behavior nor improve any performance here\n return {\n data,\n error: state.error,\n config: state.config,\n headers: state.headers,\n isFirstFetch,\n isFetching,\n isLoading: isFetching,\n isRefetching,\n isError: state.isError,\n isSuccess: state.isSuccess,\n mutate: state.mutate,\n refetch,\n };\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/react/cache-ref.ts","../../src/react/index.ts"],"names":["INFINITE_CACHE_TIME","DEFAULT_DEDUPE_TIME_MS","refs","incrementRef","key","decrementRef","cacheTime","dedupeTime","url","current","getRefCount","newCount","addTimeout","abortRequest","createAbortError","deleteCache","DEFAULT_STALE_TIME","DEFAULT_RESULT","FETCHING_RESULT","DEFAULT_REF","SAFE_METHODS","useFetcher","config","_a","_b","_c","cacheKey","useMemo","generateCacheKey","buildConfig","staleTime","shouldTriggerOnMount","currentValuesRef","useRef","initialResult","getSnapshot","useCallback","cached","getCache","pendingPromise","getInFlightPromise","currUrl","currConfig","currCacheKey","fetchf","doSubscribe","cb","getCachedResponse","refetch","unsubscribe","subscribe","state","useSyncExternalStore","forceRefresh","requestConfig","shouldRefresh","cacheBuster","data","isUnresolved","isFetching","isFirstFetch","isRefetching"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module cache-ref\n *\n * Provides reference counting utilities for cache management in React applications.\n *\n * This module maintains an internal reference count for cache keys, allowing for\n * precise control over when cache entries should be deleted. It exports functions\n * to increment and decrement reference counts, retrieve the current count, and clear\n * all reference counts. When a reference count drops to zero and certain conditions\n * are met, the corresponding cache entry is scheduled for deletion.\n *\n * @see deleteCache\n */\n\nimport {\n addTimeout,\n abortRequest,\n deleteCache,\n createAbortError,\n} from 'fetchff';\n\nexport const INFINITE_CACHE_TIME = -1;\nexport const DEFAULT_DEDUPE_TIME_MS = 2000;\n\nconst refs = new Map();\n\nexport const incrementRef = (key: string | null) => {\n if (key) {\n refs.set(key, (refs.get(key) || 0) + 1);\n }\n};\n\nexport const decrementRef = (\n key: string | null,\n cacheTime?: number,\n dedupeTime?: number,\n url?: string | null,\n) => {\n if (!key) {\n return;\n }\n\n const current = getRefCount(key);\n\n if (!current) {\n return;\n }\n\n const newCount = current - 1;\n\n // If the current reference count is less than 2, we can consider deleting the global cache entry\n // The infinite cache time is a special case where we never delete the cache entry unless the reference count drops to zero.\n // This allows for long-lived cache entries that are only deleted when explicitly no longer needed.\n if (newCount <= 0) {\n refs.delete(key);\n\n if (cacheTime && cacheTime === INFINITE_CACHE_TIME) {\n // Delay to ensure all operations are complete before deletion\n addTimeout(\n 'r:' + key,\n () => {\n // Abort any ongoing requests associated with this cache key\n abortRequest(\n key,\n createAbortError('Request to ' + url + ' aborted', 'AbortError'),\n );\n\n // Check if the reference count is still zero before deleting the cache as it might have been incremented again\n // This is to ensure that if another increment happens during the timeout, we don't delete the cache prematurely\n // This is particularly useful in scenarios where multiple components might be using the same cache\n // entry and we want to avoid unnecessary cache deletions.\n if (!getRefCount(key)) {\n deleteCache(key, true);\n }\n },\n dedupeTime ?? DEFAULT_DEDUPE_TIME_MS,\n );\n }\n } else {\n refs.set(key, newCount);\n }\n};\n\nexport const getRefCount = (key: string | null): number => {\n if (!key) {\n return 0;\n }\n\n return refs.get(key) || 0;\n};\n\nexport const getRefs = (): Map => {\n return refs;\n};\n\nexport const clearRefCache = () => {\n refs.clear();\n};\n","import { useCallback, useSyncExternalStore, useMemo, useRef } from 'react';\nimport {\n fetchf,\n subscribe,\n buildConfig,\n generateCacheKey,\n getCachedResponse,\n getInFlightPromise,\n getCache,\n} from 'fetchff';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '..';\nimport type { RefetchFunction, UseFetcherResult } from '../types/react-hooks';\n\nimport {\n decrementRef,\n DEFAULT_DEDUPE_TIME_MS,\n getRefCount,\n incrementRef,\n INFINITE_CACHE_TIME,\n} from './cache-ref';\n\n// In React, we use a default stale time of 5 minutes (SWR)\nconst DEFAULT_STALE_TIME = 300; // 5 minutes\n\n// Pre-allocate objects to avoid GC pressure\nconst DEFAULT_RESULT = Object.freeze({\n data: null,\n error: null,\n isFetching: false,\n mutate: async () => null,\n config: {},\n headers: {},\n});\n\nconst FETCHING_RESULT = Object.freeze({\n ...DEFAULT_RESULT,\n isFetching: true,\n});\n\nconst DEFAULT_REF = [null, {}, null] as [\n string | null,\n RequestConfig,\n string | null,\n];\n\n// RFC 7231: GET and HEAD are \"safe methods\" with no side effects\nconst SAFE_METHODS = new Set(['GET', 'HEAD', 'get', 'head']);\n\n/**\n * High-performance React hook for fetching data with caching, deduplication, revalidation etc.\n *\n * @template ResponseData - The expected response data type.\n * @template RequestBody - The request payload type.\n * @template QueryParams - The query parameters type.\n * @template PathParams - The URL path parameters type.\n *\n * @param {string|null} url - The endpoint URL to fetch data from. Pass null to skip fetching.\n * If the URL is null, the hook will not perform any fetch operation.\n * If the URL is an empty string, it will default to the base URL configured in fetchff.\n * If the URL is a full URL, it will be used as is.\n * @param {RequestConfig} [config={}] - fetchff and native fetch compatible configuration.\n *\n * @returns {UseFetcherResult} An object containing:\n * - `data`: The fetched data or `null` if not yet available.\n * - `error`: Any error encountered during fetching or `null`.\n * - `isLoading`: Boolean indicating if the request is in progress.\n * - `mutate`: Function to update the cached data and optionally trigger revalidation.\n *\n * @remarks\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n *\n * @example\n * ```tsx\n * const { data, error, isLoading, mutate } = useFetcher('/api/data', {\n * refetchOnFocus: true,\n * cacheTime: 5,\n * dedupeTime: 2000,\n * cacheKey: (config) => `custom-cache-key-${config.url}`,\n * });\n * ```\n */\nexport function useFetcher<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string | null,\n config: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > = {},\n): UseFetcherResult {\n // Efficient cache key generation based on URL and request parameters.\n // Optimized for speed: minimizes unnecessary function calls when possible\n const cacheKey = useMemo(\n () => (url === null ? null : generateCacheKey(buildConfig(url, config))),\n [\n config.cacheKey,\n url,\n config.url,\n config.method,\n config.headers,\n config.body,\n config.params,\n config.urlPathParams,\n config.apiUrl,\n config.baseURL,\n config.withCredentials,\n config.credentials,\n ],\n );\n const dedupeTime = config.dedupeTime ?? DEFAULT_DEDUPE_TIME_MS;\n const cacheTime = config.cacheTime || INFINITE_CACHE_TIME;\n const staleTime = config.staleTime ?? DEFAULT_STALE_TIME;\n\n // Determine if the fetch should be triggered immediately on mount\n const shouldTriggerOnMount =\n config.immediate ?? SAFE_METHODS.has(config.method || 'GET');\n\n const currentValuesRef = useRef(DEFAULT_REF);\n currentValuesRef.current = [url, config, cacheKey];\n\n // The initial data is shown while there's no cached response, e.g. during server-side rendering\n const initialResult = useMemo(\n () =>\n config.initialData === undefined\n ? null\n : Object.freeze({ ...DEFAULT_RESULT, data: config.initialData }),\n [cacheKey],\n );\n\n // Attempt to get the cached response immediately and if not available, return null\n const getSnapshot = useCallback(() => {\n const cached = getCache(\n cacheKey,\n );\n\n if (!cached && initialResult) {\n return initialResult as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n // Only throw for Suspense if we're in 'reject' mode and have no data\n if (\n config.strategy === 'reject' &&\n cacheKey &&\n (!cached || (!cached.data.data && !cached.data.error))\n ) {\n const pendingPromise = getInFlightPromise(cacheKey, dedupeTime);\n\n if (pendingPromise) {\n throw pendingPromise;\n }\n\n // If no pending promise but we need to fetch, start fetch and throw the promise\n if (!cached) {\n const [currUrl, currConfig, currCacheKey] = currentValuesRef.current;\n\n if (currUrl) {\n const fetchPromise = fetchf(currUrl, {\n ...currConfig,\n cacheKey: currCacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n strategy: 'softFail',\n cacheErrors: true,\n _isAutoKey: !currConfig.cacheKey,\n });\n\n throw fetchPromise;\n }\n }\n }\n\n if (cached) {\n return cached.data.isFetching && !config.keepPreviousData\n ? (FETCHING_RESULT as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >)\n : cached.data;\n }\n\n return (shouldTriggerOnMount\n ? FETCHING_RESULT\n : DEFAULT_RESULT) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }, [cacheKey]);\n\n // Subscribe to cache updates for the specific cache key\n const doSubscribe = useCallback(\n (cb: () => void) => {\n incrementRef(cacheKey);\n\n // When the component mounts, we want to fetch data if:\n // 1. URL is provided\n // 2. shouldTriggerOnMount is true (so the \"immediate\" isn't specified or is true)\n // 3. There is no cached data\n // 4. There is no error\n // 5. There is no ongoing fetch operation\n const shouldFetch =\n shouldTriggerOnMount && url && cacheKey && getRefCount(cacheKey) === 1; // Check if no existing refs\n\n // Initial fetch logic\n if (shouldFetch) {\n // Stale-While-Revalidate Pattern: Check for both fresh and stale data\n const cached = getCachedResponse(cacheKey, cacheTime, config);\n\n if (!cached) {\n refetch(false);\n }\n }\n\n const unsubscribe = subscribe(cacheKey, cb);\n\n return () => {\n decrementRef(cacheKey, cacheTime, dedupeTime, url);\n unsubscribe();\n };\n },\n [cacheKey, shouldTriggerOnMount, url, dedupeTime, cacheTime],\n );\n\n const state = useSyncExternalStore<\n FetchResponse\n >(doSubscribe, getSnapshot, getSnapshot);\n\n const refetch = useCallback<\n RefetchFunction\n >(\n async (forceRefresh = true, requestConfig = {}) => {\n const [currUrl, currConfig, currCacheKey] = currentValuesRef.current;\n\n if (!currUrl) {\n return null;\n }\n\n // Truthy check for forceRefresh to ensure it's a boolean. It is useful in onClick handlers so to avoid additional annonymous function calls.\n const shouldRefresh = !!forceRefresh;\n\n // Fast path: check cache first if not forcing refresh\n if (!shouldRefresh && currCacheKey) {\n const cached = getCachedResponse(currCacheKey, cacheTime, currConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n // When manual refetch is triggered, we want to ensure that the cache is busted\n // This can be disabled by passing `refetch(false)`\n const cacheBuster = shouldRefresh ? () => true : currConfig.cacheBuster;\n\n return fetchf(currUrl, {\n ...currConfig,\n cacheKey: currCacheKey,\n ...requestConfig,\n dedupeTime,\n cacheTime,\n staleTime,\n cacheBuster,\n // Ensure that errors are handled gracefully and not thrown by default\n strategy: 'softFail',\n cacheErrors: true,\n _isAutoKey: !currConfig.cacheKey,\n });\n },\n [cacheTime, dedupeTime],\n );\n\n const data = state.data;\n const isUnresolved = !data && !state.error;\n\n // This indicates if the request is in progress or if it is about to start on first mount\n // It is true when:\n // - The request is currently ongoing, and it is not background revalidation\n // - The request is unresolved (no data and no error) and shouldTriggerOnMount\n // is true (which means the request is about to start on mount)\n const isFetching =\n !!url && (state.isFetching || (isUnresolved && shouldTriggerOnMount));\n const isFirstFetch = isFetching && isUnresolved;\n const isRefetching = isFetching && !isUnresolved;\n\n // Consumers always destructure the return value and use the fields directly, so\n // memoizing the object doesn't change rerender behavior nor improve any performance here\n return {\n data,\n error: state.error,\n config: state.config,\n headers: state.headers,\n isFirstFetch,\n isFetching,\n isLoading: isFetching,\n isRefetching,\n isError: state.isError,\n isSuccess: state.isSuccess,\n mutate: state.mutate,\n refetch,\n };\n}\n"]} \ No newline at end of file diff --git a/dist/react/index.mjs b/dist/react/index.mjs index f83dd04..f09878f 100644 --- a/dist/react/index.mjs +++ b/dist/react/index.mjs @@ -1,2 +1,2 @@ -import {useMemo,useRef,useCallback,useSyncExternalStore}from'react';import {generateCacheKey,buildConfig,getCache,getInFlightPromise,fetchf,getCachedResponse,subscribe,addTimeout,abortRequest,createAbortError,deleteCache}from'fetchff';var F=-1,y=2e3,m=new Map,S=e=>{e&&m.set(e,(m.get(e)||0)+1);},q=(e,t,r,o)=>{if(!e)return;let a=f(e);if(!a)return;let i=a-1;i<=0?(m.delete(e),t===F&&addTimeout("r:"+e,()=>{abortRequest(e,createAbortError("Request to "+o+" aborted","AbortError")),f(e)||deleteCache(e,true);},r!=null?r:y)):m.set(e,i);},f=e=>e&&m.get(e)||0;var Z=300,B=Object.freeze({data:null,error:null,isFetching:false,mutate:()=>Promise.resolve(null),config:{},headers:{}}),K=Object.freeze({...B,isFetching:true}),$=[null,{},null],k=new Set(["GET","HEAD","get","head"]);function ne(e,t={}){var b,U,_;let r=useMemo(()=>e===null?null:generateCacheKey(buildConfig(e,t)),[t.cacheKey,e,t.url,t.method,t.headers,t.body,t.params,t.urlPathParams,t.apiUrl,t.baseURL,t.withCredentials,t.credentials]),o=(b=t.dedupeTime)!=null?b:y,a=t.cacheTime||F,i=(U=t.staleTime)!=null?U:Z,R=(_=t.immediate)!=null?_:k.has(t.method||"GET"),P=useRef($);P.current=[e,t,r];let g=useCallback(()=>{let s=getCache(r);if(t.strategy==="reject"&&r&&(!s||!s.data.data&&!s.data.error)){let h=getInFlightPromise(r,o);if(h)throw h;if(!s){let[u,c,l]=P.current;if(u)throw fetchf(u,{...c,cacheKey:l,dedupeTime:o,cacheTime:a,staleTime:i,strategy:"softFail",cacheErrors:true,_isAutoKey:!c.cacheKey})}}return s?s.data.isFetching&&!t.keepPreviousData?K:s.data:R?K:B},[r]),L=useCallback(s=>{S(r),R&&e&&r&&f(r)===1&&(getCachedResponse(r,a,t)||C(false));let u=subscribe(r,s);return ()=>{q(r,a,o,e),u();}},[r,R,e,o,a]),n=useSyncExternalStore(L,g,g),C=useCallback(async(s=true,h={})=>{let[u,c,l]=P.current;if(!u)return Promise.resolve(null);let E=!!s;if(!E&&l){let A=getCachedResponse(l,a,c);if(A)return Promise.resolve(A)}let Q=E?()=>true:c.cacheBuster;return fetchf(u,{...c,cacheKey:l,...h,dedupeTime:o,cacheTime:a,staleTime:i,cacheBuster:Q,strategy:"softFail",cacheErrors:true,_isAutoKey:!c.cacheKey})},[a,o]),T=n.data,p=!T&&!n.error,d=!!e&&(n.isFetching||p&&R),x=d&&p,w=d&&!p;return {data:T,error:n.error,config:n.config,headers:n.headers,isFirstFetch:x,isFetching:d,isLoading:d,isRefetching:w,isError:n.isError,isSuccess:n.isSuccess,mutate:n.mutate,refetch:C}}export{ne as useFetcher};//# sourceMappingURL=index.mjs.map +import {useMemo,useRef,useCallback,useSyncExternalStore}from'react';import {generateCacheKey,buildConfig,getCache,getInFlightPromise,fetchf,getCachedResponse,subscribe,addTimeout,abortRequest,createAbortError,deleteCache}from'fetchff';var F=-1,y=2e3,m=new Map,I=t=>{t&&m.set(t,(m.get(t)||0)+1);},M=(t,e,s,o)=>{if(!t)return;let a=f(t);if(!a)return;let i=a-1;i<=0?(m.delete(t),e===F&&addTimeout("r:"+t,()=>{abortRequest(t,createAbortError("Request to "+o+" aborted","AbortError")),f(t)||deleteCache(t,true);},s!=null?s:y)):m.set(t,i);},f=t=>t&&m.get(t)||0;var $=300,C=Object.freeze({data:null,error:null,isFetching:false,mutate:async()=>null,config:{},headers:{}}),w=Object.freeze({...C,isFetching:true}),k=[null,{},null],ee=new Set(["GET","HEAD","get","head"]);function oe(t,e={}){var _,q,A;let s=useMemo(()=>t===null?null:generateCacheKey(buildConfig(t,e)),[e.cacheKey,t,e.url,e.method,e.headers,e.body,e.params,e.urlPathParams,e.apiUrl,e.baseURL,e.withCredentials,e.credentials]),o=(_=e.dedupeTime)!=null?_:y,a=e.cacheTime||F,i=(q=e.staleTime)!=null?q:$,R=(A=e.immediate)!=null?A:ee.has(e.method||"GET"),P=useRef(k);P.current=[t,e,s];let b=useMemo(()=>e.initialData===void 0?null:Object.freeze({...C,data:e.initialData}),[s]),T=useCallback(()=>{let r=getCache(s);if(!r&&b)return b;if(e.strategy==="reject"&&s&&(!r||!r.data.data&&!r.data.error)){let h=getInFlightPromise(s,o);if(h)throw h;if(!r){let[u,c,l]=P.current;if(u)throw fetchf(u,{...c,cacheKey:l,dedupeTime:o,cacheTime:a,staleTime:i,strategy:"softFail",cacheErrors:true,_isAutoKey:!c.cacheKey})}}return r?r.data.isFetching&&!e.keepPreviousData?w:r.data:R?w:C},[s]),x=useCallback(r=>{I(s),R&&t&&s&&f(s)===1&&(getCachedResponse(s,a,e)||g(false));let u=subscribe(s,r);return ()=>{M(s,a,o,t),u();}},[s,R,t,o,a]),n=useSyncExternalStore(x,T,T),g=useCallback(async(r=true,h={})=>{let[u,c,l]=P.current;if(!u)return null;let E=!!r;if(!E&&l){let S=getCachedResponse(l,a,c);if(S)return S}let N=E?()=>true:c.cacheBuster;return fetchf(u,{...c,cacheKey:l,...h,dedupeTime:o,cacheTime:a,staleTime:i,cacheBuster:N,strategy:"softFail",cacheErrors:true,_isAutoKey:!c.cacheKey})},[a,o]),U=n.data,p=!U&&!n.error,d=!!t&&(n.isFetching||p&&R),Q=d&&p,H=d&&!p;return {data:U,error:n.error,config:n.config,headers:n.headers,isFirstFetch:Q,isFetching:d,isLoading:d,isRefetching:H,isError:n.isError,isSuccess:n.isSuccess,mutate:n.mutate,refetch:g}}export{oe as useFetcher};//# sourceMappingURL=index.mjs.map //# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/dist/react/index.mjs.map b/dist/react/index.mjs.map index e7f0930..66dae6d 100644 --- a/dist/react/index.mjs.map +++ b/dist/react/index.mjs.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/react/cache-ref.ts","../../src/react/index.ts"],"names":["INFINITE_CACHE_TIME","DEFAULT_DEDUPE_TIME_MS","refs","incrementRef","key","decrementRef","cacheTime","dedupeTime","url","current","getRefCount","newCount","addTimeout","abortRequest","createAbortError","deleteCache","DEFAULT_STALE_TIME","DEFAULT_RESULT","FETCHING_RESULT","DEFAULT_REF","SAFE_METHODS","useFetcher","config","_a","_b","_c","cacheKey","useMemo","generateCacheKey","buildConfig","staleTime","shouldTriggerOnMount","currentValuesRef","useRef","getSnapshot","useCallback","cached","getCache","pendingPromise","getInFlightPromise","currUrl","currConfig","currCacheKey","fetchf","doSubscribe","cb","getCachedResponse","refetch","unsubscribe","subscribe","state","useSyncExternalStore","forceRefresh","requestConfig","shouldRefresh","cacheBuster","data","isUnresolved","isFetching","isFirstFetch","isRefetching"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @module cache-ref\n *\n * Provides reference counting utilities for cache management in React applications.\n *\n * This module maintains an internal reference count for cache keys, allowing for\n * precise control over when cache entries should be deleted. It exports functions\n * to increment and decrement reference counts, retrieve the current count, and clear\n * all reference counts. When a reference count drops to zero and certain conditions\n * are met, the corresponding cache entry is scheduled for deletion.\n *\n * @see deleteCache\n */\n\nimport {\n addTimeout,\n abortRequest,\n deleteCache,\n createAbortError,\n} from 'fetchff';\n\nexport const INFINITE_CACHE_TIME = -1;\nexport const DEFAULT_DEDUPE_TIME_MS = 2000;\n\nconst refs = new Map();\n\nexport const incrementRef = (key: string | null) => {\n if (key) {\n refs.set(key, (refs.get(key) || 0) + 1);\n }\n};\n\nexport const decrementRef = (\n key: string | null,\n cacheTime?: number,\n dedupeTime?: number,\n url?: string | null,\n) => {\n if (!key) {\n return;\n }\n\n const current = getRefCount(key);\n\n if (!current) {\n return;\n }\n\n const newCount = current - 1;\n\n // If the current reference count is less than 2, we can consider deleting the global cache entry\n // The infinite cache time is a special case where we never delete the cache entry unless the reference count drops to zero.\n // This allows for long-lived cache entries that are only deleted when explicitly no longer needed.\n if (newCount <= 0) {\n refs.delete(key);\n\n if (cacheTime && cacheTime === INFINITE_CACHE_TIME) {\n // Delay to ensure all operations are complete before deletion\n addTimeout(\n 'r:' + key,\n () => {\n // Abort any ongoing requests associated with this cache key\n abortRequest(\n key,\n createAbortError('Request to ' + url + ' aborted', 'AbortError'),\n );\n\n // Check if the reference count is still zero before deleting the cache as it might have been incremented again\n // This is to ensure that if another increment happens during the timeout, we don't delete the cache prematurely\n // This is particularly useful in scenarios where multiple components might be using the same cache\n // entry and we want to avoid unnecessary cache deletions.\n if (!getRefCount(key)) {\n deleteCache(key, true);\n }\n },\n dedupeTime ?? DEFAULT_DEDUPE_TIME_MS,\n );\n }\n } else {\n refs.set(key, newCount);\n }\n};\n\nexport const getRefCount = (key: string | null): number => {\n if (!key) {\n return 0;\n }\n\n return refs.get(key) || 0;\n};\n\nexport const getRefs = (): Map => {\n return refs;\n};\n\nexport const clearRefCache = () => {\n refs.clear();\n};\n","import { useCallback, useSyncExternalStore, useMemo, useRef } from 'react';\nimport {\n fetchf,\n subscribe,\n buildConfig,\n generateCacheKey,\n getCachedResponse,\n getInFlightPromise,\n getCache,\n} from 'fetchff';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '..';\nimport type { RefetchFunction, UseFetcherResult } from '../types/react-hooks';\n\nimport {\n decrementRef,\n DEFAULT_DEDUPE_TIME_MS,\n getRefCount,\n incrementRef,\n INFINITE_CACHE_TIME,\n} from './cache-ref';\n\n// In React, we use a default stale time of 5 minutes (SWR)\nconst DEFAULT_STALE_TIME = 300; // 5 minutes\n\n// Pre-allocate objects to avoid GC pressure\nconst DEFAULT_RESULT = Object.freeze({\n data: null,\n error: null,\n isFetching: false,\n mutate: () => Promise.resolve(null),\n config: {},\n headers: {},\n});\n\nconst FETCHING_RESULT = Object.freeze({\n ...DEFAULT_RESULT,\n isFetching: true,\n});\n\nconst DEFAULT_REF = [null, {}, null] as [\n string | null,\n RequestConfig,\n string | null,\n];\n\n// RFC 7231: GET and HEAD are \"safe methods\" with no side effects\nconst SAFE_METHODS = new Set(['GET', 'HEAD', 'get', 'head']);\n\n/**\n * High-performance React hook for fetching data with caching, deduplication, revalidation etc.\n *\n * @template ResponseData - The expected response data type.\n * @template RequestBody - The request payload type.\n * @template QueryParams - The query parameters type.\n * @template PathParams - The URL path parameters type.\n *\n * @param {string|null} url - The endpoint URL to fetch data from. Pass null to skip fetching.\n * If the URL is null, the hook will not perform any fetch operation.\n * If the URL is an empty string, it will default to the base URL configured in fetchff.\n * If the URL is a full URL, it will be used as is.\n * @param {RequestConfig} [config={}] - fetchff and native fetch compatible configuration.\n *\n * @returns {UseFetcherResult} An object containing:\n * - `data`: The fetched data or `null` if not yet available.\n * - `error`: Any error encountered during fetching or `null`.\n * - `isLoading`: Boolean indicating if the request is in progress.\n * - `mutate`: Function to update the cached data and optionally trigger revalidation.\n *\n * @remarks\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n *\n * @example\n * ```tsx\n * const { data, error, isLoading, mutate } = useFetcher('/api/data', {\n * refetchOnFocus: true,\n * cacheTime: 5,\n * dedupeTime: 2000,\n * cacheKey: (config) => `custom-cache-key-${config.url}`,\n * });\n * ```\n */\nexport function useFetcher<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string | null,\n config: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > = {},\n): UseFetcherResult {\n // Efficient cache key generation based on URL and request parameters.\n // Optimized for speed: minimizes unnecessary function calls when possible\n const cacheKey = useMemo(\n () => (url === null ? null : generateCacheKey(buildConfig(url, config))),\n [\n config.cacheKey,\n url,\n config.url,\n config.method,\n config.headers,\n config.body,\n config.params,\n config.urlPathParams,\n config.apiUrl,\n config.baseURL,\n config.withCredentials,\n config.credentials,\n ],\n );\n const dedupeTime = config.dedupeTime ?? DEFAULT_DEDUPE_TIME_MS;\n const cacheTime = config.cacheTime || INFINITE_CACHE_TIME;\n const staleTime = config.staleTime ?? DEFAULT_STALE_TIME;\n\n // Determine if the fetch should be triggered immediately on mount\n const shouldTriggerOnMount =\n config.immediate ?? SAFE_METHODS.has(config.method || 'GET');\n\n const currentValuesRef = useRef(DEFAULT_REF);\n currentValuesRef.current = [url, config, cacheKey];\n\n // Attempt to get the cached response immediately and if not available, return null\n const getSnapshot = useCallback(() => {\n const cached = getCache(\n cacheKey,\n );\n\n // Only throw for Suspense if we're in 'reject' mode and have no data\n if (\n config.strategy === 'reject' &&\n cacheKey &&\n (!cached || (!cached.data.data && !cached.data.error))\n ) {\n const pendingPromise = getInFlightPromise(cacheKey, dedupeTime);\n\n if (pendingPromise) {\n throw pendingPromise;\n }\n\n // If no pending promise but we need to fetch, start fetch and throw the promise\n if (!cached) {\n const [currUrl, currConfig, currCacheKey] = currentValuesRef.current;\n\n if (currUrl) {\n const fetchPromise = fetchf(currUrl, {\n ...currConfig,\n cacheKey: currCacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n strategy: 'softFail',\n cacheErrors: true,\n _isAutoKey: !currConfig.cacheKey,\n });\n\n throw fetchPromise;\n }\n }\n }\n\n if (cached) {\n return cached.data.isFetching && !config.keepPreviousData\n ? (FETCHING_RESULT as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >)\n : cached.data;\n }\n\n return (shouldTriggerOnMount\n ? FETCHING_RESULT\n : DEFAULT_RESULT) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }, [cacheKey]);\n\n // Subscribe to cache updates for the specific cache key\n const doSubscribe = useCallback(\n (cb: () => void) => {\n incrementRef(cacheKey);\n\n // When the component mounts, we want to fetch data if:\n // 1. URL is provided\n // 2. shouldTriggerOnMount is true (so the \"immediate\" isn't specified or is true)\n // 3. There is no cached data\n // 4. There is no error\n // 5. There is no ongoing fetch operation\n const shouldFetch =\n shouldTriggerOnMount && url && cacheKey && getRefCount(cacheKey) === 1; // Check if no existing refs\n\n // Initial fetch logic\n if (shouldFetch) {\n // Stale-While-Revalidate Pattern: Check for both fresh and stale data\n const cached = getCachedResponse(cacheKey, cacheTime, config);\n\n if (!cached) {\n refetch(false);\n }\n }\n\n const unsubscribe = subscribe(cacheKey, cb);\n\n return () => {\n decrementRef(cacheKey, cacheTime, dedupeTime, url);\n unsubscribe();\n };\n },\n [cacheKey, shouldTriggerOnMount, url, dedupeTime, cacheTime],\n );\n\n const state = useSyncExternalStore<\n FetchResponse\n >(doSubscribe, getSnapshot, getSnapshot);\n\n const refetch = useCallback<\n RefetchFunction\n >(\n async (forceRefresh = true, requestConfig = {}) => {\n const [currUrl, currConfig, currCacheKey] = currentValuesRef.current;\n\n if (!currUrl) {\n return Promise.resolve(null);\n }\n\n // Truthy check for forceRefresh to ensure it's a boolean. It is useful in onClick handlers so to avoid additional annonymous function calls.\n const shouldRefresh = !!forceRefresh;\n\n // Fast path: check cache first if not forcing refresh\n if (!shouldRefresh && currCacheKey) {\n const cached = getCachedResponse(currCacheKey, cacheTime, currConfig);\n\n if (cached) {\n return Promise.resolve(cached);\n }\n }\n\n // When manual refetch is triggered, we want to ensure that the cache is busted\n // This can be disabled by passing `refetch(false)`\n const cacheBuster = shouldRefresh ? () => true : currConfig.cacheBuster;\n\n return fetchf(currUrl, {\n ...currConfig,\n cacheKey: currCacheKey,\n ...requestConfig,\n dedupeTime,\n cacheTime,\n staleTime,\n cacheBuster,\n // Ensure that errors are handled gracefully and not thrown by default\n strategy: 'softFail',\n cacheErrors: true,\n _isAutoKey: !currConfig.cacheKey,\n });\n },\n [cacheTime, dedupeTime],\n );\n\n const data = state.data;\n const isUnresolved = !data && !state.error;\n\n // This indicates if the request is in progress or if it is about to start on first mount\n // It is true when:\n // - The request is currently ongoing, and it is not background revalidation\n // - The request is unresolved (no data and no error) and shouldTriggerOnMount\n // is true (which means the request is about to start on mount)\n const isFetching =\n !!url && (state.isFetching || (isUnresolved && shouldTriggerOnMount));\n const isFirstFetch = isFetching && isUnresolved;\n const isRefetching = isFetching && !isUnresolved;\n\n // Consumers always destructure the return value and use the fields directly, so\n // memoizing the object doesn't change rerender behavior nor improve any performance here\n return {\n data,\n error: state.error,\n config: state.config,\n headers: state.headers,\n isFirstFetch,\n isFetching,\n isLoading: isFetching,\n isRefetching,\n isError: state.isError,\n isSuccess: state.isSuccess,\n mutate: state.mutate,\n refetch,\n };\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/react/cache-ref.ts","../../src/react/index.ts"],"names":["INFINITE_CACHE_TIME","DEFAULT_DEDUPE_TIME_MS","refs","incrementRef","key","decrementRef","cacheTime","dedupeTime","url","current","getRefCount","newCount","addTimeout","abortRequest","createAbortError","deleteCache","DEFAULT_STALE_TIME","DEFAULT_RESULT","FETCHING_RESULT","DEFAULT_REF","SAFE_METHODS","useFetcher","config","_a","_b","_c","cacheKey","useMemo","generateCacheKey","buildConfig","staleTime","shouldTriggerOnMount","currentValuesRef","useRef","initialResult","getSnapshot","useCallback","cached","getCache","pendingPromise","getInFlightPromise","currUrl","currConfig","currCacheKey","fetchf","doSubscribe","cb","getCachedResponse","refetch","unsubscribe","subscribe","state","useSyncExternalStore","forceRefresh","requestConfig","shouldRefresh","cacheBuster","data","isUnresolved","isFetching","isFirstFetch","isRefetching"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @module cache-ref\n *\n * Provides reference counting utilities for cache management in React applications.\n *\n * This module maintains an internal reference count for cache keys, allowing for\n * precise control over when cache entries should be deleted. It exports functions\n * to increment and decrement reference counts, retrieve the current count, and clear\n * all reference counts. When a reference count drops to zero and certain conditions\n * are met, the corresponding cache entry is scheduled for deletion.\n *\n * @see deleteCache\n */\n\nimport {\n addTimeout,\n abortRequest,\n deleteCache,\n createAbortError,\n} from 'fetchff';\n\nexport const INFINITE_CACHE_TIME = -1;\nexport const DEFAULT_DEDUPE_TIME_MS = 2000;\n\nconst refs = new Map();\n\nexport const incrementRef = (key: string | null) => {\n if (key) {\n refs.set(key, (refs.get(key) || 0) + 1);\n }\n};\n\nexport const decrementRef = (\n key: string | null,\n cacheTime?: number,\n dedupeTime?: number,\n url?: string | null,\n) => {\n if (!key) {\n return;\n }\n\n const current = getRefCount(key);\n\n if (!current) {\n return;\n }\n\n const newCount = current - 1;\n\n // If the current reference count is less than 2, we can consider deleting the global cache entry\n // The infinite cache time is a special case where we never delete the cache entry unless the reference count drops to zero.\n // This allows for long-lived cache entries that are only deleted when explicitly no longer needed.\n if (newCount <= 0) {\n refs.delete(key);\n\n if (cacheTime && cacheTime === INFINITE_CACHE_TIME) {\n // Delay to ensure all operations are complete before deletion\n addTimeout(\n 'r:' + key,\n () => {\n // Abort any ongoing requests associated with this cache key\n abortRequest(\n key,\n createAbortError('Request to ' + url + ' aborted', 'AbortError'),\n );\n\n // Check if the reference count is still zero before deleting the cache as it might have been incremented again\n // This is to ensure that if another increment happens during the timeout, we don't delete the cache prematurely\n // This is particularly useful in scenarios where multiple components might be using the same cache\n // entry and we want to avoid unnecessary cache deletions.\n if (!getRefCount(key)) {\n deleteCache(key, true);\n }\n },\n dedupeTime ?? DEFAULT_DEDUPE_TIME_MS,\n );\n }\n } else {\n refs.set(key, newCount);\n }\n};\n\nexport const getRefCount = (key: string | null): number => {\n if (!key) {\n return 0;\n }\n\n return refs.get(key) || 0;\n};\n\nexport const getRefs = (): Map => {\n return refs;\n};\n\nexport const clearRefCache = () => {\n refs.clear();\n};\n","import { useCallback, useSyncExternalStore, useMemo, useRef } from 'react';\nimport {\n fetchf,\n subscribe,\n buildConfig,\n generateCacheKey,\n getCachedResponse,\n getInFlightPromise,\n getCache,\n} from 'fetchff';\nimport type {\n DefaultParams,\n DefaultPayload,\n DefaultResponse,\n DefaultUrlParams,\n FetchResponse,\n RequestConfig,\n} from '..';\nimport type { RefetchFunction, UseFetcherResult } from '../types/react-hooks';\n\nimport {\n decrementRef,\n DEFAULT_DEDUPE_TIME_MS,\n getRefCount,\n incrementRef,\n INFINITE_CACHE_TIME,\n} from './cache-ref';\n\n// In React, we use a default stale time of 5 minutes (SWR)\nconst DEFAULT_STALE_TIME = 300; // 5 minutes\n\n// Pre-allocate objects to avoid GC pressure\nconst DEFAULT_RESULT = Object.freeze({\n data: null,\n error: null,\n isFetching: false,\n mutate: async () => null,\n config: {},\n headers: {},\n});\n\nconst FETCHING_RESULT = Object.freeze({\n ...DEFAULT_RESULT,\n isFetching: true,\n});\n\nconst DEFAULT_REF = [null, {}, null] as [\n string | null,\n RequestConfig,\n string | null,\n];\n\n// RFC 7231: GET and HEAD are \"safe methods\" with no side effects\nconst SAFE_METHODS = new Set(['GET', 'HEAD', 'get', 'head']);\n\n/**\n * High-performance React hook for fetching data with caching, deduplication, revalidation etc.\n *\n * @template ResponseData - The expected response data type.\n * @template RequestBody - The request payload type.\n * @template QueryParams - The query parameters type.\n * @template PathParams - The URL path parameters type.\n *\n * @param {string|null} url - The endpoint URL to fetch data from. Pass null to skip fetching.\n * If the URL is null, the hook will not perform any fetch operation.\n * If the URL is an empty string, it will default to the base URL configured in fetchff.\n * If the URL is a full URL, it will be used as is.\n * @param {RequestConfig} [config={}] - fetchff and native fetch compatible configuration.\n *\n * @returns {UseFetcherResult} An object containing:\n * - `data`: The fetched data or `null` if not yet available.\n * - `error`: Any error encountered during fetching or `null`.\n * - `isLoading`: Boolean indicating if the request is in progress.\n * - `mutate`: Function to update the cached data and optionally trigger revalidation.\n *\n * @remarks\n * - Designed for high performance: minimizes unnecessary re-renders and leverages fast cache key generation.\n * - Integrates with a global cache and pub/sub system for efficient state updates across contexts.\n * - Handles automatic revalidation, deduplication, retries, and cache management out of the box.\n *\n * @example\n * ```tsx\n * const { data, error, isLoading, mutate } = useFetcher('/api/data', {\n * refetchOnFocus: true,\n * cacheTime: 5,\n * dedupeTime: 2000,\n * cacheKey: (config) => `custom-cache-key-${config.url}`,\n * });\n * ```\n */\nexport function useFetcher<\n ResponseData = DefaultResponse,\n RequestBody = DefaultPayload,\n QueryParams = DefaultParams,\n PathParams = DefaultUrlParams,\n>(\n url: string | null,\n config: RequestConfig<\n ResponseData,\n QueryParams,\n PathParams,\n RequestBody\n > = {},\n): UseFetcherResult {\n // Efficient cache key generation based on URL and request parameters.\n // Optimized for speed: minimizes unnecessary function calls when possible\n const cacheKey = useMemo(\n () => (url === null ? null : generateCacheKey(buildConfig(url, config))),\n [\n config.cacheKey,\n url,\n config.url,\n config.method,\n config.headers,\n config.body,\n config.params,\n config.urlPathParams,\n config.apiUrl,\n config.baseURL,\n config.withCredentials,\n config.credentials,\n ],\n );\n const dedupeTime = config.dedupeTime ?? DEFAULT_DEDUPE_TIME_MS;\n const cacheTime = config.cacheTime || INFINITE_CACHE_TIME;\n const staleTime = config.staleTime ?? DEFAULT_STALE_TIME;\n\n // Determine if the fetch should be triggered immediately on mount\n const shouldTriggerOnMount =\n config.immediate ?? SAFE_METHODS.has(config.method || 'GET');\n\n const currentValuesRef = useRef(DEFAULT_REF);\n currentValuesRef.current = [url, config, cacheKey];\n\n // The initial data is shown while there's no cached response, e.g. during server-side rendering\n const initialResult = useMemo(\n () =>\n config.initialData === undefined\n ? null\n : Object.freeze({ ...DEFAULT_RESULT, data: config.initialData }),\n [cacheKey],\n );\n\n // Attempt to get the cached response immediately and if not available, return null\n const getSnapshot = useCallback(() => {\n const cached = getCache(\n cacheKey,\n );\n\n if (!cached && initialResult) {\n return initialResult as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }\n\n // Only throw for Suspense if we're in 'reject' mode and have no data\n if (\n config.strategy === 'reject' &&\n cacheKey &&\n (!cached || (!cached.data.data && !cached.data.error))\n ) {\n const pendingPromise = getInFlightPromise(cacheKey, dedupeTime);\n\n if (pendingPromise) {\n throw pendingPromise;\n }\n\n // If no pending promise but we need to fetch, start fetch and throw the promise\n if (!cached) {\n const [currUrl, currConfig, currCacheKey] = currentValuesRef.current;\n\n if (currUrl) {\n const fetchPromise = fetchf(currUrl, {\n ...currConfig,\n cacheKey: currCacheKey,\n dedupeTime,\n cacheTime,\n staleTime,\n strategy: 'softFail',\n cacheErrors: true,\n _isAutoKey: !currConfig.cacheKey,\n });\n\n throw fetchPromise;\n }\n }\n }\n\n if (cached) {\n return cached.data.isFetching && !config.keepPreviousData\n ? (FETCHING_RESULT as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >)\n : cached.data;\n }\n\n return (shouldTriggerOnMount\n ? FETCHING_RESULT\n : DEFAULT_RESULT) as unknown as FetchResponse<\n ResponseData,\n RequestBody,\n QueryParams,\n PathParams\n >;\n }, [cacheKey]);\n\n // Subscribe to cache updates for the specific cache key\n const doSubscribe = useCallback(\n (cb: () => void) => {\n incrementRef(cacheKey);\n\n // When the component mounts, we want to fetch data if:\n // 1. URL is provided\n // 2. shouldTriggerOnMount is true (so the \"immediate\" isn't specified or is true)\n // 3. There is no cached data\n // 4. There is no error\n // 5. There is no ongoing fetch operation\n const shouldFetch =\n shouldTriggerOnMount && url && cacheKey && getRefCount(cacheKey) === 1; // Check if no existing refs\n\n // Initial fetch logic\n if (shouldFetch) {\n // Stale-While-Revalidate Pattern: Check for both fresh and stale data\n const cached = getCachedResponse(cacheKey, cacheTime, config);\n\n if (!cached) {\n refetch(false);\n }\n }\n\n const unsubscribe = subscribe(cacheKey, cb);\n\n return () => {\n decrementRef(cacheKey, cacheTime, dedupeTime, url);\n unsubscribe();\n };\n },\n [cacheKey, shouldTriggerOnMount, url, dedupeTime, cacheTime],\n );\n\n const state = useSyncExternalStore<\n FetchResponse\n >(doSubscribe, getSnapshot, getSnapshot);\n\n const refetch = useCallback<\n RefetchFunction\n >(\n async (forceRefresh = true, requestConfig = {}) => {\n const [currUrl, currConfig, currCacheKey] = currentValuesRef.current;\n\n if (!currUrl) {\n return null;\n }\n\n // Truthy check for forceRefresh to ensure it's a boolean. It is useful in onClick handlers so to avoid additional annonymous function calls.\n const shouldRefresh = !!forceRefresh;\n\n // Fast path: check cache first if not forcing refresh\n if (!shouldRefresh && currCacheKey) {\n const cached = getCachedResponse(currCacheKey, cacheTime, currConfig);\n\n if (cached) {\n return cached;\n }\n }\n\n // When manual refetch is triggered, we want to ensure that the cache is busted\n // This can be disabled by passing `refetch(false)`\n const cacheBuster = shouldRefresh ? () => true : currConfig.cacheBuster;\n\n return fetchf(currUrl, {\n ...currConfig,\n cacheKey: currCacheKey,\n ...requestConfig,\n dedupeTime,\n cacheTime,\n staleTime,\n cacheBuster,\n // Ensure that errors are handled gracefully and not thrown by default\n strategy: 'softFail',\n cacheErrors: true,\n _isAutoKey: !currConfig.cacheKey,\n });\n },\n [cacheTime, dedupeTime],\n );\n\n const data = state.data;\n const isUnresolved = !data && !state.error;\n\n // This indicates if the request is in progress or if it is about to start on first mount\n // It is true when:\n // - The request is currently ongoing, and it is not background revalidation\n // - The request is unresolved (no data and no error) and shouldTriggerOnMount\n // is true (which means the request is about to start on mount)\n const isFetching =\n !!url && (state.isFetching || (isUnresolved && shouldTriggerOnMount));\n const isFirstFetch = isFetching && isUnresolved;\n const isRefetching = isFetching && !isUnresolved;\n\n // Consumers always destructure the return value and use the fields directly, so\n // memoizing the object doesn't change rerender behavior nor improve any performance here\n return {\n data,\n error: state.error,\n config: state.config,\n headers: state.headers,\n isFirstFetch,\n isFetching,\n isLoading: isFetching,\n isRefetching,\n isError: state.isError,\n isSuccess: state.isSuccess,\n mutate: state.mutate,\n refetch,\n };\n}\n"]} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 308f92c..6294516 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fetchff", - "version": "4.2.0", + "version": "4.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fetchff", - "version": "4.2.0", + "version": "4.3.0", "license": "MIT", "devDependencies": { "@size-limit/preset-small-lib": "12.1.0", diff --git a/package.json b/package.json index e518765..19dbb6f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fetchff", - "version": "4.2.0", + "version": "4.3.0", "license": "MIT", "author": "Matt Czapliński ", "repository": { diff --git a/src/response-parser.ts b/src/response-parser.ts index 9bf9004..2c7f3c4 100644 --- a/src/response-parser.ts +++ b/src/response-parser.ts @@ -236,14 +236,13 @@ export const prepareResponse = < // If it's a custom fetcher, and it does not return any Response instance, it may have its own internal handler if (isObject(response)) { - Object.assign(response, { - error, - headers, - isFetching: false, - mutate: mutatator, - isSuccess: response.ok && !error, - isError: !!error, - }); + // Assigned one by one, as Object.assign() with an object literal is measurably slower here + response.error = error; + response.headers = headers; + response.isFetching = false; + response.mutate = mutatator; + response.isSuccess = response.ok && !error; + response.isError = !!error; } return response;