From 66df0420135bc8e61e68887749ff8db8b8273fd7 Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 7 Feb 2026 19:24:26 +0100 Subject: [PATCH 01/30] fix: Timeout hangs indefinitely in React Native when the server is unreachable --- src/cache-manager.ts | 3 ++- src/index.ts | 2 +- src/inflight-manager.ts | 8 +++---- src/react/cache-ref.ts | 9 ++++++-- src/utils.ts | 22 ++++++++++++++++++++ test/utils.spec.ts | 46 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/cache-manager.ts b/src/cache-manager.ts index 02b0bbdd..dc9a9c98 100644 --- a/src/cache-manager.ts +++ b/src/cache-manager.ts @@ -290,11 +290,12 @@ export function setCache( const time = timeNow(); const ttlMs = ttl ? ttl * 1000 : 0; + const staleTimeMs = staleTime ? staleTime * 1000 : 0; // Ensure default value for staleTime _cache.set(key, { data, time, - stale: staleTime && staleTime > 0 ? time + staleTime * 1000 : staleTime, + stale: staleTimeMs > 0 ? time + staleTimeMs : undefined, // Use undefined if staleTime is not set expiry: ttl === -1 ? undefined : time + ttlMs, }); diff --git a/src/index.ts b/src/index.ts index b3c39351..5e7d1008 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,7 +38,7 @@ export { subscribe } from './pubsub-manager'; export { abortRequest, getInFlightPromise } from './inflight-manager'; /** Network and environment utilities (Browser Only) */ -export { isSlowConnection } from './utils'; +export { isSlowConnection, createAbortError } from './utils'; /** Timeout management for delayed operations */ export { addTimeout } from './timeout-wheel'; diff --git a/src/inflight-manager.ts b/src/inflight-manager.ts index dc70cbfa..793ef595 100644 --- a/src/inflight-manager.ts +++ b/src/inflight-manager.ts @@ -20,7 +20,7 @@ import { ABORT_ERROR, TIMEOUT_ERROR } from './constants'; import { addTimeout, removeTimeout } from './timeout-wheel'; -import { timeNow } from './utils'; +import { createAbortError, timeNow } from './utils'; export type InFlightItem = [ AbortController, // AbortController for the request @@ -76,7 +76,7 @@ export function markInFlight( // Abort previous request, if applicable, and continue as usual if (prevIsCancellable) { prevController.abort( - new DOMException('Aborted due to new request', ABORT_ERROR), + createAbortError('Aborted due to new request', ABORT_ERROR), ); } @@ -100,7 +100,7 @@ export function markInFlight( () => { abortRequest( key, - new DOMException(url + ' aborted due to timeout', TIMEOUT_ERROR), + createAbortError(url + ' aborted due to timeout', TIMEOUT_ERROR), ); }, timeout as number, @@ -119,7 +119,7 @@ export function markInFlight( */ export async function abortRequest( key: string | null, - error: DOMException | null | string = null, + error: DOMException | Error | null | string = null, ): Promise { // If the key is not in the queue, there's nothing to remove if (key) { diff --git a/src/react/cache-ref.ts b/src/react/cache-ref.ts index 1dacf322..d005a366 100644 --- a/src/react/cache-ref.ts +++ b/src/react/cache-ref.ts @@ -12,7 +12,12 @@ * @see deleteCache */ -import { addTimeout, abortRequest, deleteCache } from 'fetchff'; +import { + addTimeout, + abortRequest, + deleteCache, + createAbortError, +} from 'fetchff'; export const INFINITE_CACHE_TIME = -1; export const DEFAULT_DEDUPE_TIME_MS = 2000; @@ -57,7 +62,7 @@ export const decrementRef = ( // Abort any ongoing requests associated with this cache key abortRequest( key, - new DOMException('Request to ' + url + ' aborted', 'AbortError'), + createAbortError('Request to ' + url + ' aborted', 'AbortError'), ); // Check if the reference count is still zero before deleting the cache as it might have been incremented again diff --git a/src/utils.ts b/src/utils.ts index 79cdebda..69d2541f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -363,6 +363,28 @@ export function isBrowser(): boolean { ); } +/** + * Creates an abort/timeout error compatible with all JS runtimes. + * Falls back to a plain Error with the correct `name` when DOMException is unavailable (e.g. React Native). + * + * @param {string} message - The error message. + * @param {string} name - The error name (e.g. 'AbortError', 'TimeoutError'). + * @returns {DOMException | Error} - An error object with the specified name. + */ +export function createAbortError( + message: string, + name: string, +): DOMException | Error { + if (typeof DOMException !== UNDEFINED) { + return new DOMException(message, name); + } + + const error = new Error(message); + error.name = name; + + return error; +} + /** * Detects if the user is on a slow network connection * @returns {boolean} True if connection is slow, false otherwise or if detection unavailable diff --git a/test/utils.spec.ts b/test/utils.spec.ts index 6aa21471..134f4a46 100644 --- a/test/utils.spec.ts +++ b/test/utils.spec.ts @@ -6,6 +6,7 @@ import { processHeaders, sortObject, sanitizeObject, + createAbortError, } from '../src/utils'; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -696,4 +697,49 @@ describe('Utils', () => { expect(result).toEqual({}); }); }); + + describe('createAbortError()', () => { + it('should create a DOMException when DOMException is available', () => { + const error = createAbortError('test message', 'AbortError'); + + expect(error.message).toBe('test message'); + expect(error.name).toBe('AbortError'); + expect(error).toBeInstanceOf(DOMException); + }); + + it('should create a DOMException with TimeoutError name', () => { + const error = createAbortError('timeout message', 'TimeoutError'); + + expect(error.message).toBe('timeout message'); + expect(error.name).toBe('TimeoutError'); + }); + + it('should fall back to a plain Error when DOMException is unavailable (e.g. React Native)', () => { + const OriginalDOMException = globalThis.DOMException; + + try { + // Simulate React Native environment where DOMException is not defined + // eslint-disable-next-line @typescript-eslint/no-explicit-any + delete (globalThis as any).DOMException; + + const error = createAbortError('timeout', 'TimeoutError'); + + expect(error.message).toBe('timeout'); + expect(error.name).toBe('TimeoutError'); + expect(error).toBeInstanceOf(Error); + } finally { + globalThis.DOMException = OriginalDOMException; + } + }); + + it('should create errors usable with AbortController.abort()', () => { + const controller = new AbortController(); + const error = createAbortError('aborted', 'AbortError'); + + controller.abort(error); + + expect(controller.signal.aborted).toBe(true); + expect(controller.signal.reason).toBe(error); + }); + }); }); From 3c395d5ddc0be11ed993b2b7a38c4152fa22110b Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 01:35:57 +0100 Subject: [PATCH 02/30] fix: prevent race condition in fetchf() by yielding to microtask queue before onRequest interceptors --- src/request-handler.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/request-handler.ts b/src/request-handler.ts index 8d1c74a0..ebbc4eda 100644 --- a/src/request-handler.ts +++ b/src/request-handler.ts @@ -191,6 +191,16 @@ export async function fetchf< try { if (fetcherConfig.onRequest) { + // Zero-allocation yield to microtask queue so the outer fetchf() can call setInFlightPromise() + // before onRequest interceptors run. This ensures that if onRequest triggers + // another fetchf() with the same cacheKey, getInFlightPromise() finds item[4]. + // On retries (attempt > 0), setInFlightPromise() was already called during the first attempt. + // The promise stored in item[4] is the outer doRequestPromise which covers all retries. + // So the race only matters on the very first attempt when the outer scope hasn't had a chance to call setInFlightPromise() yet. + if (_cacheKey && dedupeTime && !attempt) { + await null; + } + await applyInterceptors(fetcherConfig.onRequest, requestConfig); } From 391aac1fc19126033d590dbb8b03563553387c58 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 01:59:19 +0100 Subject: [PATCH 03/30] fix: improve async handling in tests by using act() for state updates and cleanup --- test/react/index.spec.ts | 8 +- .../react/integration/error-handling.spec.tsx | 16 +- .../integration/fetchf-deduplication.spec.tsx | 199 ++++++++++++++++++ test/react/integration/hook.spec.tsx | 33 ++- .../integration/performance-caching.spec.tsx | 2 +- 5 files changed, 242 insertions(+), 16 deletions(-) create mode 100644 test/react/integration/fetchf-deduplication.spec.tsx diff --git a/test/react/index.spec.ts b/test/react/index.spec.ts index 5d3aa3fd..ece7b3a3 100644 --- a/test/react/index.spec.ts +++ b/test/react/index.spec.ts @@ -285,9 +285,11 @@ describe('useFetcher', () => { it('should show loading when no state and URL exists', async () => { const { result } = renderHook(() => useFetcher(testUrl)); - await waitFor(() => { - expect(result.current.isLoading).toBe(true); - }); + // isLoading is true synchronously before the fetch resolves + expect(result.current.isLoading).toBe(true); + + // Drain pending microtasks from await null in request-handler + await act(async () => {}); }); it('should not show loading when no URL', () => { diff --git a/test/react/integration/error-handling.spec.tsx b/test/react/integration/error-handling.spec.tsx index bf45f318..ca9701f0 100644 --- a/test/react/integration/error-handling.spec.tsx +++ b/test/react/integration/error-handling.spec.tsx @@ -2,7 +2,13 @@ * @jest-environment jsdom */ import '@testing-library/jest-dom'; -import { render, screen, waitFor, fireEvent } from '@testing-library/react'; +import { + render, + screen, + waitFor, + fireEvent, + act, +} from '@testing-library/react'; import React from 'react'; import { clearMockResponses, @@ -127,11 +133,15 @@ describe('Error Handling Integration Tests', () => { }); // Test retry functionality - fireEvent.click(screen.getByTestId('retry-button')); + await act(async () => { + fireEvent.click(screen.getByTestId('retry-button')); + }); expect(screen.getByTestId('connection-loading')).toHaveTextContent( 'Loading...', ); - jest.runAllTimers(); + await act(async () => { + jest.runAllTimers(); + }); await waitFor(() => { expect(abortSignal).not.toBeNull(); diff --git a/test/react/integration/fetchf-deduplication.spec.tsx b/test/react/integration/fetchf-deduplication.spec.tsx new file mode 100644 index 00000000..8933e7de --- /dev/null +++ b/test/react/integration/fetchf-deduplication.spec.tsx @@ -0,0 +1,199 @@ +/** + * @jest-environment jsdom + */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import '@testing-library/jest-dom'; +import { act, render, screen, waitFor, cleanup } from '@testing-library/react'; +import { fetchf } from '../../../src/index'; +import { useFetcher } from '../../../src/react/index'; +import { clearAllTimeouts } from '../../../src/timeout-wheel'; + +describe('fetchf deduplication and parking with jsdom and onRequest', () => { + afterEach(() => { + cleanup(); + jest.restoreAllMocks(); + clearAllTimeouts(); + delete (window as any).__dedupeTriggered; + }); + + it('deduplicates and parks requests when onRequest triggers a second identical fetchf call', async () => { + const testUrl = '/api/onrequest-dedupe'; + const cacheKey = 'onrequest-dedupe-key'; + let resolveFetch: ((value: Response) => void) | undefined; + let fetchCallCount = 0; + + // Mock global.fetch to simulate slow network + global.fetch = jest.fn().mockImplementation(() => { + fetchCallCount++; + return new Promise((resolve) => { + resolveFetch = resolve; + }); + }); + + // Track results from both calls + let onRequestResult: any = undefined; + + // Set up onRequest interceptor that triggers a second fetchf call + const onRequest = async (config: any) => { + if (!onRequestResult) { + // Trigger a second fetchf with the same cacheKey while the first is in-flight + onRequestResult = fetchf(testUrl, { + cacheKey, + dedupeTime: 2000, + }); + } + return config; + }; + + // Start first request with onRequest interceptor + const promise1 = fetchf(testUrl, { + cacheKey, + dedupeTime: 2000, + onRequest, + }); + + expect(promise1).not.toBeUndefined(); + + // Allow microtasks to flush so onRequest fires and the first doRequestOnce calls fetch() + await act(async () => { + await new Promise((r) => setTimeout(r, 0)); + }); + + // onRequest triggered a second fetchf that was deduped + expect(onRequestResult).not.toBeUndefined(); + expect(promise1).not.toBe(onRequestResult); // Different promise objects, but parked + + // Only one actual fetch call should have been made (the second was deduped) + expect(fetchCallCount).toBe(1); + + // Resolve the fetch with a proper mock response + await act(async () => { + if (resolveFetch) { + resolveFetch({ + ok: true, + status: 200, + data: { result: 'deduped-onrequest' }, + body: JSON.stringify({ result: 'deduped-onrequest' }), + headers: { 'content-type': 'application/json' }, + } as unknown as Response); + } + }); + + // Both promises should resolve to the same result + const [result1, result2] = await Promise.all([promise1, onRequestResult]); + expect(result1.data).toEqual({ result: 'deduped-onrequest' }); + expect(result2.data).toEqual({ result: 'deduped-onrequest' }); + expect(fetchCallCount).toBe(1); + }); + + it('useFetcher deduplication: onRequest triggers fetchf with same cacheKey, other useFetcher waits for it', async () => { + const testUrl = '/api/component-dedupe'; + const cacheKey = 'component-dedupe-key'; + let resolveFetch: ((value: Response) => void) | undefined; + let fetchCallCount = 0; + + // Mock global.fetch to simulate slow network + global.fetch = jest.fn().mockImplementation(() => { + fetchCallCount++; + return new Promise((resolve) => { + resolveFetch = resolve; + }); + }); + + // React test component that triggers the fetch + function DedupeComponent() { + const { data, isLoading } = useFetcher(testUrl, { + cacheKey, + dedupeTime: 2000, + immediate: true, + onRequest: async (config: any) => { + // Only trigger once to avoid infinite loop + if (!(window as any).__dedupeTriggered) { + (window as any).__dedupeTriggered = true; + // This fetchf call uses the same cacheKey and should be deduped + fetchf(testUrl, { cacheKey, dedupeTime: 2000 }); + } + return config; + }, + }); + return ( +
+
+ {data ? JSON.stringify(data) : 'No Data'} +
+
+ {isLoading ? 'Loading' : 'Not Loading'} +
+
+ ); + } + + // Another useFetcher instance that relies on the same cacheKey + function WaitingComponent() { + const { data, isLoading } = useFetcher(testUrl, { + cacheKey, + dedupeTime: 2000, + immediate: true, + }); + return ( +
+
+ {data ? JSON.stringify(data) : 'No Data'} +
+
+ {isLoading ? 'Loading' : 'Not Loading'} +
+
+ ); + } + + // Render both components + render( + <> + + + , + ); + + // Both should be loading initially + expect(screen.getByTestId('loading').textContent).toBe('Loading'); + expect(screen.getByTestId('waiting-loading').textContent).toBe('Loading'); + + // Allow microtasks to flush so the fetch is actually called + await act(async () => { + await new Promise((r) => setTimeout(r, 0)); + }); + + expect(fetchCallCount).toBe(1); + + // Resolve the fetch with a proper mock response + await act(async () => { + if (resolveFetch) { + resolveFetch({ + ok: true, + status: 200, + data: { result: 'deduped-component' }, + body: JSON.stringify({ result: 'deduped-component' }), + headers: { 'content-type': 'application/json' }, + } as unknown as Response); + } + }); + + // Both should show the result and not loading + await waitFor(() => { + expect(screen.getByTestId('data').textContent).toContain( + 'deduped-component', + ); + expect(screen.getByTestId('loading').textContent).toBe('Not Loading'); + expect(screen.getByTestId('waiting-data').textContent).toContain( + 'deduped-component', + ); + expect(screen.getByTestId('waiting-loading').textContent).toBe( + 'Not Loading', + ); + }); + + // Only one network request should have been made + expect(fetchCallCount).toBe(1); + }); +}); diff --git a/test/react/integration/hook.spec.tsx b/test/react/integration/hook.spec.tsx index 76aa5157..d08ddd8a 100644 --- a/test/react/integration/hook.spec.tsx +++ b/test/react/integration/hook.spec.tsx @@ -36,7 +36,10 @@ describe('React Integration Tests', () => { jest.useFakeTimers(); }); - afterEach(() => { + afterEach(async () => { + await act(async () => { + cleanup(); + }); jest.useRealTimers(); jest.resetAllMocks(); clearAllTimeouts(); @@ -1030,7 +1033,10 @@ describe('React Integration Tests', () => { ); }; - const { rerender } = render(); + let rerender!: ReturnType['rerender']; + await act(async () => { + ({ rerender } = render()); + }); await waitFor(() => { expect(screen.getByTestId('overlap-data1')).toHaveTextContent( @@ -1038,10 +1044,14 @@ describe('React Integration Tests', () => { ); }); - rerender(); - fireEvent.click(screen.getByTestId('overlap-refetch')); + await act(async () => { + rerender(); + fireEvent.click(screen.getByTestId('overlap-refetch')); + }); - rerender(); + await act(async () => { + rerender(); + }); expect(screen.getByTestId('overlap-phase')).toHaveTextContent('3'); }); @@ -1556,9 +1566,12 @@ describe('React Integration Tests', () => { const testCase = testCases[index]; mockFetchResponse(`/api/types-${index}`, testCase); - const { unmount } = render( - , - ); + let unmount!: ReturnType['unmount']; + await act(async () => { + ({ unmount } = render( + , + )); + }); await waitFor(() => { const dataText = screen.getByTestId('data').textContent; @@ -1570,7 +1583,9 @@ describe('React Integration Tests', () => { }); // Clean up between iterations to avoid multiple elements - unmount(); + await act(async () => { + unmount(); + }); } }); diff --git a/test/react/integration/performance-caching.spec.tsx b/test/react/integration/performance-caching.spec.tsx index f0676d87..26f73e81 100644 --- a/test/react/integration/performance-caching.spec.tsx +++ b/test/react/integration/performance-caching.spec.tsx @@ -847,7 +847,7 @@ describe('Performance & Caching Integration Tests', () => { }); // Should start loading non-critical data - act(() => { + await act(async () => { jest.advanceTimersByTime(600); }); From 52568701bccfc60d1f813117c7699797dd462248 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:17:05 +0100 Subject: [PATCH 04/30] perf: enhance sanitizeObject to check for dangerous properties before creating a shallow copy --- src/utils.ts | 21 +++++++++++++++------ test/utils.spec.ts | 12 ++++++++++-- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 69d2541f..d753ede3 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -46,18 +46,27 @@ export function shallowSerialize(obj: Record): string { /** * Removes properties that could lead to prototype pollution from an object. * - * This function creates a shallow copy of the input object with dangerous - * properties like '__proto__', 'constructor', and 'prototype' removed. + * This function checks for dangerous properties like '__proto__', 'constructor', + * and 'prototype'. If none are present, the object is returned as-is (zero-copy fast path). + * Otherwise, a shallow copy is created with the dangerous properties removed. * * @param obj - The object to sanitize - * @returns A new object without dangerous properties + * @returns A safe object without dangerous properties */ export function sanitizeObject>(obj: T): T { + const hasProto = Object.prototype.hasOwnProperty.call(obj, '__proto__'); + const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor'); + const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype'); + + if (!hasProto && !hasCtor && !hasPrototype) { + return obj; + } + const safeObj = { ...obj }; - delete safeObj.__proto__; - delete (safeObj as any).constructor; - delete safeObj.prototype; + if (hasProto) delete safeObj.__proto__; + if (hasCtor) delete (safeObj as any).constructor; + if (hasPrototype) delete safeObj.prototype; return safeObj; } diff --git a/test/utils.spec.ts b/test/utils.spec.ts index 134f4a46..ae802e44 100644 --- a/test/utils.spec.ts +++ b/test/utils.spec.ts @@ -49,14 +49,22 @@ describe('Utils', () => { ); }); - it('should return a new object reference', () => { + it('should return same reference when no dangerous properties exist', () => { const input = { a: 1, b: 2 }; const output = sanitizeObject(input); - expect(output).not.toBe(input); // Different reference + expect(output).toBe(input); // Same reference (zero-copy fast path) expect(output).toEqual(input); // Same content }); + it('should return a new object reference when dangerous properties exist', () => { + const input = { a: 1, b: 2, constructor: 'unsafe' }; + const output = sanitizeObject(input); + + expect(output).not.toBe(input); // Different reference + expect(output).toEqual({ a: 1, b: 2 }); // Dangerous props removed + }); + xit('should handle null and undefined inputs', () => { // @ts-expect-error Null and undefined are not objects expect(sanitizeObject(null)).toBeNull(); From 35842ed4a32103d0a57c4f323b510bd37f663aa4 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:18:00 +0100 Subject: [PATCH 05/30] fix: prevent cache key collisions from over-aggressive sanitization --- src/cache-manager.ts | 22 +++++++++++++++------- test/cache-manager.spec.ts | 22 +++++++++++----------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/cache-manager.ts b/src/cache-manager.ts index dc9a9c98..adc47dc9 100644 --- a/src/cache-manager.ts +++ b/src/cache-manager.ts @@ -23,7 +23,8 @@ export const IMMEDIATE_DISCARD_CACHE_TIME = 0; // Use it for cache entries that const _cache = new Map>(); const DELIMITER = '|'; const MIN_LENGTH_TO_HASH = 64; -const CACHE_KEY_SANITIZE_PATTERN = new RegExp('[^\\w\\-_|]', 'g'); +const CACHE_KEY_SANITIZE_PATTERN = /[^\w\-_|/:@.?=&~%#]/g; +const CACHE_KEY_NEEDS_SANITIZE = /[^\w\-_|/:@.?=&~%#]/; // Non-global for fast test /** * Headers that may affect HTTP response content and should be included in cache key generation. @@ -145,15 +146,18 @@ export function generateCacheKey( // For GET requests, return early with shorter cache key if (method === GET) { - return ( + const cacheStr = method + DELIMITER + url + DELIMITER + credentials + DELIMITER + - headersString - ).replace(CACHE_KEY_SANITIZE_PATTERN, ''); + headersString; + + return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr) + ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '') + : cacheStr; } let bodyString = ''; @@ -187,7 +191,7 @@ export function generateCacheKey( // Concatenate all key parts into a cache key string // Template literals are apparently slower - return ( + const cacheStr = method + DELIMITER + url + @@ -196,8 +200,12 @@ export function generateCacheKey( DELIMITER + headersString + DELIMITER + - bodyString - ).replace(CACHE_KEY_SANITIZE_PATTERN, ''); // Prevent cache poisoning by removal of anything that isn't letters, numbers, -, _, or | + bodyString; + + // Prevent cache poisoning by removal of control chars and unusual characters + return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr) + ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '') + : cacheStr; } /** diff --git a/test/cache-manager.spec.ts b/test/cache-manager.spec.ts index d88c2ed3..dd5ecdec 100644 --- a/test/cache-manager.spec.ts +++ b/test/cache-manager.spec.ts @@ -47,7 +47,7 @@ describe('Cache Manager', () => { 'Accept-Encoding': 'gzip, deflate, br', }, }); - expect(key).toContain('GET|httpsapiexamplecomdata'); + expect(key).toContain('GET|https://api.example.com/data'); }); it('should generate a cache key for basic GET request with empty url', () => { @@ -83,7 +83,7 @@ describe('Cache Manager', () => { } as never); expect(key).toContain( - 'GET|httpsapiexamplecomdata|same-origin|1306150308', + 'GET|https://api.example.com/data|same-origin|1306150308', ); }); @@ -94,7 +94,7 @@ describe('Cache Manager', () => { headers: { 'Content-Type': 'application/json' }, }); expect(key).toContain( - 'POST|httpsapiexamplecomdata|same-origin|395078312|', + 'POST|https://api.example.com/data|same-origin|395078312|', ); }); @@ -108,7 +108,7 @@ describe('Cache Manager', () => { }); expect(spy).toHaveBeenCalled(); expect(key).toContain( - 'POST|httpsapiexamplecomdata|same-origin||655859486', + 'POST|https://api.example.com/data|same-origin||655859486', ); }); @@ -122,7 +122,7 @@ describe('Cache Manager', () => { }); expect(spy).toHaveBeenCalled(); expect(key).toContain( - 'POST|httpsapiexamplecomdata|same-origin||-1171129837', + 'POST|https://api.example.com/data|same-origin||-1171129837', ); }); @@ -136,7 +136,7 @@ describe('Cache Manager', () => { }); expect(spy).not.toHaveBeenCalled(); expect(key).toContain( - 'POST|httpsapiexamplecomdata|same-origin||nameAlice', + 'POST|https://api.example.com/data|same-origin||name:Alice', ); }); @@ -150,7 +150,7 @@ describe('Cache Manager', () => { body: formData, }); expect(key).toContain( - 'POST|httpsapiexamplecomdata|same-origin||1870802307', + 'POST|https://api.example.com/data|same-origin||1870802307', ); }); @@ -162,7 +162,7 @@ describe('Cache Manager', () => { body: blob, }); expect(key).toContain( - 'POST|httpsapiexamplecomdata|same-origin||BF4textplain', + 'POST|https://api.example.com/data|same-origin||BF4text/plain', ); }); @@ -182,7 +182,7 @@ describe('Cache Manager', () => { method: 'POST', body: 10, }); - expect(key).toContain('POST|httpsapiexamplecomdata|same-origin||10'); + expect(key).toContain('POST|https://api.example.com/data|same-origin||10'); }); it('should handle Array body', () => { @@ -192,7 +192,7 @@ describe('Cache Manager', () => { method: 'POST', body: arrayBody, }); - expect(key).toContain('POST|httpsapiexamplecomdata|same-origin||011223'); + expect(key).toContain('POST|https://api.example.com/data|same-origin||0:11:22:3'); }); it('should handle Object body and sort properties', () => { @@ -203,7 +203,7 @@ describe('Cache Manager', () => { body: objectBody, }); - expect(key).toContain('POST|httpsapiexamplecomdata|same-origin||a1b2'); + expect(key).toContain('POST|https://api.example.com/data|same-origin||a:1b:2'); }); }); From 38292f6e429663bf99569be88a9580124007df17 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:18:48 +0100 Subject: [PATCH 06/30] perf: cache time tracking in markInFlight result instead of calling the same fn twice --- src/inflight-manager.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/inflight-manager.ts b/src/inflight-manager.ts index 793ef595..8015704a 100644 --- a/src/inflight-manager.ts +++ b/src/inflight-manager.ts @@ -55,6 +55,7 @@ export function markInFlight( return new AbortController(); } + const now = timeNow(); const item = inFlight.get(key); let prevPromise: Promise | null = null; @@ -66,7 +67,7 @@ export function markInFlight( // If the request is already in the queue and within the dedupeTime, reuse the existing controller if ( !prevIsCancellable && - timeNow() - item[2] < dedupeTime && + now - item[2] < dedupeTime && !prevController.signal.aborted ) { return prevController; @@ -89,7 +90,7 @@ export function markInFlight( inFlight.set(key, [ controller, isTimeoutEnabled, - timeNow(), + now, isCancellable, prevPromise, ]); From 5a490d5e37f7e4fc97b1dbf7a3563f8c4b672851 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:20:46 +0100 Subject: [PATCH 07/30] perf: single lookup instead of 2 in ensureListenerSet function --- src/pubsub-manager.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pubsub-manager.ts b/src/pubsub-manager.ts index bbf0a0ec..3c5a218f 100644 --- a/src/pubsub-manager.ts +++ b/src/pubsub-manager.ts @@ -28,11 +28,14 @@ type Listener = (response: T) => void; const listeners = new Map>(); function ensureListenerSet(key: string) { - if (!listeners.has(key)) { - listeners.set(key, new Set()); + let set = listeners.get(key); + + if (!set) { + set = new Set(); + listeners.set(key, set); } - return listeners.get(key)!; + return set; } // eslint-disable-next-line @typescript-eslint/no-explicit-any From 1ea9134fb31d215350836d36c36bfd8ffa36de23 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:21:26 +0100 Subject: [PATCH 08/30] text: adjust expected cache keys --- test/cache-manager.spec.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/cache-manager.spec.ts b/test/cache-manager.spec.ts index dd5ecdec..a554d776 100644 --- a/test/cache-manager.spec.ts +++ b/test/cache-manager.spec.ts @@ -182,7 +182,9 @@ describe('Cache Manager', () => { method: 'POST', body: 10, }); - expect(key).toContain('POST|https://api.example.com/data|same-origin||10'); + expect(key).toContain( + 'POST|https://api.example.com/data|same-origin||10', + ); }); it('should handle Array body', () => { @@ -192,7 +194,9 @@ describe('Cache Manager', () => { method: 'POST', body: arrayBody, }); - expect(key).toContain('POST|https://api.example.com/data|same-origin||0:11:22:3'); + expect(key).toContain( + 'POST|https://api.example.com/data|same-origin||0:11:22:3', + ); }); it('should handle Object body and sort properties', () => { @@ -203,7 +207,9 @@ describe('Cache Manager', () => { body: objectBody, }); - expect(key).toContain('POST|https://api.example.com/data|same-origin||a:1b:2'); + expect(key).toContain( + 'POST|https://api.example.com/data|same-origin||a:1b:2', + ); }); }); From 98b84dcb9e6ef6cf43483dffd4c5f5edb4fdd457 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:24:13 +0100 Subject: [PATCH 09/30] perf: improve request handling for retries with stale revalidation --- src/request-handler.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/request-handler.ts b/src/request-handler.ts index ebbc4eda..876fdfad 100644 --- a/src/request-handler.ts +++ b/src/request-handler.ts @@ -296,8 +296,16 @@ export async function fetchf< }; // Inline and minimize function wrappers for performance + // When retries are enabled, forward isStaleRevalidation so the first attempt + // of a background SWR revalidation doesn't incorrectly mark the request as in-flight const baseRequest = - retries > 0 ? () => withRetry(doRequestOnce, retryConfig) : doRequestOnce; + retries > 0 + ? (isStaleRevalidation = false) => + withRetry( + (_, attempt) => doRequestOnce(isStaleRevalidation, attempt), + retryConfig, + ) + : doRequestOnce; const requestWithErrorHandling = (isStaleRevalidation = false) => withErrorHandling( From 6247d52d03305ae9d2724a76fc94eb9feb7b6f90 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:24:23 +0100 Subject: [PATCH 10/30] perf: optimize revalidation loop by using for...of instead of forEach --- src/revalidator-manager.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/revalidator-manager.ts b/src/revalidator-manager.ts index 18781647..dbed6ac5 100644 --- a/src/revalidator-manager.ts +++ b/src/revalidator-manager.ts @@ -64,9 +64,9 @@ export function revalidateAll( const flagIndex = type === 'focus' ? 5 : 6; const now = timeNow(); - revalidators.forEach((entry) => { + for (const entry of revalidators.values()) { if (!entry[flagIndex]) { - return; + continue; } entry[1] = now; @@ -77,7 +77,7 @@ export function revalidateAll( if (revalidator) { Promise.resolve(revalidator(isStaleRevalidation)).catch(noop); } - }); + } } /** From afd016cbe10c89833b22ddf61ef08bcf59c4d385 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:24:49 +0100 Subject: [PATCH 11/30] fix: enhance timeout handling for sub-second values and improve edge case tests --- src/timeout-wheel.ts | 35 ++++++++++++++++++++++++----------- test/timeout-wheel.spec.ts | 4 ++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/timeout-wheel.ts b/src/timeout-wheel.ts index e78cea54..e1492afc 100644 --- a/src/timeout-wheel.ts +++ b/src/timeout-wheel.ts @@ -57,8 +57,8 @@ export const addTimeout = ( ): void => { removeTimeout(key); - // Fallback to setTimeout if wheel size is exceeded or ms is not divisible by SECOND - if (ms > MAX_WHEEL_MS || ms % SECOND !== 0) { + // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND + if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) { keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot return; @@ -74,8 +74,15 @@ export const addTimeout = ( if (!timer) { timer = setInterval(() => { position = (position + 1) % WHEEL_SIZE; - wheel[position].forEach(handleCallback); - wheel[position] = []; + const slot = wheel[position]; + + // Use slot.length directly (not cached) so mid-iteration mutations + // from callbacks (e.g. removeTimeout) are handled correctly + for (let i = 0; i < slot.length; i++) { + handleCallback(slot[i]); + } + + slot.length = 0; // Reuse array, avoid GC allocation if (!keyMap.size && timer) { clearInterval(timer); @@ -93,10 +100,12 @@ export const removeTimeout = (key: string): void => { if (Array.isArray(slotOrTimeout)) { clearTimeout(slotOrTimeout[0]); } else { - wheel[slotOrTimeout].splice( - wheel[slotOrTimeout].findIndex(([k]) => k === key), - 1, - ); + const slotArr = wheel[slotOrTimeout]; + const idx = slotArr.findIndex(([k]) => k === key); + + if (idx !== -1) { + slotArr.splice(idx, 1); + } } keyMap.delete(key); @@ -110,11 +119,11 @@ export const removeTimeout = (key: string): void => { export const clearAllTimeouts = () => { // Clear native setTimeout timeouts first! - keyMap.forEach((value) => { + for (const value of keyMap.values()) { if (Array.isArray(value)) { clearTimeout(value[0]); } - }); + } if (timer) { clearInterval(timer); @@ -122,6 +131,10 @@ export const clearAllTimeouts = () => { } keyMap.clear(); - wheel.forEach((slot) => (slot.length = 0)); + + for (let i = 0; i < WHEEL_SIZE; i++) { + wheel[i].length = 0; + } + position = 0; }; diff --git a/test/timeout-wheel.spec.ts b/test/timeout-wheel.spec.ts index 1139c8b9..fe0447cd 100644 --- a/test/timeout-wheel.spec.ts +++ b/test/timeout-wheel.spec.ts @@ -265,13 +265,13 @@ describe('Timeout Wheel', () => { }); describe('Edge Cases', () => { - it('should handle zero timeout', () => { + it('should handle zero timeout via setTimeout fallback', () => { const callback = jest.fn(); addTimeout('zero', callback, 0); jest.advanceTimersByTime(1); - expect(callback).toHaveBeenCalledTimes(0); // Should not execute immediately + expect(callback).toHaveBeenCalledTimes(1); // Fires via setTimeout(cb, 0) }); it('should handle timeout at wheel boundary', () => { From c6d3ed3d9431db0de3a0e29175758b44ee1aff52 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:25:35 +0100 Subject: [PATCH 12/30] test: remove unnecessary skipped tests for null, undefined, array, and primitive inputs in sanitizeObject --- test/utils.spec.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/test/utils.spec.ts b/test/utils.spec.ts index ae802e44..f2c7e385 100644 --- a/test/utils.spec.ts +++ b/test/utils.spec.ts @@ -65,27 +65,6 @@ describe('Utils', () => { expect(output).toEqual({ a: 1, b: 2 }); // Dangerous props removed }); - xit('should handle null and undefined inputs', () => { - // @ts-expect-error Null and undefined are not objects - expect(sanitizeObject(null)).toBeNull(); - // @ts-expect-error Null and undefined are not objects - expect(sanitizeObject(undefined)).toBeUndefined(); - }); - - xit('should handle array inputs without modification', () => { - const input = [1, 2, 3]; - expect(sanitizeObject(input)).toEqual(input); - }); - - xit('should handle primitive inputs without modification', () => { - // @ts-expect-error String, number, and boolean are not objects - expect(sanitizeObject('string')).toBe('string'); - // @ts-expect-error String, number, and boolean are not objects - expect(sanitizeObject(123)).toBe(123); - // @ts-expect-error String, number, and boolean are not objects - expect(sanitizeObject(true)).toBe(true); - }); - it('should preserve all safe properties', () => { const date = new Date(); const input = { From 5c4da09512f87960bc4d4223a6f9bd30680da090 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:37:43 +0100 Subject: [PATCH 13/30] chore: update dev dependencies and react package limit - Updated @testing-library/react from 16.3.0 to 16.3.2 - Updated @types/react from 19.2.7 to 19.2.13 - Updated eslint-plugin-prettier from 5.5.4 to 5.5.5 - Updated globals from 16.5.0 to 17.3.0 - Updated prettier from 3.7.4 to 3.8.1 - Updated react from 19.2.1 to 19.2.4 - Updated react-dom from 19.2.1 to 19.2.4 - Updated typescript-eslint from 8.48.1 to 8.54.0 - Increased size limit for dist/react/index.js from 9.5 KB to 10 KB --- dist/browser/index.global.js | 4 +- dist/browser/index.global.js.map | 2 +- dist/browser/index.mjs | 4 +- dist/browser/index.mjs.map | 2 +- dist/node/index.js | 4 +- dist/node/index.js.map | 2 +- dist/react/index.js | 2 +- dist/react/index.js.map | 2 +- dist/react/index.mjs | 2 +- dist/react/index.mjs.map | 2 +- package-lock.json | 254 +++++++++++++++---------------- package.json | 18 +-- 12 files changed, 145 insertions(+), 153 deletions(-) diff --git a/dist/browser/index.global.js b/dist/browser/index.global.js index f49227c7..45593b60 100644 --- a/dist/browser/index.global.js +++ b/dist/browser/index.global.js @@ -1,3 +1,3 @@ -var fetchff=(function(exports){'use strict';var ct=Object.defineProperty;var ft=(e,t,r)=>t in e?ct(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var L=(e,t,r)=>ft(e,typeof t!="symbol"?t+"":t,r);var x="application/",j=x+"json",Ne="charset=utf-8",C="Content-Type",h="undefined",K="object",b="string",g="function",ee="AbortError",Se="TimeoutError",O="GET",ve="HEAD",te="reject";var Ue=10;function re(e){return e instanceof URLSearchParams}function p(e){return e!==null&&typeof e===K}function J(e){let t={...e};return delete t.__proto__,delete t.constructor,delete t.prototype,t}function He(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=Ue)return r;let c,R,P;if(l)if(Array.isArray(i))for(c=0,R=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function ae(e){return e.includes("://")}var y=()=>Date.now(),Q=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==h&&typeof globalThis.Buffer!==h&&globalThis.Buffer.isBuffer(e)||e instanceof Date||re(e)?false:!!(p(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&p(e)&&typeof e.data!==h?De(e.data,t+1):e}function ne(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a]=r;});else if(p(e))for(let[r,a]of Object.entries(e))t[r.toLowerCase()]=a;return t}function se(){return typeof window!==h&&typeof window.addEventListener===g}var Te=()=>{if(!se())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function w(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&p(t)&&p(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&p(t)&&p(n)&&Object.assign(t,n);}}}var oe=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;L(this,"status");L(this,"statusText");L(this,"config");L(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ie=class extends oe{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var le=600,ue=1e3,mt=le*ue,k=Array(le).fill(0).map(()=>[]),q=new Map,z=0,E=null,je=([e,t])=>{q.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(Q);}catch(r){}},I=(e,t,r)=>{if(S(e),r>mt||r%ue!==0){q.set(e,[setTimeout(je.bind(null,[e,t]),r)]);return}let a=r/ue,n=(z+a)%le;k[n].push([e,t]),q.set(e,n),E||(E=setInterval(()=>{z=(z+1)%le,k[z].forEach(je),k[z]=[],!q.size&&E&&(clearInterval(E),E=null);},ue));},S=e=>{let t=q.get(e);t!==void 0&&(Array.isArray(t)?clearTimeout(t[0]):k[t].splice(k[t].findIndex(([r])=>r===e),1),q.delete(e),!q.size&&E&&(clearInterval(E),E=null));};var A=new Map;function Ke(e,t,r,a,n,s){if(!e)return new AbortController;let o=A.get(e),u=null;if(o){let i=o[0],m=o[3];if(!m&&y()-o[2]{Je(e,new DOMException(t+" aborted due to timeout",Se));},r),l}async function Je(e,t=null){if(e){let r=A.get(e);r&&(t&&r[0].abort(t),ce(e));}}function ce(e){S(e),A.delete(e);}function ze(e,t){let r=A.get(e);r&&(r[4]=t,A.set(e,r));}function be(e,t){if(!e)return null;let r=A.get(e);return r&&r[4]&&!r[3]&&y()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(Q);});}async function me(e,t=false){if(!e)return null;let r=W.get(e);if(r){r[1]=y();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function dt(e){Rt(e);let t=e==="focus"?5:6;W.forEach((r,a)=>{r[t]&&yt(a);});}function ke(e){if(!se()||fe.has(e))return;let t=Ge.bind(null,e,true);fe.set(e,t),window.addEventListener(e,t);}function Rt(e){if(!se())return;let t=fe.get(e);t&&(window.removeEventListener(e,t),fe.delete(e));}function We(e,t,r,a,n,s,o){W.set(e,[t,y(),pt,a,n,s,o]),s&&ke("focus"),o&&ke("online"),a&&I("s:"+e,me.bind(null,e,true),a*1e3);}function yt(e){W.delete(e),S("s:"+e);}var v=new Map;function Pt(e){return v.has(e)||v.set(e,new Set),v.get(e)}function ht(e,t){Pt(e).add(t);}function gt(e,t){let r=v.get(e);r&&(r.delete(t),r.size===0&&v.delete(e));}function _(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 Dt(e,t){return e?(ht(e,t),()=>{gt(e,t);}):Q}var Ee=(Te()?60:30)*1e3,U={strategy:te,timeout:Ee,headers:{Accept:j+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:Ee/30,maxDelay:Ee,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Tt(e){let t=J(e);return Object.assign(U,t),U}function Ve(){return {...U}}function Ce(e,t){if(!t)return Ye(e,Ve());let r=J(t),a=Y(U,r);return Ye(e,a)}function Ye(e,t){var i;let r=t.method;r=r?r.toUpperCase():O;let a;r!==O&&r!==ve&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==b&&ge(a)&&(a=JSON.stringify(a))),bt(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),l=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function bt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==h&&t instanceof Blob||typeof File!==h&&t instanceof File||typeof ReadableStream!==h&&t instanceof ReadableStream)return;let r;if(re(t))r=x+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=x+"octet-stream";else if(ge(t))r=j+";"+Ne;else return;e instanceof Headers?e.has(C)||e.set(C,r):p(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function Y(e,t){let r=Object.assign({},e,t);return $e("retry",r,e,t),$e("headers",r,e,t),xe("onRequest",r,e,t),xe("onResponse",r,e,t),xe("onError",r,e,t),r}function xe(e,t,r,a){let n=r[e],s=a[e];if(!n&&!s)return;if(!n){t[e]=s;return}if(!s){t[e]=n;return}let o=Array.isArray(n)?n:[n],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function $e(e,t,r,a){a[e]&&(t[e]={...r[e],...a[e]});}var de=new Map,B="|",we=64,Ze=new RegExp("[^\\w\\-_|]","g"),Et=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 $(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=O,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let m;s instanceof Headers?m=ne(s):m=s;let c=Object.keys(m),R=c.length;R>1&&c.sort();let P="";for(let f=0;f{i+=c+"="+m+"&";}),i.length>we&&(i=G(i));else if(typeof Blob!==h&&o instanceof Blob||typeof File!==h&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let m=p(o)?JSON.stringify(He(o)):String(o);i=m.length>we?G(m):m;}return (n+B+a+B+u+B+l+B+i).replace(Ze,"")}function Xe(e){return e.expiry?y()>e.expiry:false}function xt(e){return e.stale?y()>e.stale:false}function Re(e){return de.get(e)}function ye(e,t,r,a){if(r===0){pe(e);return}let n=y(),s=r?r*1e3:0;de.set(e,{data:t,time:n,stale:a&&a>0?n+a*1e3:a,expiry:r===-1?void 0:n+s}),s>0&&I("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=Re(e);if(!r||!Xe(r))return}de.delete(e);}async function qe(e,t,r){if(!e)return null;let a=Re(e);if(!a)return null;let n=p(t)?J(t):t,s={...a.data,data:n},o={...a,data:s};return de.set(e,o),_(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||U.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=Re(e);if(!n)return null;let s=Xe(n),o=xt(n);return s?(pe(e),null):!o||o&&!s?n.data:null}function Ie(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&ye(a,e,n,t.staleTime),_(a,e),ce(a);let o=t._prevKey;o&&ce(o);}}async function et(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(j)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(x+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(x+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===b){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 Ae=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=qe.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===K&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let l=ne(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(p(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function tt(e){let t=Date.parse(e)-y();return isNaN(t)?null:Math.max(0,Math.floor(t))}function Ct(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 u=tt(r);if(u!==null)return u}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?tt(s):null}async function rt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,H=f.onRetry;H&&(await w(H,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=$(f,false)));}c=await e(l>0,l);let R=c.error;if(!R){if(u&&l0&&await N(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await N(t);return o}async function nt(e,t,r){let a=await t(e),n=a.error;if(!n)return Ie(a,r),a;r.onError&&await w(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&qt(r,"FETCH ERROR",n),Ie(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===te)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function st(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===ee;}function qt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Be={isFetching:true};async function he(e,t=null){let r=Ce(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,R=u!==void 0||l!==void 0,P=!!(s||a||o||R||n||i||m),f=null;if(P&&(f=$(r)),f&&R){let T=Pe(f,u,r);if(T)return T}if(f&&o){let T=be(f,o);if(T)return T}let H=r.retry||{},{retries:ot=0,resetTimeout:it}=H,Fe=async(T=false,Qe=0)=>{Qe||(f&&!T&&(l?Pe(f,u,r)||(ye(f,Be,u,l),_(f,Be)):_(f,Be)),r.cacheKey=f);let Z=r.url,lt=Ke(f,Z,a,o||0,!!n,!!(a&&(!Qe||it))),D=r;D.signal=lt.signal;let X,d=null;try{r.onRequest&&await w(r.onRequest,D);let F=r.fetcher;if(d=F?await F(Z,D):await fetch(Z,D),p(d)&&(typeof Response===g&&d instanceof Response?d.data=await et(d):F&&("data"in d&&"body"in d||(d={data:d})),d.config=D,d.ok!==void 0&&!d.ok))throw new ie(`${D.method} to ${Z} failed! Status: ${d.status||null}`,D,d);X=Ae(d,D);let M=r.onResponse;M&&await w(M,X);}catch(F){let M=F;st(M,d,D),X=Ae(d,D,M);}return X},ut=ot>0?()=>rt(Fe,H):Fe,V=(T=false)=>nt(T,ut,r),Oe=c?at(V,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):V();return f&&(o&&ze(f,Oe),We(f,V,void 0,l,V,!!i,!!m)),Oe}function It(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(l)?(o==null?void 0:o.url)===l?Y(u,s):s:Y(Y(e,u),s);return he(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=Je;exports.addTimeout=I;exports.buildConfig=Ce;exports.createApiFetcher=It;exports.deleteCache=pe;exports.fetchf=he;exports.fetchff=he;exports.generateCacheKey=$;exports.getCache=Re;exports.getCachedResponse=Pe;exports.getDefaultConfig=Ve;exports.getInFlightPromise=be;exports.isSlowConnection=Te;exports.mutate=qe;exports.removeRevalidators=dt;exports.revalidate=me;exports.revalidateAll=Ge;exports.setCache=ye;exports.setDefaultConfig=Tt;exports.subscribe=Dt;return exports;})({});//# sourceMappingURL=index.global.js.map +var fetchff=(function(exports){'use strict';var mt=Object.defineProperty;var pt=(e,t,r)=>t in e?mt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var L=(e,t,r)=>pt(e,typeof t!="symbol"?t+"":t,r);var C="application/",j=C+"json",ve="charset=utf-8",w="Content-Type",R="undefined",K="object",E="string",g="function",ee="AbortError",Ne="TimeoutError",S="GET",_e="HEAD",te="reject";var He=10;function re(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===K}function J(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(c)+"="+a(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function ae(e){return e.includes("://")}var P=()=>Date.now(),v=()=>{};function De(e){let t=typeof e;return e==null?false:t===E||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||re(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function Te(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?Te(e.data,t+1):e}function ne(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a]=r;});else if(d(e))for(let[r,a]of Object.entries(e))t[r.toLowerCase()]=a;return t}function se(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var be=()=>{if(!se())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;L(this,"status");L(this,"statusText");L(this,"config");L(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,z=1e3,dt=ce*z,Ee=Array(ce).fill(0).map(()=>[]),A=new Map,le=0,x=null,Ke=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(v);}catch(r){}},I=(e,t,r)=>{if(_(e),rdt||r%z!==0){A.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let a=r/z,n=(le+a)%ce;Ee[n].push([e,t]),A.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Ee[le];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ze(e,oe(t+" aborted due to timeout",Ne));},r),i}async function ze(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),B.delete(e);}function ke(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function xe(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&ht(a);});}function Ge(e){if(!se()||me.has(e))return;let t=We.bind(null,e,true);me.set(e,t),window.addEventListener(e,t);}function Pt(e){if(!se())return;let t=me.get(e);t&&(window.removeEventListener(e,t),me.delete(e));}function Ye(e,t,r,a,n,s,o){G.set(e,[t,P(),yt,a,n,s,o]),s&&Ge("focus"),o&&Ge("online"),a&&I("s:"+e,pe.bind(null,e,true),a*1e3);}function ht(e){G.delete(e),_("s:"+e);}var W=new Map;function gt(e){let t=W.get(e);return t||(t=new Set,W.set(e,t)),t}function Dt(e,t){gt(e).add(t);}function Tt(e,t){let r=W.get(e);r&&(r.delete(t),r.size===0&&W.delete(e));}function U(e,t){let r=W.get(e);if(r)if(r.size===1){let a=r.values().next().value;a(t);}else r.forEach(a=>a(t));}function bt(e,t){return e?(Dt(e,t),()=>{Tt(e,t);}):v}var Ce=(be()?60:30)*1e3,H={strategy:te,timeout:Ce,headers:{Accept:j+", 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 Et(e){let t=J(e);return Object.assign(H,t),H}function Ve(){return {...H}}function qe(e,t){if(!t)return $e(e,Ve());let r=J(t),a=Y(H,r);return $e(e,a)}function $e(e,t){var i;let r=t.method;r=r?r.toUpperCase():S;let a;r!==S&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==E&&De(a)&&(a=JSON.stringify(a))),xt(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=n,t.body=a,t}function xt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(re(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(De(t))r=j+";"+ve;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function Y(e,t){let r=Object.assign({},e,t);return Ze("retry",r,e,t),Ze("headers",r,e,t),we("onRequest",r,e,t),we("onResponse",r,e,t),we("onError",r,e,t),r}function we(e,t,r,a){let n=r[e],s=a[e];if(!n&&!s)return;if(!n){t[e]=s;return}if(!s){t[e]=n;return}let o=Array.isArray(n)?n:[n],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Ze(e,t,r,a){a[e]&&(t[e]={...r[e],...a[e]});}var ye=new Map,F="|",Ae=64,Xe=/[^\w\-_|/:@.?=&~%#]/g,et=/[^\w\-_|/:@.?=&~%#]/,Ct=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 $(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===E?r:r(e);let{url:a="",method:n=S,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=ne(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>Ae&&(i=k(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Me(o)):String(o);i=l.length>Ae?k(l):l;}let m=n+F+a+F+u+F+c+F+i;return et.test(m)?m.replace(Xe,""):m}function tt(e){return e.expiry?P()>e.expiry:false}function wt(e){return e.stale?P()>e.stale:false}function Re(e){return ye.get(e)}function Pe(e,t,r,a){if(r===0){de(e);return}let n=P(),s=r?r*1e3:0,o=a?a*1e3:0;ye.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&I("c:"+e,()=>{de(e,true);},s);}function de(e,t=false){if(t){let r=Re(e);if(!r||!tt(r))return}ye.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=Re(e);if(!a)return null;let n=d(t)?J(t):t,s={...a.data,data:n},o={...a,data:s};return ye.set(e,o),U(e,s),r&&r.refetch?await pe(e):null}function he(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||H.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=Re(e);if(!n)return null;let s=tt(n),o=wt(n);return s?(de(e),null):!o||o&&!s?n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Pe(a,e,n,t.staleTime),U(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function rt(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(j)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===E){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===K&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=Te(u)),t.select&&(e.data=u=t.select(u));let c=ne(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function at(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function qt(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 u=at(r);if(u!==null)return u}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?at(s):null}async function nt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=a,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=$(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await N(t);return o}async function ot(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await q(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&It(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===te)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function it(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===ee;}function It(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe={isFetching:true};async function ge(e,t=null){let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||a||o||p||n||i||m),f=null;if(h&&(f=$(r)),f&&p){let T=he(f,u,r);if(T)return T}if(f&&o){let T=xe(f,o);if(T)return T}let D=r.retry||{},{retries:ut=0,resetTimeout:lt}=D,Qe=async(T=false,V=0)=>{V||(f&&!T&&(c?he(f,u,r)||(Pe(f,Oe,u,c),U(f,Oe)):U(f,Oe)),r.cacheKey=f);let O=r.url,ft=Je(f,O,a,o||0,!!n,!!(a&&(!V||lt))),b=r;b.signal=ft.signal;let X,y=null;try{r.onRequest&&(f&&o&&!V&&await null,await q(r.onRequest,b));let Q=r.fetcher;if(y=Q?await Q(O,b):await fetch(O,b),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await rt(y):Q&&("data"in y&&"body"in y||(y={data:y})),y.config=b,y.ok!==void 0&&!y.ok))throw new ue(`${b.method} to ${O} failed! Status: ${y.status||null}`,b,y);X=Fe(y,b);let M=r.onResponse;M&&await q(M,X);}catch(Q){let M=Q;it(M,y,b),X=Fe(y,b,M);}return X},ct=ut>0?(T=false)=>nt((V,O)=>Qe(T,O),D):Qe,Z=(T=false)=>ot(T,ct,r),Se=l?st(Z,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):Z();return f&&(o&&ke(f,Se),Ye(f,Z,void 0,c,Z,!!i,!!m)),Se}function Bt(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=t[n],u=o||{url:String(n)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?(o==null?void 0:o.url)===c?Y(u,s):s:Y(Y(e,u),s);return ge(c,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} +exports.abortRequest=ze;exports.addTimeout=I;exports.buildConfig=qe;exports.createAbortError=oe;exports.createApiFetcher=Bt;exports.deleteCache=de;exports.fetchf=ge;exports.fetchff=ge;exports.generateCacheKey=$;exports.getCache=Re;exports.getCachedResponse=he;exports.getDefaultConfig=Ve;exports.getInFlightPromise=xe;exports.isSlowConnection=be;exports.mutate=Ie;exports.removeRevalidators=Rt;exports.revalidate=pe;exports.revalidateAll=We;exports.setCache=Pe;exports.setDefaultConfig=Et;exports.subscribe=bt;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 0f006c71..79492edf 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","message","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","error","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","revalidateAll","type","isStaleRevalidation","flagIndex","now","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","addListener","fn","removeListener","set","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function creates a shallow copy of the input object with dangerous\n * properties like '__proto__', 'constructor', and 'prototype' removed.\n *\n * @param obj - The object to sanitize\n * @returns A new object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const safeObj = { ...obj };\n\n delete safeObj.__proto__;\n delete (safeObj as any).constructor;\n delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 * 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded or ms is not divisible by SECOND\n if (ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n wheel[position].forEach(handleCallback);\n wheel[position] = [];\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 wheel[slotOrTimeout].splice(\n wheel[slotOrTimeout].findIndex(([k]) => k === key),\n 1,\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 wheel.forEach((slot) => (slot.length = 0));\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 { 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 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 timeNow() - 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 new DOMException('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 timeNow(),\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n new DOMException(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 | 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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n if (!listeners.has(key)) {\n listeners.set(key, new Set());\n }\n\n return listeners.get(key)!;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 = new RegExp('[^\\\\w\\\\-_|]', 'g');\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 return (\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString\n ).replace(CACHE_KEY_SANITIZE_PATTERN, '');\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 return (\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString +\n DELIMITER +\n bodyString\n ).replace(CACHE_KEY_SANITIZE_PATTERN, ''); // Prevent cache poisoning by removal of anything that isn't letters, numbers, -, _, or |\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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\n _cache.set(key, {\n data,\n time,\n stale: staleTime && staleTime > 0 ? time + staleTime * 1000 : staleTime,\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 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 = 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} to ${url} failed! Status: ${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 const baseRequest =\n retries > 0 ? () => withRetry(doRequestOnce, retryConfig) : 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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","revalidateAll","type","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/browser/index.mjs b/dist/browser/index.mjs index ee7fae59..4a9c89dc 100644 --- a/dist/browser/index.mjs +++ b/dist/browser/index.mjs @@ -1,3 +1,3 @@ -var ct=Object.defineProperty;var ft=(e,t,r)=>t in e?ct(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var L=(e,t,r)=>ft(e,typeof t!="symbol"?t+"":t,r);var x="application/",j=x+"json",Ne="charset=utf-8",C="Content-Type",h="undefined",K="object",b="string",g="function",ee="AbortError",Se="TimeoutError",O="GET",ve="HEAD",te="reject";var Ue=10;function re(e){return e instanceof URLSearchParams}function p(e){return e!==null&&typeof e===K}function J(e){let t={...e};return delete t.__proto__,delete t.constructor,delete t.prototype,t}function He(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=Ue)return r;let c,R,P;if(l)if(Array.isArray(i))for(c=0,R=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function ae(e){return e.includes("://")}var y=()=>Date.now(),Q=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==h&&typeof globalThis.Buffer!==h&&globalThis.Buffer.isBuffer(e)||e instanceof Date||re(e)?false:!!(p(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&p(e)&&typeof e.data!==h?De(e.data,t+1):e}function ne(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a]=r;});else if(p(e))for(let[r,a]of Object.entries(e))t[r.toLowerCase()]=a;return t}function se(){return typeof window!==h&&typeof window.addEventListener===g}var Te=()=>{if(!se())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function w(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&p(t)&&p(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&p(t)&&p(n)&&Object.assign(t,n);}}}var oe=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;L(this,"status");L(this,"statusText");L(this,"config");L(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ie=class extends oe{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var le=600,ue=1e3,mt=le*ue,k=Array(le).fill(0).map(()=>[]),q=new Map,z=0,E=null,je=([e,t])=>{q.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(Q);}catch(r){}},I=(e,t,r)=>{if(S(e),r>mt||r%ue!==0){q.set(e,[setTimeout(je.bind(null,[e,t]),r)]);return}let a=r/ue,n=(z+a)%le;k[n].push([e,t]),q.set(e,n),E||(E=setInterval(()=>{z=(z+1)%le,k[z].forEach(je),k[z]=[],!q.size&&E&&(clearInterval(E),E=null);},ue));},S=e=>{let t=q.get(e);t!==void 0&&(Array.isArray(t)?clearTimeout(t[0]):k[t].splice(k[t].findIndex(([r])=>r===e),1),q.delete(e),!q.size&&E&&(clearInterval(E),E=null));};var A=new Map;function Ke(e,t,r,a,n,s){if(!e)return new AbortController;let o=A.get(e),u=null;if(o){let i=o[0],m=o[3];if(!m&&y()-o[2]{Je(e,new DOMException(t+" aborted due to timeout",Se));},r),l}async function Je(e,t=null){if(e){let r=A.get(e);r&&(t&&r[0].abort(t),ce(e));}}function ce(e){S(e),A.delete(e);}function ze(e,t){let r=A.get(e);r&&(r[4]=t,A.set(e,r));}function be(e,t){if(!e)return null;let r=A.get(e);return r&&r[4]&&!r[3]&&y()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(Q);});}async function me(e,t=false){if(!e)return null;let r=W.get(e);if(r){r[1]=y();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function dt(e){Rt(e);let t=e==="focus"?5:6;W.forEach((r,a)=>{r[t]&&yt(a);});}function ke(e){if(!se()||fe.has(e))return;let t=Ge.bind(null,e,true);fe.set(e,t),window.addEventListener(e,t);}function Rt(e){if(!se())return;let t=fe.get(e);t&&(window.removeEventListener(e,t),fe.delete(e));}function We(e,t,r,a,n,s,o){W.set(e,[t,y(),pt,a,n,s,o]),s&&ke("focus"),o&&ke("online"),a&&I("s:"+e,me.bind(null,e,true),a*1e3);}function yt(e){W.delete(e),S("s:"+e);}var v=new Map;function Pt(e){return v.has(e)||v.set(e,new Set),v.get(e)}function ht(e,t){Pt(e).add(t);}function gt(e,t){let r=v.get(e);r&&(r.delete(t),r.size===0&&v.delete(e));}function _(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 Dt(e,t){return e?(ht(e,t),()=>{gt(e,t);}):Q}var Ee=(Te()?60:30)*1e3,U={strategy:te,timeout:Ee,headers:{Accept:j+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:Ee/30,maxDelay:Ee,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Tt(e){let t=J(e);return Object.assign(U,t),U}function Ve(){return {...U}}function Ce(e,t){if(!t)return Ye(e,Ve());let r=J(t),a=Y(U,r);return Ye(e,a)}function Ye(e,t){var i;let r=t.method;r=r?r.toUpperCase():O;let a;r!==O&&r!==ve&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==b&&ge(a)&&(a=JSON.stringify(a))),bt(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),l=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function bt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==h&&t instanceof Blob||typeof File!==h&&t instanceof File||typeof ReadableStream!==h&&t instanceof ReadableStream)return;let r;if(re(t))r=x+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=x+"octet-stream";else if(ge(t))r=j+";"+Ne;else return;e instanceof Headers?e.has(C)||e.set(C,r):p(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function Y(e,t){let r=Object.assign({},e,t);return $e("retry",r,e,t),$e("headers",r,e,t),xe("onRequest",r,e,t),xe("onResponse",r,e,t),xe("onError",r,e,t),r}function xe(e,t,r,a){let n=r[e],s=a[e];if(!n&&!s)return;if(!n){t[e]=s;return}if(!s){t[e]=n;return}let o=Array.isArray(n)?n:[n],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function $e(e,t,r,a){a[e]&&(t[e]={...r[e],...a[e]});}var de=new Map,B="|",we=64,Ze=new RegExp("[^\\w\\-_|]","g"),Et=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 $(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=O,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let m;s instanceof Headers?m=ne(s):m=s;let c=Object.keys(m),R=c.length;R>1&&c.sort();let P="";for(let f=0;f{i+=c+"="+m+"&";}),i.length>we&&(i=G(i));else if(typeof Blob!==h&&o instanceof Blob||typeof File!==h&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let m=p(o)?JSON.stringify(He(o)):String(o);i=m.length>we?G(m):m;}return (n+B+a+B+u+B+l+B+i).replace(Ze,"")}function Xe(e){return e.expiry?y()>e.expiry:false}function xt(e){return e.stale?y()>e.stale:false}function Re(e){return de.get(e)}function ye(e,t,r,a){if(r===0){pe(e);return}let n=y(),s=r?r*1e3:0;de.set(e,{data:t,time:n,stale:a&&a>0?n+a*1e3:a,expiry:r===-1?void 0:n+s}),s>0&&I("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=Re(e);if(!r||!Xe(r))return}de.delete(e);}async function qe(e,t,r){if(!e)return null;let a=Re(e);if(!a)return null;let n=p(t)?J(t):t,s={...a.data,data:n},o={...a,data:s};return de.set(e,o),_(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||U.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=Re(e);if(!n)return null;let s=Xe(n),o=xt(n);return s?(pe(e),null):!o||o&&!s?n.data:null}function Ie(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&ye(a,e,n,t.staleTime),_(a,e),ce(a);let o=t._prevKey;o&&ce(o);}}async function et(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(j)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(x+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(x+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===b){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 Ae=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=qe.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===K&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let l=ne(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(p(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function tt(e){let t=Date.parse(e)-y();return isNaN(t)?null:Math.max(0,Math.floor(t))}function Ct(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 u=tt(r);if(u!==null)return u}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?tt(s):null}async function rt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,H=f.onRetry;H&&(await w(H,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=$(f,false)));}c=await e(l>0,l);let R=c.error;if(!R){if(u&&l0&&await N(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await N(t);return o}async function nt(e,t,r){let a=await t(e),n=a.error;if(!n)return Ie(a,r),a;r.onError&&await w(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&qt(r,"FETCH ERROR",n),Ie(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===te)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function st(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===ee;}function qt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Be={isFetching:true};async function he(e,t=null){let r=Ce(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,R=u!==void 0||l!==void 0,P=!!(s||a||o||R||n||i||m),f=null;if(P&&(f=$(r)),f&&R){let T=Pe(f,u,r);if(T)return T}if(f&&o){let T=be(f,o);if(T)return T}let H=r.retry||{},{retries:ot=0,resetTimeout:it}=H,Fe=async(T=false,Qe=0)=>{Qe||(f&&!T&&(l?Pe(f,u,r)||(ye(f,Be,u,l),_(f,Be)):_(f,Be)),r.cacheKey=f);let Z=r.url,lt=Ke(f,Z,a,o||0,!!n,!!(a&&(!Qe||it))),D=r;D.signal=lt.signal;let X,d=null;try{r.onRequest&&await w(r.onRequest,D);let F=r.fetcher;if(d=F?await F(Z,D):await fetch(Z,D),p(d)&&(typeof Response===g&&d instanceof Response?d.data=await et(d):F&&("data"in d&&"body"in d||(d={data:d})),d.config=D,d.ok!==void 0&&!d.ok))throw new ie(`${D.method} to ${Z} failed! Status: ${d.status||null}`,D,d);X=Ae(d,D);let M=r.onResponse;M&&await w(M,X);}catch(F){let M=F;st(M,d,D),X=Ae(d,D,M);}return X},ut=ot>0?()=>rt(Fe,H):Fe,V=(T=false)=>nt(T,ut,r),Oe=c?at(V,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):V();return f&&(o&&ze(f,Oe),We(f,V,void 0,l,V,!!i,!!m)),Oe}function It(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(l)?(o==null?void 0:o.url)===l?Y(u,s):s:Y(Y(e,u),s);return he(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} -export{Je as abortRequest,I as addTimeout,Ce as buildConfig,It as createApiFetcher,pe as deleteCache,he as fetchf,he as fetchff,$ as generateCacheKey,Re as getCache,Pe as getCachedResponse,Ve as getDefaultConfig,be as getInFlightPromise,Te as isSlowConnection,qe as mutate,dt as removeRevalidators,me as revalidate,Ge as revalidateAll,ye as setCache,Tt as setDefaultConfig,Dt as subscribe};//# sourceMappingURL=index.mjs.map +var mt=Object.defineProperty;var pt=(e,t,r)=>t in e?mt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var L=(e,t,r)=>pt(e,typeof t!="symbol"?t+"":t,r);var C="application/",j=C+"json",ve="charset=utf-8",w="Content-Type",R="undefined",K="object",E="string",g="function",ee="AbortError",Ne="TimeoutError",S="GET",_e="HEAD",te="reject";var He=10;function re(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===K}function J(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(c)+"="+a(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function ae(e){return e.includes("://")}var P=()=>Date.now(),v=()=>{};function De(e){let t=typeof e;return e==null?false:t===E||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||re(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function Te(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?Te(e.data,t+1):e}function ne(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a]=r;});else if(d(e))for(let[r,a]of Object.entries(e))t[r.toLowerCase()]=a;return t}function se(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var be=()=>{if(!se())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;L(this,"status");L(this,"statusText");L(this,"config");L(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,z=1e3,dt=ce*z,Ee=Array(ce).fill(0).map(()=>[]),A=new Map,le=0,x=null,Ke=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(v);}catch(r){}},I=(e,t,r)=>{if(_(e),rdt||r%z!==0){A.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let a=r/z,n=(le+a)%ce;Ee[n].push([e,t]),A.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Ee[le];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ze(e,oe(t+" aborted due to timeout",Ne));},r),i}async function ze(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),B.delete(e);}function ke(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function xe(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&ht(a);});}function Ge(e){if(!se()||me.has(e))return;let t=We.bind(null,e,true);me.set(e,t),window.addEventListener(e,t);}function Pt(e){if(!se())return;let t=me.get(e);t&&(window.removeEventListener(e,t),me.delete(e));}function Ye(e,t,r,a,n,s,o){G.set(e,[t,P(),yt,a,n,s,o]),s&&Ge("focus"),o&&Ge("online"),a&&I("s:"+e,pe.bind(null,e,true),a*1e3);}function ht(e){G.delete(e),_("s:"+e);}var W=new Map;function gt(e){let t=W.get(e);return t||(t=new Set,W.set(e,t)),t}function Dt(e,t){gt(e).add(t);}function Tt(e,t){let r=W.get(e);r&&(r.delete(t),r.size===0&&W.delete(e));}function U(e,t){let r=W.get(e);if(r)if(r.size===1){let a=r.values().next().value;a(t);}else r.forEach(a=>a(t));}function bt(e,t){return e?(Dt(e,t),()=>{Tt(e,t);}):v}var Ce=(be()?60:30)*1e3,H={strategy:te,timeout:Ce,headers:{Accept:j+", 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 Et(e){let t=J(e);return Object.assign(H,t),H}function Ve(){return {...H}}function qe(e,t){if(!t)return $e(e,Ve());let r=J(t),a=Y(H,r);return $e(e,a)}function $e(e,t){var i;let r=t.method;r=r?r.toUpperCase():S;let a;r!==S&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==E&&De(a)&&(a=JSON.stringify(a))),xt(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=n,t.body=a,t}function xt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(re(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(De(t))r=j+";"+ve;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function Y(e,t){let r=Object.assign({},e,t);return Ze("retry",r,e,t),Ze("headers",r,e,t),we("onRequest",r,e,t),we("onResponse",r,e,t),we("onError",r,e,t),r}function we(e,t,r,a){let n=r[e],s=a[e];if(!n&&!s)return;if(!n){t[e]=s;return}if(!s){t[e]=n;return}let o=Array.isArray(n)?n:[n],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Ze(e,t,r,a){a[e]&&(t[e]={...r[e],...a[e]});}var ye=new Map,F="|",Ae=64,Xe=/[^\w\-_|/:@.?=&~%#]/g,et=/[^\w\-_|/:@.?=&~%#]/,Ct=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 $(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===E?r:r(e);let{url:a="",method:n=S,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=ne(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>Ae&&(i=k(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Me(o)):String(o);i=l.length>Ae?k(l):l;}let m=n+F+a+F+u+F+c+F+i;return et.test(m)?m.replace(Xe,""):m}function tt(e){return e.expiry?P()>e.expiry:false}function wt(e){return e.stale?P()>e.stale:false}function Re(e){return ye.get(e)}function Pe(e,t,r,a){if(r===0){de(e);return}let n=P(),s=r?r*1e3:0,o=a?a*1e3:0;ye.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&I("c:"+e,()=>{de(e,true);},s);}function de(e,t=false){if(t){let r=Re(e);if(!r||!tt(r))return}ye.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=Re(e);if(!a)return null;let n=d(t)?J(t):t,s={...a.data,data:n},o={...a,data:s};return ye.set(e,o),U(e,s),r&&r.refetch?await pe(e):null}function he(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||H.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=Re(e);if(!n)return null;let s=tt(n),o=wt(n);return s?(de(e),null):!o||o&&!s?n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Pe(a,e,n,t.staleTime),U(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function rt(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(j)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===E){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===K&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=Te(u)),t.select&&(e.data=u=t.select(u));let c=ne(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function at(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function qt(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 u=at(r);if(u!==null)return u}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?at(s):null}async function nt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=a,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=$(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await N(t);return o}async function ot(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await q(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&It(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===te)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function it(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===ee;}function It(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe={isFetching:true};async function ge(e,t=null){let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||a||o||p||n||i||m),f=null;if(h&&(f=$(r)),f&&p){let T=he(f,u,r);if(T)return T}if(f&&o){let T=xe(f,o);if(T)return T}let D=r.retry||{},{retries:ut=0,resetTimeout:lt}=D,Qe=async(T=false,V=0)=>{V||(f&&!T&&(c?he(f,u,r)||(Pe(f,Oe,u,c),U(f,Oe)):U(f,Oe)),r.cacheKey=f);let O=r.url,ft=Je(f,O,a,o||0,!!n,!!(a&&(!V||lt))),b=r;b.signal=ft.signal;let X,y=null;try{r.onRequest&&(f&&o&&!V&&await null,await q(r.onRequest,b));let Q=r.fetcher;if(y=Q?await Q(O,b):await fetch(O,b),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await rt(y):Q&&("data"in y&&"body"in y||(y={data:y})),y.config=b,y.ok!==void 0&&!y.ok))throw new ue(`${b.method} to ${O} failed! Status: ${y.status||null}`,b,y);X=Fe(y,b);let M=r.onResponse;M&&await q(M,X);}catch(Q){let M=Q;it(M,y,b),X=Fe(y,b,M);}return X},ct=ut>0?(T=false)=>nt((V,O)=>Qe(T,O),D):Qe,Z=(T=false)=>ot(T,ct,r),Se=l?st(Z,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):Z();return f&&(o&&ke(f,Se),Ye(f,Z,void 0,c,Z,!!i,!!m)),Se}function Bt(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=t[n],u=o||{url:String(n)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?(o==null?void 0:o.url)===c?Y(u,s):s:Y(Y(e,u),s);return ge(c,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} +export{ze as abortRequest,I as addTimeout,qe as buildConfig,oe as createAbortError,Bt as createApiFetcher,de as deleteCache,ge as fetchf,ge as fetchff,$ as generateCacheKey,Re as getCache,he as getCachedResponse,Ve as getDefaultConfig,xe as getInFlightPromise,be as isSlowConnection,Ie as mutate,Rt as removeRevalidators,pe as revalidate,We as revalidateAll,Pe as setCache,Et as setDefaultConfig,bt 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 c3d4ba97..069cf1c9 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","message","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","error","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","revalidateAll","type","isStaleRevalidation","flagIndex","now","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","addListener","fn","removeListener","set","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function creates a shallow copy of the input object with dangerous\n * properties like '__proto__', 'constructor', and 'prototype' removed.\n *\n * @param obj - The object to sanitize\n * @returns A new object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const safeObj = { ...obj };\n\n delete safeObj.__proto__;\n delete (safeObj as any).constructor;\n delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 * 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded or ms is not divisible by SECOND\n if (ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n wheel[position].forEach(handleCallback);\n wheel[position] = [];\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 wheel[slotOrTimeout].splice(\n wheel[slotOrTimeout].findIndex(([k]) => k === key),\n 1,\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 wheel.forEach((slot) => (slot.length = 0));\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 { 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 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 timeNow() - 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 new DOMException('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 timeNow(),\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n new DOMException(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 | 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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n if (!listeners.has(key)) {\n listeners.set(key, new Set());\n }\n\n return listeners.get(key)!;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 = new RegExp('[^\\\\w\\\\-_|]', 'g');\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 return (\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString\n ).replace(CACHE_KEY_SANITIZE_PATTERN, '');\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 return (\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString +\n DELIMITER +\n bodyString\n ).replace(CACHE_KEY_SANITIZE_PATTERN, ''); // Prevent cache poisoning by removal of anything that isn't letters, numbers, -, _, or |\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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\n _cache.set(key, {\n data,\n time,\n stale: staleTime && staleTime > 0 ? time + staleTime * 1000 : staleTime,\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 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 = 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} to ${url} failed! Status: ${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 const baseRequest =\n retries > 0 ? () => withRetry(doRequestOnce, retryConfig) : 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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","revalidateAll","type","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/node/index.js b/dist/node/index.js index 3da4d12f..de261e22 100644 --- a/dist/node/index.js +++ b/dist/node/index.js @@ -1,3 +1,3 @@ -'use strict';var x="application/",L=x+"json",Qe="charset=utf-8",C="Content-Type",h="undefined",j="object",b="string",g="function",X="AbortError",Ne="TimeoutError",O="GET",Se="HEAD",ee="reject";var _e=10;function te(e){return e instanceof URLSearchParams}function p(e){return e!==null&&typeof e===j}function K(e){let t={...e};return delete t.__proto__,delete t.constructor,delete t.prototype,t}function Ue(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=_e)return r;let c,R,P;if(l)if(Array.isArray(i))for(c=0,R=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function re(e){return e.includes("://")}var y=()=>Date.now(),Q=()=>{};function he(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==h&&typeof globalThis.Buffer!==h&&globalThis.Buffer.isBuffer(e)||e instanceof Date||te(e)?false:!!(p(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function ge(e,t=0){return t>=_e?e:e&&p(e)&&typeof e.data!==h?ge(e.data,t+1):e}function ae(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a]=r;});else if(p(e))for(let[r,a]of Object.entries(e))t[r.toLowerCase()]=a;return t}function ne(){return typeof window!==h&&typeof window.addEventListener===g}var De=()=>{if(!ne())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function w(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&p(t)&&p(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&p(t)&&p(n)&&Object.assign(t,n);}}}var se=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}status;statusText;config;isCancelled};var oe=class extends se{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ue=600,ie=1e3,lt=ue*ie,z=Array(ue).fill(0).map(()=>[]),q=new Map,J=0,E=null,Le=([e,t])=>{q.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(Q);}catch{}},I=(e,t,r)=>{if(S(e),r>lt||r%ie!==0){q.set(e,[setTimeout(Le.bind(null,[e,t]),r)]);return}let a=r/ie,n=(J+a)%ue;z[n].push([e,t]),q.set(e,n),E||(E=setInterval(()=>{J=(J+1)%ue,z[J].forEach(Le),z[J]=[],!q.size&&E&&(clearInterval(E),E=null);},ie));},S=e=>{let t=q.get(e);t!==void 0&&(Array.isArray(t)?clearTimeout(t[0]):z[t].splice(z[t].findIndex(([r])=>r===e),1),q.delete(e),!q.size&&E&&(clearInterval(E),E=null));};var A=new Map;function je(e,t,r,a,n,s){if(!e)return new AbortController;let o=A.get(e),u=null;if(o){let i=o[0],m=o[3];if(!m&&y()-o[2]{Ke(e,new DOMException(t+" aborted due to timeout",Ne));},r),l}async function Ke(e,t=null){if(e){let r=A.get(e);r&&(t&&r[0].abort(t),le(e));}}function le(e){S(e),A.delete(e);}function Je(e,t){let r=A.get(e);r&&(r[4]=t,A.set(e,r));}function Te(e,t){if(!e)return null;let r=A.get(e);return r&&r[4]&&!r[3]&&y()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(Q);});}async function fe(e,t=false){if(!e)return null;let r=G.get(e);if(r){r[1]=y();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function ft(e){mt(e);let t=e==="focus"?5:6;G.forEach((r,a)=>{r[t]&&pt(a);});}function ze(e){if(!ne()||ce.has(e))return;let t=ke.bind(null,e,true);ce.set(e,t),window.addEventListener(e,t);}function mt(e){if(!ne())return;let t=ce.get(e);t&&(window.removeEventListener(e,t),ce.delete(e));}function Ge(e,t,r,a,n,s,o){G.set(e,[t,y(),ct,a,n,s,o]),s&&ze("focus"),o&&ze("online"),a&&I("s:"+e,fe.bind(null,e,true),a*1e3);}function pt(e){G.delete(e),S("s:"+e);}var v=new Map;function dt(e){return v.has(e)||v.set(e,new Set),v.get(e)}function Rt(e,t){dt(e).add(t);}function yt(e,t){let r=v.get(e);r&&(r.delete(t),r.size===0&&v.delete(e));}function _(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 Pt(e,t){return e?(Rt(e,t),()=>{yt(e,t);}):Q}var be=(De()?60:30)*1e3,U={strategy:ee,timeout:be,headers:{Accept:L+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:be/30,maxDelay:be,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function ht(e){let t=K(e);return Object.assign(U,t),U}function $e(){return {...U}}function xe(e,t){if(!t)return We(e,$e());let r=K(t),a=W(U,r);return We(e,a)}function We(e,t){let r=t.method;r=r?r.toUpperCase():O;let a;r!==O&&r!==Se&&(a=t.body??t.data,a&&typeof a!==b&&he(a)&&(a=JSON.stringify(a))),gt(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=Me(e,t.urlPathParams),o=He(s,t.params),l=re(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function gt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==h&&t instanceof Blob||typeof File!==h&&t instanceof File||typeof ReadableStream!==h&&t instanceof ReadableStream)return;let r;if(te(t))r=x+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=x+"octet-stream";else if(he(t))r=L+";"+Qe;else return;e instanceof Headers?e.has(C)||e.set(C,r):p(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function W(e,t){let r=Object.assign({},e,t);return Ye("retry",r,e,t),Ye("headers",r,e,t),Ee("onRequest",r,e,t),Ee("onResponse",r,e,t),Ee("onError",r,e,t),r}function Ee(e,t,r,a){let n=r[e],s=a[e];if(!n&&!s)return;if(!n){t[e]=s;return}if(!s){t[e]=n;return}let o=Array.isArray(n)?n:[n],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Ye(e,t,r,a){a[e]&&(t[e]={...r[e],...a[e]});}var pe=new Map,B="|",Ce=64,Ve=new RegExp("[^\\w\\-_|]","g"),Dt=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 Y(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=O,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let m;s instanceof Headers?m=ae(s):m=s;let c=Object.keys(m),R=c.length;R>1&&c.sort();let P="";for(let f=0;f{i+=c+"="+m+"&";}),i.length>Ce&&(i=k(i));else if(typeof Blob!==h&&o instanceof Blob||typeof File!==h&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let m=p(o)?JSON.stringify(Ue(o)):String(o);i=m.length>Ce?k(m):m;}return (n+B+a+B+u+B+l+B+i).replace(Ve,"")}function Ze(e){return e.expiry?y()>e.expiry:false}function Tt(e){return e.stale?y()>e.stale:false}function de(e){return pe.get(e)}function Re(e,t,r,a){if(r===0){me(e);return}let n=y(),s=r?r*1e3:0;pe.set(e,{data:t,time:n,stale:a&&a>0?n+a*1e3:a,expiry:r===-1?void 0:n+s}),s>0&&I("c:"+e,()=>{me(e,true);},s);}function me(e,t=false){if(t){let r=de(e);if(!r||!Ze(r))return}pe.delete(e);}async function we(e,t,r){if(!e)return null;let a=de(e);if(!a)return null;let n=p(t)?K(t):t,s={...a.data,data:n},o={...a,data:s};return pe.set(e,o),_(e,s),r&&r.refetch?await fe(e):null}function ye(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||U.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=de(e);if(!n)return null;let s=Ze(n),o=Tt(n);return s?(me(e),null):!o||o&&!s?n.data:null}function qe(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(a,e,n,t.staleTime),_(a,e),le(a);let o=t._prevKey;o&&le(o);}}async function Xe(e){if(!e)return null;let t=e.headers?.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(L)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(x+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(x+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===b){let n=a.trim();if(n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]"))try{a=JSON.parse(n);}catch{}}}catch{a=null;}return a}var Ie=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=we.bind(null,n);if(!e)return {ok:false,error:r,data:a??null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===j&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=ge(u)),t.select&&(e.data=u=t.select(u));let l=ae(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(p(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function et(e){let t=Date.parse(e)-y();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 u=et(r);if(u!==null)return u}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?et(s):null}async function tt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,H=f.onRetry;H&&(await w(H,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Y(f,false)));}c=await e(l>0,l);let R=c.error;if(!R){if(u&&l0&&await N(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await N(t);return o}async function at(e,t,r){let a=await t(e),n=a.error;if(!n)return qe(a,r),a;r.onError&&await w(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&xt(r,"FETCH ERROR",n),qe(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ee)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function nt(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===X;}function xt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Ae={isFetching:true};async function Pe(e,t=null){let r=xe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,R=u!==void 0||l!==void 0,P=!!(s||a||o||R||n||i||m),f=null;if(P&&(f=Y(r)),f&&R){let T=ye(f,u,r);if(T)return T}if(f&&o){let T=Te(f,o);if(T)return T}let H=r.retry||{},{retries:st=0,resetTimeout:ot}=H,Be=async(T=false,Oe=0)=>{Oe||(f&&!T&&(l?ye(f,u,r)||(Re(f,Ae,u,l),_(f,Ae)):_(f,Ae)),r.cacheKey=f);let V=r.url,ut=je(f,V,a,o||0,!!n,!!(a&&(!Oe||ot))),D=r;D.signal=ut.signal;let Z,d=null;try{r.onRequest&&await w(r.onRequest,D);let F=r.fetcher;if(d=F?await F(V,D):await fetch(V,D),p(d)&&(typeof Response===g&&d instanceof Response?d.data=await Xe(d):F&&("data"in d&&"body"in d||(d={data:d})),d.config=D,d.ok!==void 0&&!d.ok))throw new oe(`${D.method} to ${V} failed! Status: ${d.status||null}`,D,d);Z=Ie(d,D);let M=r.onResponse;M&&await w(M,Z);}catch(F){let M=F;nt(M,d,D),Z=Ie(d,D,M);}return Z},it=st>0?()=>tt(Be,H):Be,$=(T=false)=>at(T,it,r),Fe=c?rt($,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):$();return f&&(o&&Je(f,Fe),Ge(f,$,void 0,l,$,!!i,!!m)),Fe}function Ct(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=re(l)?o?.url===l?W(u,s):s:W(W(e,u),s);return Pe(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=Ke;exports.addTimeout=I;exports.buildConfig=xe;exports.createApiFetcher=Ct;exports.deleteCache=me;exports.fetchf=Pe;exports.fetchff=Pe;exports.generateCacheKey=Y;exports.getCache=de;exports.getCachedResponse=ye;exports.getDefaultConfig=$e;exports.getInFlightPromise=Te;exports.isSlowConnection=De;exports.mutate=we;exports.removeRevalidators=ft;exports.revalidate=fe;exports.revalidateAll=ke;exports.setCache=Re;exports.setDefaultConfig=ht;exports.subscribe=Pt;//# sourceMappingURL=index.js.map +'use strict';var C="application/",L=C+"json",Se="charset=utf-8",w="Content-Type",R="undefined",j="object",E="string",g="function",X="AbortError",ve="TimeoutError",S="GET",Ne="HEAD",ee="reject";var Ue=10;function te(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===j}function K(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function He(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=Ue)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function re(e){return e.includes("://")}var P=()=>Date.now(),v=()=>{};function ge(e){let t=typeof e;return e==null?false:t===E||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||te(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function ne(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n]=r;});else if(d(e))for(let[r,n]of Object.entries(e))t[r.toLowerCase()]=n;return t}function ae(){return typeof window!==R&&typeof window.addEventListener===g}function se(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Te=()=>{if(!ae())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var oe=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}status;statusText;config;isCancelled};var ie=class extends oe{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var le=600,J=1e3,ft=le*J,be=Array(le).fill(0).map(()=>[]),A=new Map,ue=0,x=null,je=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(v);}catch{}},I=(e,t,r)=>{if(_(e),rft||r%J!==0){A.set(e,[setTimeout(je.bind(null,[e,t]),r)]);return}let n=r/J,a=(ue+n)%le;be[a].push([e,t]),A.set(e,a),x||(x=setInterval(()=>{ue=(ue+1)%le;let s=be[ue];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=be[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function Ke(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{Je(e,se(t+" aborted due to timeout",ve));},r),i}async function Je(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),ce(e));}}function ce(e){_(e),B.delete(e);}function ze(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function Ee(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&yt(n);});}function ke(e){if(!ae()||fe.has(e))return;let t=Ge.bind(null,e,true);fe.set(e,t),window.addEventListener(e,t);}function dt(e){if(!ae())return;let t=fe.get(e);t&&(window.removeEventListener(e,t),fe.delete(e));}function We(e,t,r,n,a,s,o){k.set(e,[t,P(),mt,n,a,s,o]),s&&ke("focus"),o&&ke("online"),n&&I("s:"+e,me.bind(null,e,true),n*1e3);}function yt(e){k.delete(e),_("s:"+e);}var G=new Map;function Rt(e){let t=G.get(e);return t||(t=new Set,G.set(e,t)),t}function Pt(e,t){Rt(e).add(t);}function ht(e,t){let r=G.get(e);r&&(r.delete(t),r.size===0&&G.delete(e));}function U(e,t){let r=G.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function gt(e,t){return e?(Pt(e,t),()=>{ht(e,t);}):v}var xe=(Te()?60:30)*1e3,H={strategy:ee,timeout:xe,headers:{Accept:L+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:xe/30,maxDelay:xe,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Dt(e){let t=K(e);return Object.assign(H,t),H}function Ze(){return {...H}}function we(e,t){if(!t)return Ye(e,Ze());let r=K(t),n=W(H,r);return Ye(e,n)}function Ye(e,t){let r=t.method;r=r?r.toUpperCase():S;let n;r!==S&&r!==Ne&&(n=t.body??t.data,n&&typeof n!==E&&ge(n)&&(n=JSON.stringify(n))),Tt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),c=re(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function Tt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(te(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(ge(t))r=L+";"+Se;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function W(e,t){let r=Object.assign({},e,t);return $e("retry",r,e,t),$e("headers",r,e,t),Ce("onRequest",r,e,t),Ce("onResponse",r,e,t),Ce("onError",r,e,t),r}function Ce(e,t,r,n){let a=r[e],s=n[e];if(!a&&!s)return;if(!a){t[e]=s;return}if(!s){t[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function $e(e,t,r,n){n[e]&&(t[e]={...r[e],...n[e]});}var de=new Map,F="|",qe=64,Ve=/[^\w\-_|/:@.?=&~%#]/g,Xe=/[^\w\-_|/:@.?=&~%#]/,bt=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 Y(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===E?r:r(e);let{url:n="",method:a=S,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=ne(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>qe&&(i=z(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(He(o)):String(o);i=l.length>qe?z(l):l;}let m=a+F+n+F+u+F+c+F+i;return Xe.test(m)?m.replace(Ve,""):m}function et(e){return e.expiry?P()>e.expiry:false}function Et(e){return e.stale?P()>e.stale:false}function ye(e){return de.get(e)}function Re(e,t,r,n){if(r===0){pe(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;de.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&I("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!et(r))return}de.delete(e);}async function Ae(e,t,r){if(!e)return null;let n=ye(e);if(!n)return null;let a=d(t)?K(t):t,s={...n.data,data:a},o={...n,data:s};return de.set(e,o),U(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||H.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=ye(e);if(!a)return null;let s=et(a),o=Et(a);return s?(pe(e),null):!o||o&&!s?a.data:null}function Ie(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(n,e,a,t.staleTime),U(n,e),ce(n);let o=t._prevKey;o&&ce(o);}}async function tt(e){if(!e)return null;let t=e.headers?.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(L)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===E){let a=n.trim();if(a.startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]"))try{n=JSON.parse(a);}catch{}}}catch{n=null;}return n}var Be=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ae.bind(null,a);if(!e)return {ok:false,error:r,data:n??null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===j&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let c=ne(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function rt(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function xt(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 u=rt(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?rt(s):null}async function nt(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Y(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await N(t);return o}async function st(e,t,r){let n=await t(e),a=n.error;if(!a)return Ie(n,r),n;r.onError&&await q(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&wt(r,"FETCH ERROR",a),Ie(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ee)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function ot(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===X;}function wt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Fe={isFetching:true};async function he(e,t=null){let r=we(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=Y(r)),f&&p){let T=Pe(f,u,r);if(T)return T}if(f&&o){let T=Ee(f,o);if(T)return T}let D=r.retry||{},{retries:it=0,resetTimeout:ut}=D,Oe=async(T=false,Z=0)=>{Z||(f&&!T&&(c?Pe(f,u,r)||(Re(f,Fe,u,c),U(f,Fe)):U(f,Fe)),r.cacheKey=f);let O=r.url,ct=Ke(f,O,n,o||0,!!a,!!(n&&(!Z||ut))),b=r;b.signal=ct.signal;let V,y=null;try{r.onRequest&&(f&&o&&!Z&&await null,await q(r.onRequest,b));let Q=r.fetcher;if(y=Q?await Q(O,b):await fetch(O,b),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await tt(y):Q&&("data"in y&&"body"in y||(y={data:y})),y.config=b,y.ok!==void 0&&!y.ok))throw new ie(`${b.method} to ${O} failed! Status: ${y.status||null}`,b,y);V=Be(y,b);let M=r.onResponse;M&&await q(M,V);}catch(Q){let M=Q;ot(M,y,b),V=Be(y,b,M);}return V},lt=it>0?(T=false)=>nt((Z,O)=>Oe(T,O),D):Oe,$=(T=false)=>st(T,lt,r),Qe=l?at($,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):$();return f&&(o&&ze(f,Qe),We(f,$,void 0,c,$,!!i,!!m)),Qe}function qt(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=re(c)?o?.url===c?W(u,s):s:W(W(e,u),s);return he(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} +exports.abortRequest=Je;exports.addTimeout=I;exports.buildConfig=we;exports.createAbortError=se;exports.createApiFetcher=qt;exports.deleteCache=pe;exports.fetchf=he;exports.fetchff=he;exports.generateCacheKey=Y;exports.getCache=ye;exports.getCachedResponse=Pe;exports.getDefaultConfig=Ze;exports.getInFlightPromise=Ee;exports.isSlowConnection=Te;exports.mutate=Ae;exports.removeRevalidators=pt;exports.revalidate=me;exports.revalidateAll=Ge;exports.setCache=Re;exports.setDefaultConfig=Dt;exports.subscribe=gt;//# 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 48153c1d..dfc2ed66 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","message","request","response","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","inFlight","markInFlight","timeout","dedupeTime","isCancellable","isTimeoutEnabled","item","prevPromise","prevController","prevIsCancellable","controller","abortRequest","error","removeInFlight","setInFlightPromise","promise","getInFlightPromise","prevReq","hash","str","char","DEFAULT_TTL","revalidators","eventHandlers","revalidateAll","type","isStaleRevalidation","flagIndex","now","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","addListener","fn","removeListener","set","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","_error","baseRequest","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * Removes properties that could lead to prototype pollution from an object.\n *\n * This function creates a shallow copy of the input object with dangerous\n * properties like '__proto__', 'constructor', and 'prototype' removed.\n *\n * @param obj - The object to sanitize\n * @returns A new object without dangerous properties\n */\nexport function sanitizeObject>(obj: T): T {\n const safeObj = { ...obj };\n\n delete safeObj.__proto__;\n delete (safeObj as any).constructor;\n delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 * 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded or ms is not divisible by SECOND\n if (ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\n wheel[position].forEach(handleCallback);\n wheel[position] = [];\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 wheel[slotOrTimeout].splice(\n wheel[slotOrTimeout].findIndex(([k]) => k === key),\n 1,\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 wheel.forEach((slot) => (slot.length = 0));\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 { 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 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 timeNow() - 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 new DOMException('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 timeNow(),\n isCancellable,\n prevPromise,\n ]);\n\n if (isTimeoutEnabled) {\n addTimeout(\n key,\n () => {\n abortRequest(\n key,\n new DOMException(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 | 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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n if (!listeners.has(key)) {\n listeners.set(key, new Set());\n }\n\n return listeners.get(key)!;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 = new RegExp('[^\\\\w\\\\-_|]', 'g');\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 return (\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString\n ).replace(CACHE_KEY_SANITIZE_PATTERN, '');\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 return (\n method +\n DELIMITER +\n url +\n DELIMITER +\n credentials +\n DELIMITER +\n headersString +\n DELIMITER +\n bodyString\n ).replace(CACHE_KEY_SANITIZE_PATTERN, ''); // Prevent cache poisoning by removal of anything that isn't letters, numbers, -, _, or |\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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\n _cache.set(key, {\n data,\n time,\n stale: staleTime && staleTime > 0 ? time + staleTime * 1000 : staleTime,\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 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 = 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} to ${url} failed! Status: ${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 const baseRequest =\n retries > 0 ? () => withRetry(doRequestOnce, retryConfig) : 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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","revalidateAll","type","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","_error","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/react/index.js b/dist/react/index.js index d2f10ebb..cb755278 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,D=2e3,m=new Map,q=e=>{e&&m.set(e,(m.get(e)||0)+1);},A=(e,t,s,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,new DOMException("Request to "+o+" aborted","AbortError")),f(e)||fetchff.deleteCache(e,true);},s!=null?s:D)):m.set(e,i);},f=e=>e&&m.get(e)||0;var Y=300,x=Object.freeze({data:null,error:null,isFetching:false,mutate:()=>Promise.resolve(null),config:{},headers:{}}),K=Object.freeze({...x,isFetching:true}),Z=[null,{},null],$=new Set(["GET","HEAD","get","head"]);function ae(e,t={}){var b,U,_;let s=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:D,a=t.cacheTime||F,i=(U=t.staleTime)!=null?U:Y,R=(_=t.immediate)!=null?_:$.has(t.method||"GET"),P=react.useRef(Z);P.current=[e,t,s];let g=react.useCallback(()=>{let r=fetchff.getCache(s);if(t.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&&!t.keepPreviousData?K:r.data:R?K:x},[s]),B=react.useCallback(r=>{q(s),R&&e&&s&&f(s)===1&&(fetchff.getCachedResponse(s,a,t)||C(false));let u=fetchff.subscribe(s,r);return ()=>{A(s,a,o,e),u();}},[s,R,e,o,a]),n=react.useSyncExternalStore(B,g,g),C=react.useCallback(async(r=true,h={})=>{let[u,c,l]=P.current;if(!u)return Promise.resolve(null);let E=!!r;if(!E&&l){let S=fetchff.getCachedResponse(l,a,c);if(S)return Promise.resolve(S)}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),L=d&&p,w=d&&!p;return {data:T,error:n.error,config:n.config,headers:n.headers,isFirstFetch:L,isFetching:d,isLoading:d,isRefetching:w,isError:n.isError,isSuccess:n.isSuccess,mutate:n.mutate,refetch:C}}exports.useFetcher=ae;//# sourceMappingURL=index.js.map +'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 //# 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 35e5dcf4..511bf205 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","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 { addTimeout, abortRequest, deleteCache } 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 new DOMException('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","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 diff --git a/dist/react/index.mjs b/dist/react/index.mjs index 450fd2e3..f83dd041 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,deleteCache}from'fetchff';var F=-1,D=2e3,m=new Map,q=e=>{e&&m.set(e,(m.get(e)||0)+1);},A=(e,t,s,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,new DOMException("Request to "+o+" aborted","AbortError")),f(e)||deleteCache(e,true);},s!=null?s:D)):m.set(e,i);},f=e=>e&&m.get(e)||0;var Y=300,x=Object.freeze({data:null,error:null,isFetching:false,mutate:()=>Promise.resolve(null),config:{},headers:{}}),K=Object.freeze({...x,isFetching:true}),Z=[null,{},null],$=new Set(["GET","HEAD","get","head"]);function ae(e,t={}){var b,U,_;let s=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:D,a=t.cacheTime||F,i=(U=t.staleTime)!=null?U:Y,R=(_=t.immediate)!=null?_:$.has(t.method||"GET"),P=useRef(Z);P.current=[e,t,s];let g=useCallback(()=>{let r=getCache(s);if(t.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&&!t.keepPreviousData?K:r.data:R?K:x},[s]),B=useCallback(r=>{q(s),R&&e&&s&&f(s)===1&&(getCachedResponse(s,a,t)||C(false));let u=subscribe(s,r);return ()=>{A(s,a,o,e),u();}},[s,R,e,o,a]),n=useSyncExternalStore(B,g,g),C=useCallback(async(r=true,h={})=>{let[u,c,l]=P.current;if(!u)return Promise.resolve(null);let E=!!r;if(!E&&l){let S=getCachedResponse(l,a,c);if(S)return Promise.resolve(S)}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),L=d&&p,w=d&&!p;return {data:T,error:n.error,config:n.config,headers:n.headers,isFirstFetch:L,isFetching:d,isLoading:d,isRefetching:w,isError:n.isError,isSuccess:n.isSuccess,mutate:n.mutate,refetch:C}}export{ae 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,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 //# 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 624fec04..e7f0930c 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","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 { addTimeout, abortRequest, deleteCache } 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 new DOMException('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","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":"2OAqBO,IAAMA,CAAAA,CAAsB,EAAA,CACtBC,CAAAA,CAAyB,GAAA,CAEhCC,EAAO,IAAI,GAAA,CAEJC,CAAAA,CAAgBC,CAAAA,EAAuB,CAC9CA,CAAAA,EACFF,CAAAA,CAAK,GAAA,CAAIE,GAAMF,CAAAA,CAAK,GAAA,CAAIE,CAAG,CAAA,EAAK,CAAA,EAAK,CAAC,EAE1C,CAAA,CAEaC,EAAe,CAC1BD,CAAAA,CACAE,CAAAA,CACAC,CAAAA,CACAC,CAAAA,GACG,CACH,GAAI,CAACJ,EACH,OAGF,IAAMK,CAAAA,CAAUC,CAAAA,CAAYN,CAAG,CAAA,CAE/B,GAAI,CAACK,EACH,OAGF,IAAME,CAAAA,CAAWF,CAAAA,CAAU,CAAA,CAKvBE,CAAAA,EAAY,CAAA,EACdT,CAAAA,CAAK,OAAOE,CAAG,CAAA,CAEEE,CAAAA,GAAcN,CAAAA,EAE7BY,UAAAA,CACE,IAAA,CAAOR,CAAAA,CACP,IAAM,CAEJS,YAAAA,CACET,CAAAA,CACAU,gBAAAA,CAAiB,aAAA,CAAgBN,CAAAA,CAAM,UAAA,CAAY,YAAY,CACjE,CAAA,CAMKE,CAAAA,CAAYN,CAAG,CAAA,EAClBW,WAAAA,CAAYX,CAAAA,CAAK,IAAI,EAEzB,EACAG,CAAAA,EAAA,IAAA,CAAAA,CAAAA,CAAcN,CAChB,CAAA,EAGFC,CAAAA,CAAK,GAAA,CAAIE,CAAAA,CAAKO,CAAQ,EAE1B,CAAA,CAEaD,CAAAA,CAAeN,CAAAA,EACrBA,CAAAA,EAIEF,CAAAA,CAAK,GAAA,CAAIE,CAAG,GAAK,CAAA,CC3D1B,IAAMY,CAAAA,CAAqB,GAAA,CAGrBC,CAAAA,CAAiB,MAAA,CAAO,MAAA,CAAO,CACnC,KAAM,IAAA,CACN,KAAA,CAAO,IAAA,CACP,UAAA,CAAY,KAAA,CACZ,MAAA,CAAQ,IAAM,OAAA,CAAQ,QAAQ,IAAI,CAAA,CAClC,MAAA,CAAQ,EAAC,CACT,OAAA,CAAS,EACX,CAAC,CAAA,CAEKC,CAAAA,CAAkB,MAAA,CAAO,MAAA,CAAO,CACpC,GAAGD,CAAAA,CACH,UAAA,CAAY,IACd,CAAC,CAAA,CAEKE,CAAAA,CAAc,CAAC,IAAA,CAAM,EAAC,CAAG,IAAI,EAO7BC,CAAAA,CAAe,IAAI,GAAA,CAAI,CAAC,KAAA,CAAO,MAAA,CAAQ,KAAA,CAAO,MAAM,CAAC,CAAA,CAqCpD,SAASC,EAAAA,CAMdb,CAAAA,CACAc,CAAAA,CAKI,EAAC,CACiE,CAvGxE,IAAAC,CAAAA,CAAAC,CAAAA,CAAAC,CAAAA,CA0GE,IAAMC,CAAAA,CAAWC,OAAAA,CACf,IAAOnB,CAAAA,GAAQ,KAAO,IAAA,CAAOoB,gBAAAA,CAAiBC,WAAAA,CAAYrB,CAAAA,CAAKc,CAAM,CAAC,CAAA,CACtE,CACEA,EAAO,QAAA,CACPd,CAAAA,CACAc,CAAAA,CAAO,GAAA,CACPA,CAAAA,CAAO,MAAA,CACPA,CAAAA,CAAO,OAAA,CACPA,EAAO,IAAA,CACPA,CAAAA,CAAO,MAAA,CACPA,CAAAA,CAAO,aAAA,CACPA,CAAAA,CAAO,MAAA,CACPA,CAAAA,CAAO,QACPA,CAAAA,CAAO,eAAA,CACPA,CAAAA,CAAO,WACT,CACF,CAAA,CACMf,CAAAA,CAAAA,CAAagB,CAAAA,CAAAD,EAAO,UAAA,GAAP,IAAA,CAAAC,CAAAA,CAAqBtB,CAAAA,CAClCK,CAAAA,CAAYgB,CAAAA,CAAO,SAAA,EAAatB,CAAAA,CAChC8B,GAAYN,CAAAA,CAAAF,CAAAA,CAAO,SAAA,GAAP,IAAA,CAAAE,CAAAA,CAAoBR,CAAAA,CAGhCe,CAAAA,CAAAA,CACJN,CAAAA,CAAAH,EAAO,SAAA,GAAP,IAAA,CAAAG,CAAAA,CAAoBL,CAAAA,CAAa,GAAA,CAAIE,CAAAA,CAAO,MAAA,EAAU,KAAK,EAEvDU,CAAAA,CAAmBC,MAAAA,CAAOd,CAAW,CAAA,CAC3Ca,CAAAA,CAAiB,OAAA,CAAU,CAACxB,CAAAA,CAAKc,EAAQI,CAAQ,CAAA,CAGjD,IAAMQ,CAAAA,CAAcC,YAAY,IAAM,CACpC,IAAMC,CAAAA,CAASC,SACbX,CACF,CAAA,CAGA,GACEJ,CAAAA,CAAO,QAAA,GAAa,QAAA,EACpBI,CAAAA,GACC,CAACU,GAAW,CAACA,CAAAA,CAAO,IAAA,CAAK,IAAA,EAAQ,CAACA,CAAAA,CAAO,IAAA,CAAK,KAAA,CAAA,CAC/C,CACA,IAAME,CAAAA,CAAiBC,kBAAAA,CAAmBb,CAAAA,CAAUnB,CAAU,CAAA,CAE9D,GAAI+B,CAAAA,CACF,MAAMA,CAAAA,CAIR,GAAI,CAACF,CAAAA,CAAQ,CACX,GAAM,CAACI,CAAAA,CAASC,EAAYC,CAAY,CAAA,CAAIV,CAAAA,CAAiB,OAAA,CAE7D,GAAIQ,CAAAA,CAYF,MAXqBG,MAAAA,CAAOH,EAAS,CACnC,GAAGC,CAAAA,CACH,QAAA,CAAUC,CAAAA,CACV,UAAA,CAAAnC,CAAAA,CACA,SAAA,CAAAD,EACA,SAAA,CAAAwB,CAAAA,CACA,QAAA,CAAU,UAAA,CACV,WAAA,CAAa,IAAA,CACb,UAAA,CAAY,CAACW,EAAW,QAC1B,CAAC,CAIL,CACF,CAEA,OAAIL,CAAAA,CACKA,CAAAA,CAAO,KAAK,UAAA,EAAc,CAACd,CAAAA,CAAO,gBAAA,CACpCJ,CAAAA,CAMDkB,CAAAA,CAAO,IAAA,CAGLL,CAAAA,CACJb,EACAD,CAMN,CAAA,CAAG,CAACS,CAAQ,CAAC,CAAA,CAGPkB,CAAAA,CAAcT,WAAAA,CACjBU,GAAmB,CAClB1C,CAAAA,CAAauB,CAAQ,CAAA,CASnBK,CAAAA,EAAwBvB,CAAAA,EAAOkB,CAAAA,EAAYhB,CAAAA,CAAYgB,CAAQ,CAAA,GAAM,CAAA,GAKtDoB,iBAAAA,CAAkBpB,CAAAA,CAAUpB,CAAAA,CAAWgB,CAAM,CAAA,EAG1DyB,CAAAA,CAAQ,KAAK,CAAA,CAAA,CAIjB,IAAMC,CAAAA,CAAcC,SAAAA,CAAUvB,CAAAA,CAAUmB,CAAE,CAAA,CAE1C,OAAO,IAAM,CACXxC,CAAAA,CAAaqB,CAAAA,CAAUpB,CAAAA,CAAWC,CAAAA,CAAYC,CAAG,CAAA,CACjDwC,CAAAA,GACF,CACF,CAAA,CACA,CAACtB,CAAAA,CAAUK,CAAAA,CAAsBvB,CAAAA,CAAKD,CAAAA,CAAYD,CAAS,CAC7D,CAAA,CAEM4C,CAAAA,CAAQC,oBAAAA,CAEZP,CAAAA,CAAaV,CAAAA,CAAaA,CAAW,CAAA,CAEjCa,CAAAA,CAAUZ,YAGd,MAAOiB,CAAAA,CAAe,IAAA,CAAMC,CAAAA,CAAgB,EAAC,GAAM,CACjD,GAAM,CAACb,CAAAA,CAASC,CAAAA,CAAYC,CAAY,CAAA,CAAIV,CAAAA,CAAiB,OAAA,CAE7D,GAAI,CAACQ,EACH,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA,CAI7B,IAAMc,CAAAA,CAAgB,CAAC,CAACF,CAAAA,CAGxB,GAAI,CAACE,CAAAA,EAAiBZ,CAAAA,CAAc,CAClC,IAAMN,CAAAA,CAASU,kBAAkBJ,CAAAA,CAAcpC,CAAAA,CAAWmC,CAAU,CAAA,CAEpE,GAAIL,CAAAA,CACF,OAAO,OAAA,CAAQ,QAAQA,CAAM,CAEjC,CAIA,IAAMmB,CAAAA,CAAcD,CAAAA,CAAgB,IAAM,IAAA,CAAOb,EAAW,WAAA,CAE5D,OAAOE,MAAAA,CAAOH,CAAAA,CAAS,CACrB,GAAGC,CAAAA,CACH,QAAA,CAAUC,EACV,GAAGW,CAAAA,CACH,UAAA,CAAA9C,CAAAA,CACA,SAAA,CAAAD,CAAAA,CACA,SAAA,CAAAwB,CAAAA,CACA,YAAAyB,CAAAA,CAEA,QAAA,CAAU,UAAA,CACV,WAAA,CAAa,IAAA,CACb,UAAA,CAAY,CAACd,CAAAA,CAAW,QAC1B,CAAC,CACH,CAAA,CACA,CAACnC,CAAAA,CAAWC,CAAU,CACxB,CAAA,CAEMiD,EAAON,CAAAA,CAAM,IAAA,CACbO,CAAAA,CAAe,CAACD,CAAAA,EAAQ,CAACN,CAAAA,CAAM,KAAA,CAO/BQ,EACJ,CAAC,CAAClD,CAAAA,GAAQ0C,CAAAA,CAAM,UAAA,EAAeO,CAAAA,EAAgB1B,CAAAA,CAAAA,CAC3C4B,CAAAA,CAAeD,GAAcD,CAAAA,CAC7BG,CAAAA,CAAeF,CAAAA,EAAc,CAACD,CAAAA,CAIpC,OAAO,CACL,IAAA,CAAAD,EACA,KAAA,CAAON,CAAAA,CAAM,KAAA,CACb,MAAA,CAAQA,CAAAA,CAAM,MAAA,CACd,OAAA,CAASA,CAAAA,CAAM,QACf,YAAA,CAAAS,CAAAA,CACA,UAAA,CAAAD,CAAAA,CACA,SAAA,CAAWA,CAAAA,CACX,YAAA,CAAAE,CAAAA,CACA,QAASV,CAAAA,CAAM,OAAA,CACf,SAAA,CAAWA,CAAAA,CAAM,UACjB,MAAA,CAAQA,CAAAA,CAAM,MAAA,CACd,OAAA,CAAAH,CACF,CACF","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 diff --git a/package-lock.json b/package-lock.json index b1efd141..3f2be16b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,26 +11,26 @@ "devDependencies": { "@size-limit/preset-small-lib": "12.0.0", "@testing-library/jest-dom": "6.9.1", - "@testing-library/react": "16.3.0", + "@testing-library/react": "16.3.2", "@types/jest": "30.0.0", - "@types/react": "19.2.7", + "@types/react": "19.2.13", "benchmark": "2.1.4", "eslint": "9.39.1", "eslint-config-prettier": "10.1.8", - "eslint-plugin-prettier": "5.5.4", + "eslint-plugin-prettier": "5.5.5", "fetch-mock": "12.6.0", - "globals": "16.5.0", + "globals": "17.3.0", "jest": "30.2.0", "jest-environment-jsdom": "30.2.0", - "prettier": "3.7.4", - "react": "19.2.1", - "react-dom": "19.2.1", + "prettier": "3.8.1", + "react": "19.2.4", + "react-dom": "19.2.4", "size-limit": "12.0.0", "ts-jest": "29.4.6", "tslib": "2.8.1", "tsup": "8.5.1", "typescript": "5.9.3", - "typescript-eslint": "8.48.1" + "typescript-eslint": "8.54.0" }, "engines": { "node": ">=18" @@ -1165,9 +1165,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2428,9 +2428,9 @@ "license": "MIT" }, "node_modules/@testing-library/react": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", - "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", "dev": true, "license": "MIT", "dependencies": { @@ -2636,9 +2636,9 @@ } }, "node_modules/@types/react": { - "version": "19.2.7", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", - "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", + "version": "19.2.13", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.13.tgz", + "integrity": "sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2677,21 +2677,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz", - "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz", + "integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.48.1", - "@typescript-eslint/type-utils": "8.48.1", - "@typescript-eslint/utils": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/type-utils": "8.54.0", + "@typescript-eslint/utils": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2701,7 +2700,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.48.1", + "@typescript-eslint/parser": "^8.54.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -2717,17 +2716,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz", - "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz", + "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.48.1", - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2742,15 +2741,15 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz", - "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz", + "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.48.1", - "@typescript-eslint/types": "^8.48.1", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.54.0", + "@typescript-eslint/types": "^8.54.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2764,14 +2763,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz", - "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz", + "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1" + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2782,9 +2781,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz", - "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz", + "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==", "dev": true, "license": "MIT", "engines": { @@ -2799,17 +2798,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz", - "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz", + "integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1", - "@typescript-eslint/utils": "8.48.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/utils": "8.54.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2824,9 +2823,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz", - "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz", + "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==", "dev": true, "license": "MIT", "engines": { @@ -2838,21 +2837,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz", - "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz", + "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.48.1", - "@typescript-eslint/tsconfig-utils": "8.48.1", - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1", - "debug": "^4.3.4", - "minimatch": "^9.0.4", - "semver": "^7.6.0", + "@typescript-eslint/project-service": "8.54.0", + "@typescript-eslint/tsconfig-utils": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2892,9 +2891,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -2905,16 +2904,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz", - "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz", + "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.48.1", - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2929,13 +2928,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz", - "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz", + "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/types": "8.54.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -4198,14 +4197,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", - "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", "dev": true, "license": "MIT", "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.11.7" + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.12" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -4675,9 +4674,9 @@ } }, "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.3.0.tgz", + "integrity": "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==", "dev": true, "license": "MIT", "engines": { @@ -4694,13 +4693,6 @@ "dev": true, "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -6228,9 +6220,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, @@ -6915,9 +6907,9 @@ } }, "node_modules/prettier": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", - "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", "bin": { @@ -6931,9 +6923,9 @@ } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, "license": "MIT", "dependencies": { @@ -7001,9 +6993,9 @@ "license": "MIT" }, "node_modules/react": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", - "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "dev": true, "license": "MIT", "engines": { @@ -7011,16 +7003,16 @@ } }, "node_modules/react-dom": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", - "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "dev": true, "license": "MIT", "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.1" + "react": "^19.2.4" } }, "node_modules/react-is": { @@ -7551,9 +7543,9 @@ "license": "MIT" }, "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7758,9 +7750,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -7987,16 +7979,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz", - "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.54.0.tgz", + "integrity": "sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.48.1", - "@typescript-eslint/parser": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1", - "@typescript-eslint/utils": "8.48.1" + "@typescript-eslint/eslint-plugin": "8.54.0", + "@typescript-eslint/parser": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/utils": "8.54.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/package.json b/package.json index a3ffd9e9..846baca4 100644 --- a/package.json +++ b/package.json @@ -87,32 +87,32 @@ }, { "path": "dist/react/index.js", - "limit": "9.5 KB" + "limit": "10 KB" } ], "devDependencies": { "@size-limit/preset-small-lib": "12.0.0", "@testing-library/jest-dom": "6.9.1", - "@testing-library/react": "16.3.0", + "@testing-library/react": "16.3.2", "@types/jest": "30.0.0", - "@types/react": "19.2.7", + "@types/react": "19.2.13", "benchmark": "2.1.4", "eslint": "9.39.1", "eslint-config-prettier": "10.1.8", - "eslint-plugin-prettier": "5.5.4", + "eslint-plugin-prettier": "5.5.5", "fetch-mock": "12.6.0", - "globals": "16.5.0", + "globals": "17.3.0", "jest": "30.2.0", "jest-environment-jsdom": "30.2.0", - "prettier": "3.7.4", - "react": "19.2.1", - "react-dom": "19.2.1", + "prettier": "3.8.1", + "react": "19.2.4", + "react-dom": "19.2.4", "size-limit": "12.0.0", "ts-jest": "29.4.6", "tslib": "2.8.1", "tsup": "8.5.1", "typescript": "5.9.3", - "typescript-eslint": "8.48.1" + "typescript-eslint": "8.54.0" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.38.0" From 54c63aec3d0f9bc9ab0337ddc0228ae8b3f1590b Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:43:45 +0100 Subject: [PATCH 14/30] fix: improve isSlowConnection function to handle non-browser environments --- src/utils.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index d753ede3..a74ea67b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -399,12 +399,7 @@ export function createAbortError( * @returns {boolean} True if connection is slow, false otherwise or if detection unavailable */ export const isSlowConnection = (): boolean => { - // Only works in browser environments - if (!isBrowser()) { - return false; - } - - const conn = navigator && (navigator as any).connection; + const conn = typeof navigator !== UNDEFINED && (navigator as any).connection; return conn && ['slow-2g', '2g', '3g'].includes(conn.effectiveType); }; From 04abe6ba3d8704d121718610766870730abd0a66 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 02:43:51 +0100 Subject: [PATCH 15/30] feat: add support for react-native in exports and keywords --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 846baca4..b5df3e42 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "exports": { ".": { "types": "./dist/index.d.ts", + "react-native": "./dist/browser/index.mjs", "import": { "node": "./dist/node/index.js", "default": "./dist/browser/index.mjs" @@ -45,7 +46,8 @@ "http-client", "browser", "node", - "nodejs" + "nodejs", + "react-native" ], "engines": { "node": ">=18" From 0eb98a55a8b6394d40c366107663c66813de272d Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 03:03:26 +0100 Subject: [PATCH 16/30] feat: add React Native support with custom event providers for focus and online events --- README.md | 34 +++++++++ src/index.ts | 5 +- src/revalidator-manager.ts | 69 +++++++++++++----- src/types/request-handler.ts | 6 +- src/utils.ts | 2 +- test/revalidator-manager.spec.ts | 117 +++++++++++++++++++++++++++++++ 6 files changed, 213 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index bc1af52b..83b71c68 100644 --- a/README.md +++ b/README.md @@ -1149,6 +1149,8 @@ const api = createApiFetcher({ 4. **Consider user experience** - Network revalidation happens silently in the background, providing smooth UX without loading spinners. > ⚠️ **Browser Support**: These features work in all modern browsers that support the `focus` and `online` events. In server-side environments (Node.js), these options are safely ignored. +> +> **React Native**: Use `setEventProvider()` to enable these features. See the [React Native](#react-native) section for details. @@ -3798,6 +3800,38 @@ For environments that do not support modern JavaScript features or APIs, you mig - **Promise Polyfill**: For older browsers that do not support Promises. Libraries like [es6-promise](https://github.com/stefanpenner/es6-promise) can be used. - **AbortController Polyfill**: For environments that do not support the `AbortController` API used for aborting fetch requests. You can use the [abort-controller](https://github.com/mysticatea/abort-controller) polyfill. +### React Native + +`fetchff` is fully compatible with React Native. Core features like caching, retries, deduplication, and the React hook work out of the box. + +To enable `refetchOnFocus` and `refetchOnReconnect`, register event providers at your app's entry point using `setEventProvider()`: + +```ts +import { AppState } from 'react-native'; +import NetInfo from '@react-native-community/netinfo'; +import { setEventProvider } from 'fetchff'; + +// Refetch when app comes to foreground +setEventProvider('focus', (handler) => { + const sub = AppState.addEventListener('change', (state) => { + if (state === 'active') handler(); + }); + return () => sub.remove(); +}); + +// Refetch when network reconnects +setEventProvider('online', (handler) => { + let wasConnected = true; + const unsubscribe = NetInfo.addEventListener((state) => { + if (state.isConnected && !wasConnected) handler(); + wasConnected = !!state.isConnected; + }); + return unsubscribe; +}); +``` + +> **Note:** `@react-native-community/netinfo` is optional — only needed if you use `refetchOnReconnect`. + ### Using `node-fetch` for Node.js < 18 If you need to support Node.js versions below 18 (not officially supported), you can use the [`node-fetch`](https://www.npmjs.com/package/node-fetch) package to polyfill the `fetch` API. Install it with: diff --git a/src/index.ts b/src/index.ts index 5e7d1008..fee9c4af 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,15 +29,18 @@ export { revalidate, // Revalidate specific cache entry revalidateAll, // Revalidate all entries by event type removeRevalidators, // Clean up all revalidators by type + setEventProvider, // Register custom event provider for focus/online events (e.g. React Native) } from './revalidator-manager'; +export type { EventProvider } from './revalidator-manager'; + /** Subscribe to cache updates via pub/sub */ export { subscribe } from './pubsub-manager'; /** Abort in-flight requests and check request status */ export { abortRequest, getInFlightPromise } from './inflight-manager'; -/** Network and environment utilities (Browser Only) */ +/** Network and environment utilities */ export { isSlowConnection, createAbortError } from './utils'; /** Timeout management for delayed operations */ diff --git a/src/revalidator-manager.ts b/src/revalidator-manager.ts index dbed6ac5..ff9332c6 100644 --- a/src/revalidator-manager.ts +++ b/src/revalidator-manager.ts @@ -40,15 +40,39 @@ const DEFAULT_TTL = 3 * 60 * 1000; // Default TTL of 3 minutes const revalidators = new Map(); /** - * Stores global event handlers for cache revalidation events (e.g., focus, online). - * This avoids attaching multiple event listeners by maintaining a single handler per event type. - * Event handlers are registered as needed when revalidators are registered with the corresponding flags. + * Stores cleanup functions for active event handlers (browser or custom providers). + * Each entry removes the corresponding event listener when called. * @remarks * - Improves performance by reducing the number of event listeners. * - Enables efficient O(1) lookup and management of event handlers for revalidation. */ const eventHandlers = new Map void>(); +/** Subscribe to an event and return a cleanup function */ +export type EventProvider = (handler: () => void) => () => void; + +const customEventProviders = new Map(); + +/** + * Registers a custom event provider for 'focus' or 'online' events. + * Useful for non-browser environments like React Native. + * + * @param type - The event type ('focus' or 'online'). + * @param provider - A function that subscribes to the event and returns a cleanup function. + */ +export function setEventProvider( + type: EventType, + provider: EventProvider, +): void { + customEventProviders.set(type, provider); + + // Re-register if already active + if (eventHandlers.has(type)) { + removeEventHandler(type); + addEventHandler(type); + } +} + /** * Triggers revalidation for all registered entries based on the given event type. * For example, if it's a 'focus' event, it will revalidate entries that have the `refetchOnFocus` flag set. @@ -135,36 +159,47 @@ export function removeRevalidators(type: EventType) { /** * Registers a generic revalidation event handler for the specified event type. - * Ensures the handler is only added once and only in browser environments. + * Supports browser window events and custom event providers (e.g. for React Native). + * Ensures the handler is only added once. * - * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange'). + * @param event - The type of event to listen for (e.g., 'focus', 'online'). */ function addEventHandler(event: EventType) { - if (!isBrowser() || eventHandlers.has(event)) { + if (eventHandlers.has(event)) { return; } const handler = revalidateAll.bind(null, event, true); - eventHandlers.set(event, handler); - window.addEventListener(event, handler); + // Priority 1: Custom event provider (works in any environment including React Native) + const customProvider = customEventProviders.get(event); + + if (customProvider) { + const cleanup = customProvider(handler); + + eventHandlers.set(event, cleanup); + + return; + } + + // Priority 2: Browser window events + if (isBrowser()) { + window.addEventListener(event, handler); + + eventHandlers.set(event, () => window.removeEventListener(event, handler)); + } } /** - * Removes the generic event handler for the specified event type from the window object. + * Removes the event handler for the specified event type. * * @param event - The type of event whose handler should be removed. */ function removeEventHandler(event: EventType) { - if (!isBrowser()) { - return; - } - - const handler = eventHandlers.get(event); - - if (handler) { - window.removeEventListener(event, handler); + const cleanup = eventHandlers.get(event); + if (cleanup) { + cleanup(); eventHandlers.delete(event); } } diff --git a/src/types/request-handler.ts b/src/types/request-handler.ts index 463d66fb..59e6dc12 100644 --- a/src/types/request-handler.ts +++ b/src/types/request-handler.ts @@ -497,12 +497,16 @@ export interface ExtendedRequestConfig< /** * If true, automatically revalidates the request when the window regains focus. + * In browsers, listens for the 'focus' window event. + * Custom providers can be registered via `setEventProvider('focus', provider)`. * @default false */ refetchOnFocus?: boolean; /** - * If true, automatically revalidates the request when the browser regains network connectivity. + * If true, automatically revalidates the request when network connectivity is restored. + * In browsers, listens for the 'online' window event. + * Otherwise, requires a custom event provider via `setEventProvider('online', provider)`. * @default false */ refetchOnReconnect?: boolean; diff --git a/src/utils.ts b/src/utils.ts index a74ea67b..cf8d459a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -366,7 +366,7 @@ export function processHeaders( * @returns {boolean} - True if running in a browser environment, false otherwise. */ export function isBrowser(): boolean { - // For node and and some mobile frameworks like React Native, `add/removeEventListener` doesn't exist on window! + // For node and some mobile frameworks like React Native, `add/removeEventListener` doesn't exist on window! return ( typeof window !== UNDEFINED && typeof window.addEventListener === FUNCTION ); diff --git a/test/revalidator-manager.spec.ts b/test/revalidator-manager.spec.ts index e13024bf..fb97aa38 100644 --- a/test/revalidator-manager.spec.ts +++ b/test/revalidator-manager.spec.ts @@ -7,6 +7,7 @@ import { revalidate, startRevalidatorCleanup, removeRevalidators, + setEventProvider, } from '../src/revalidator-manager'; describe('Revalidator Manager', () => { @@ -1257,4 +1258,120 @@ describe('Revalidator Manager', () => { jest.useFakeTimers(); // Restore fake timers }); }); + + describe('setEventProvider', () => { + afterEach(() => { + removeRevalidators('focus'); + removeRevalidators('online'); + }); + + it('should use custom provider instead of window events for focus', () => { + const cleanup = jest.fn(); + let capturedHandler: (() => void) | undefined; + + setEventProvider('focus', (handler) => { + capturedHandler = handler; + return cleanup; + }); + + addRevalidator( + testKey, + mockRevalidatorFn, + undefined, + undefined, + mockRevalidatorFn, + true, + ); + + // Trigger focus via custom provider + capturedHandler!(); + + expect(mockRevalidatorFn).toHaveBeenCalledTimes(1); + }); + + it('should use custom provider for online events', () => { + const cleanup = jest.fn(); + let capturedHandler: (() => void) | undefined; + + setEventProvider('online', (handler) => { + capturedHandler = handler; + return cleanup; + }); + + addRevalidator( + testKey, + mockRevalidatorFn, + undefined, + undefined, + mockRevalidatorFn, + false, + true, + ); + + capturedHandler!(); + + expect(mockRevalidatorFn).toHaveBeenCalledTimes(1); + }); + + it('should call cleanup when removing revalidators', () => { + const cleanup = jest.fn(); + + setEventProvider('focus', () => cleanup); + + addRevalidator( + testKey, + mockRevalidatorFn, + undefined, + undefined, + undefined, + true, + ); + + removeRevalidators('focus'); + + expect(cleanup).toHaveBeenCalledTimes(1); + }); + + it('should re-register handler when provider is set after revalidators', () => { + const cleanup = jest.fn(); + let capturedHandler: (() => void) | undefined; + + // First register with browser events + addRevalidator( + testKey, + mockRevalidatorFn, + undefined, + undefined, + mockRevalidatorFn, + true, + ); + + // Then set a custom provider — should re-register + setEventProvider('focus', (handler) => { + capturedHandler = handler; + return cleanup; + }); + + // Custom provider should now be active + capturedHandler!(); + + expect(mockRevalidatorFn).toHaveBeenCalledTimes(1); + }); + + it('should not trigger revalidators without the matching flag', () => { + let capturedHandler: (() => void) | undefined; + + setEventProvider('focus', (handler) => { + capturedHandler = handler; + return jest.fn(); + }); + + // Register without refetchOnFocus + addRevalidator(testKey, mockRevalidatorFn); + + capturedHandler?.(); + + expect(mockRevalidatorFn).not.toHaveBeenCalled(); + }); + }); }); From c0572a7042b7a24c6cb991b029b4d543e9887a56 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 03:06:56 +0100 Subject: [PATCH 17/30] test: enhance cache and response handling tests with new scenarios --- test/cache-manager.spec.ts | 25 ++++++++ test/config-handler.spec.ts | 49 ++++++++++++++++ test/request-parser.spec.ts | 112 +++++++++++++++++++++++++++++++++++- test/retry-handler.spec.ts | 38 ++++++++++++ test/utils.spec.ts | 64 +++++++++++++++++++++ 5 files changed, 286 insertions(+), 2 deletions(-) diff --git a/test/cache-manager.spec.ts b/test/cache-manager.spec.ts index a554d776..8c07fd6b 100644 --- a/test/cache-manager.spec.ts +++ b/test/cache-manager.spec.ts @@ -1,6 +1,7 @@ import { generateCacheKey, getCache, + getCacheData, setCache, deleteCache, getCachedResponse, @@ -346,6 +347,30 @@ describe('Cache Manager', () => { ); expect(result).toBeNull(); }); + + it('should return null when cache mode is reload', () => { + setCache(cacheKey, responseObj, cacheTime); + fetcherConfig.cache = 'reload'; + const result = getCachedResponse(cacheKey, cacheTime, fetcherConfig); + expect(result).toBeNull(); + delete fetcherConfig.cache; + }); + }); + + describe('getCacheData', () => { + it('should return cached data for existing key', () => { + setCache('data-key', { data: 'test-value' }); + const result = getCacheData('data-key'); + expect(result).toEqual({ data: 'test-value' }); + }); + + it('should return null for non-existent key', () => { + expect(getCacheData('missing-key')).toBeNull(); + }); + + it('should return null for null key', () => { + expect(getCacheData(null)).toBeNull(); + }); }); describe('mutate', () => { diff --git a/test/config-handler.spec.ts b/test/config-handler.spec.ts index 8db40140..d57c6a8c 100644 --- a/test/config-handler.spec.ts +++ b/test/config-handler.spec.ts @@ -283,4 +283,53 @@ describe('request() Content-Type', () => { }); }, ); + + it('should set Content-Type on Headers instance when not already set', () => { + const headers = new Headers(); + headers.set('Accept', 'application/json'); + const result = buildFetcherConfig(apiUrl, { + method: 'POST', + body: { foo: 'bar' }, + headers, + }); + expect((result.headers as Headers).get('Content-Type')).toContain( + 'application/json', + ); + }); + + it('should not override Content-Type on Headers instance when already set', () => { + const headers = new Headers(); + headers.set('Content-Type', 'text/plain'); + const result = buildFetcherConfig(apiUrl, { + method: 'POST', + body: { foo: 'bar' }, + headers, + }); + expect((result.headers as Headers).get('Content-Type')).toBe('text/plain'); + }); + + it('should set Content-Type to application/x-www-form-urlencoded for URLSearchParams body', () => { + const params = new URLSearchParams(); + params.set('key', 'value'); + const result = buildFetcherConfig(apiUrl, { + method: 'POST', + body: params, + headers: {}, + }); + expect((result.headers as Record)['Content-Type']).toContain( + 'x-www-form-urlencoded', + ); + }); + + it('should set Content-Type to application/octet-stream for ArrayBuffer body', () => { + const buffer = new ArrayBuffer(8); + const result = buildFetcherConfig(apiUrl, { + method: 'POST', + body: buffer, + headers: {}, + }); + expect((result.headers as Record)['Content-Type']).toContain( + 'octet-stream', + ); + }); }); diff --git a/test/request-parser.spec.ts b/test/request-parser.spec.ts index 4c7b3c04..0b72d422 100644 --- a/test/request-parser.spec.ts +++ b/test/request-parser.spec.ts @@ -1,5 +1,8 @@ -import { parseResponseData } from '../src/response-parser'; -import type { FetchResponse } from '../src/types/request-handler'; +import { parseResponseData, prepareResponse } from '../src/response-parser'; +import type { + FetchResponse, + RequestConfig, +} from '../src/types/request-handler'; describe('parseData()', () => { let mockResponse: FetchResponse; @@ -119,4 +122,109 @@ describe('parseData()', () => { const data = await parseResponseData(mockResponse); expect(data).toEqual(streamContent); }); + + it('should return null for null response', async () => { + const data = await parseResponseData(null as any); + expect(data).toBeNull(); + }); + + it('should auto-parse JSON-like text when content type is missing', async () => { + (mockResponse.headers.get as jest.Mock).mockReturnValue(''); + (mockResponse.text as jest.Mock).mockResolvedValue('{"key":"value"}'); + + const data = await parseResponseData(mockResponse); + expect(data).toEqual({ key: 'value' }); + }); + + it('should auto-parse JSON array text when content type is missing', async () => { + (mockResponse.headers.get as jest.Mock).mockReturnValue(''); + (mockResponse.text as jest.Mock).mockResolvedValue('[1,2,3]'); + + const data = await parseResponseData(mockResponse); + expect(data).toEqual([1, 2, 3]); + }); +}); + +describe('prepareResponse()', () => { + const baseConfig: RequestConfig = { + method: 'GET', + url: '/test', + cacheKey: 'test-key', + }; + + it('should return error response when response is null', () => { + const result = prepareResponse(null, baseConfig); + + expect(result.ok).toBe(false); + expect(result.data).toBeNull(); + expect(result.isFetching).toBe(false); + expect(result.isSuccess).toBe(false); + expect(result.isError).toBe(true); + expect(result.headers).toBeNull(); + expect(typeof result.mutate).toBe('function'); + }); + + it('should use defaultResponse when response is null and defaultResponse is set', () => { + const config = { ...baseConfig, defaultResponse: { fallback: true } }; + const result = prepareResponse(null, config); + + expect(result.data).toEqual({ fallback: true }); + }); + + it('should apply flattenResponse when enabled', () => { + const response = { + data: { data: 'nested-value' }, + ok: true, + headers: {}, + } as unknown as FetchResponse; + const config = { ...baseConfig, flattenResponse: true }; + + const result = prepareResponse(response, config); + + expect(result.data).toBe('nested-value'); + }); + + it('should apply select function when provided', () => { + const response = { + data: { items: [1, 2, 3], total: 3 }, + ok: true, + headers: {}, + } as unknown as FetchResponse; + const config = { + ...baseConfig, + select: (data: any) => data.items, + }; + + const result = prepareResponse(response, config); + + expect(result.data).toEqual([1, 2, 3]); + }); + + it('should handle custom fetcher response (non-native Response)', () => { + const response = { + data: { id: 1 }, + ok: true, + headers: {}, + } as unknown as FetchResponse; + + const result = prepareResponse(response, baseConfig); + + expect(result.isFetching).toBe(false); + expect(result.isSuccess).toBe(true); + expect(result.isError).toBe(false); + expect(typeof result.mutate).toBe('function'); + }); + + it('should set defaultResponse when data is empty object', () => { + const response = { + data: {}, + ok: true, + headers: {}, + } as unknown as FetchResponse; + const config = { ...baseConfig, defaultResponse: [] }; + + const result = prepareResponse(response, config); + + expect(result.data).toEqual([]); + }); }); diff --git a/test/retry-handler.spec.ts b/test/retry-handler.spec.ts index 9eca5b0e..af57a230 100644 --- a/test/retry-handler.spec.ts +++ b/test/retry-handler.spec.ts @@ -43,4 +43,42 @@ describe('getRetryAfterMs', () => { getRetryAfterMs({ headers: { 'retry-after': 'not-a-date' } } as any), ).toBeNull(); }); + + it('parses ratelimit-reset-after header', () => { + expect( + getRetryAfterMs({ headers: { 'ratelimit-reset-after': '5' } } as any), + ).toBe(5000); + }); + + it('parses x-ratelimit-reset-after header', () => { + expect( + getRetryAfterMs({ headers: { 'x-ratelimit-reset-after': '3' } } as any), + ).toBe(3000); + }); + + it('parses ratelimit-reset-at header with future date', () => { + const future = new Date(Date.now() + 5000).toUTCString(); + const ms = getRetryAfterMs({ + headers: { 'ratelimit-reset-at': future }, + } as any); + expect(ms).toBeGreaterThanOrEqual(0); + expect(ms).toBeLessThanOrEqual(5000); + }); + + it('parses x-ratelimit-reset-at header with future date', () => { + const future = new Date(Date.now() + 5000).toUTCString(); + const ms = getRetryAfterMs({ + headers: { 'x-ratelimit-reset-at': future }, + } as any); + expect(ms).toBeGreaterThanOrEqual(0); + expect(ms).toBeLessThanOrEqual(5000); + }); + + it('returns null for invalid ratelimit-reset-at value', () => { + expect( + getRetryAfterMs({ + headers: { 'ratelimit-reset-at': 'not-a-date' }, + } as any), + ).toBeNull(); + }); }); diff --git a/test/utils.spec.ts b/test/utils.spec.ts index f2c7e385..4dc3e15b 100644 --- a/test/utils.spec.ts +++ b/test/utils.spec.ts @@ -7,6 +7,8 @@ import { sortObject, sanitizeObject, createAbortError, + shallowSerialize, + flattenData, } from '../src/utils'; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -729,4 +731,66 @@ describe('Utils', () => { expect(controller.signal.reason).toBe(error); }); }); + + describe('shallowSerialize()', () => { + it('should serialize object properties to a string', () => { + const result = shallowSerialize({ a: 1, b: 'test' }); + expect(result).toBe('a:1b:test'); + }); + + it('should return empty string for empty object', () => { + expect(shallowSerialize({})).toBe(''); + }); + + it('should skip inherited properties', () => { + const parent = { inherited: true }; + const child = Object.create(parent); + child.own = 'value'; + expect(shallowSerialize(child)).toBe('own:value'); + }); + }); + + describe('flattenData()', () => { + it('should flatten nested data property', () => { + expect(flattenData({ data: 'value' })).toBe('value'); + }); + + it('should recursively flatten deeply nested data', () => { + expect(flattenData({ data: { data: 'deep' } })).toBe('deep'); + }); + + it('should return non-object data as-is', () => { + expect(flattenData('string')).toBe('string'); + expect(flattenData(42)).toBe(42); + expect(flattenData(null)).toBe(null); + }); + + it('should return object without data property as-is', () => { + const obj = { foo: 'bar' }; + expect(flattenData(obj)).toEqual(obj); + }); + + it('should stop at max recursion depth', () => { + // Build a deeply nested structure beyond MAX_DEPTH (10) + let nested: any = 'bottom'; + for (let i = 0; i < 15; i++) { + nested = { data: nested }; + } + const result = flattenData(nested); + // Should not reach 'bottom' due to depth limit + expect(result).toHaveProperty('data'); + }); + }); + + describe('appendQueryParams() - max depth', () => { + it('should stop recursion at max depth for deeply nested params', () => { + let nested: any = 'value'; + for (let i = 0; i < 15; i++) { + nested = { a: nested }; + } + const result = appendQueryParams('https://example.com', nested); + // Should not throw — recursion stops before stack overflow + expect(result).toContain('https://example.com'); + }); + }); }); From 1689727c734050cfa69f50ed1721d468ae141af7 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 03:07:06 +0100 Subject: [PATCH 18/30] chore: build --- dist/browser/index.global.js | 4 ++-- dist/browser/index.global.js.map | 2 +- dist/browser/index.mjs | 4 ++-- dist/browser/index.mjs.map | 2 +- dist/node/index.js | 4 ++-- dist/node/index.js.map | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dist/browser/index.global.js b/dist/browser/index.global.js index 45593b60..b4ea3e05 100644 --- a/dist/browser/index.global.js +++ b/dist/browser/index.global.js @@ -1,3 +1,3 @@ -var fetchff=(function(exports){'use strict';var mt=Object.defineProperty;var pt=(e,t,r)=>t in e?mt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var L=(e,t,r)=>pt(e,typeof t!="symbol"?t+"":t,r);var C="application/",j=C+"json",ve="charset=utf-8",w="Content-Type",R="undefined",K="object",E="string",g="function",ee="AbortError",Ne="TimeoutError",S="GET",_e="HEAD",te="reject";var He=10;function re(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===K}function J(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(c)+"="+a(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function ae(e){return e.includes("://")}var P=()=>Date.now(),v=()=>{};function De(e){let t=typeof e;return e==null?false:t===E||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||re(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function Te(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?Te(e.data,t+1):e}function ne(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a]=r;});else if(d(e))for(let[r,a]of Object.entries(e))t[r.toLowerCase()]=a;return t}function se(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var be=()=>{if(!se())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;L(this,"status");L(this,"statusText");L(this,"config");L(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,z=1e3,dt=ce*z,Ee=Array(ce).fill(0).map(()=>[]),A=new Map,le=0,x=null,Ke=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(v);}catch(r){}},I=(e,t,r)=>{if(_(e),rdt||r%z!==0){A.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let a=r/z,n=(le+a)%ce;Ee[n].push([e,t]),A.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Ee[le];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ze(e,oe(t+" aborted due to timeout",Ne));},r),i}async function ze(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),B.delete(e);}function ke(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function xe(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&ht(a);});}function Ge(e){if(!se()||me.has(e))return;let t=We.bind(null,e,true);me.set(e,t),window.addEventListener(e,t);}function Pt(e){if(!se())return;let t=me.get(e);t&&(window.removeEventListener(e,t),me.delete(e));}function Ye(e,t,r,a,n,s,o){G.set(e,[t,P(),yt,a,n,s,o]),s&&Ge("focus"),o&&Ge("online"),a&&I("s:"+e,pe.bind(null,e,true),a*1e3);}function ht(e){G.delete(e),_("s:"+e);}var W=new Map;function gt(e){let t=W.get(e);return t||(t=new Set,W.set(e,t)),t}function Dt(e,t){gt(e).add(t);}function Tt(e,t){let r=W.get(e);r&&(r.delete(t),r.size===0&&W.delete(e));}function U(e,t){let r=W.get(e);if(r)if(r.size===1){let a=r.values().next().value;a(t);}else r.forEach(a=>a(t));}function bt(e,t){return e?(Dt(e,t),()=>{Tt(e,t);}):v}var Ce=(be()?60:30)*1e3,H={strategy:te,timeout:Ce,headers:{Accept:j+", 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 Et(e){let t=J(e);return Object.assign(H,t),H}function Ve(){return {...H}}function qe(e,t){if(!t)return $e(e,Ve());let r=J(t),a=Y(H,r);return $e(e,a)}function $e(e,t){var i;let r=t.method;r=r?r.toUpperCase():S;let a;r!==S&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==E&&De(a)&&(a=JSON.stringify(a))),xt(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=n,t.body=a,t}function xt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(re(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(De(t))r=j+";"+ve;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function Y(e,t){let r=Object.assign({},e,t);return Ze("retry",r,e,t),Ze("headers",r,e,t),we("onRequest",r,e,t),we("onResponse",r,e,t),we("onError",r,e,t),r}function we(e,t,r,a){let n=r[e],s=a[e];if(!n&&!s)return;if(!n){t[e]=s;return}if(!s){t[e]=n;return}let o=Array.isArray(n)?n:[n],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Ze(e,t,r,a){a[e]&&(t[e]={...r[e],...a[e]});}var ye=new Map,F="|",Ae=64,Xe=/[^\w\-_|/:@.?=&~%#]/g,et=/[^\w\-_|/:@.?=&~%#]/,Ct=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 $(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===E?r:r(e);let{url:a="",method:n=S,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=ne(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>Ae&&(i=k(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Me(o)):String(o);i=l.length>Ae?k(l):l;}let m=n+F+a+F+u+F+c+F+i;return et.test(m)?m.replace(Xe,""):m}function tt(e){return e.expiry?P()>e.expiry:false}function wt(e){return e.stale?P()>e.stale:false}function Re(e){return ye.get(e)}function Pe(e,t,r,a){if(r===0){de(e);return}let n=P(),s=r?r*1e3:0,o=a?a*1e3:0;ye.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&I("c:"+e,()=>{de(e,true);},s);}function de(e,t=false){if(t){let r=Re(e);if(!r||!tt(r))return}ye.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=Re(e);if(!a)return null;let n=d(t)?J(t):t,s={...a.data,data:n},o={...a,data:s};return ye.set(e,o),U(e,s),r&&r.refetch?await pe(e):null}function he(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||H.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=Re(e);if(!n)return null;let s=tt(n),o=wt(n);return s?(de(e),null):!o||o&&!s?n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Pe(a,e,n,t.staleTime),U(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function rt(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(j)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===E){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===K&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=Te(u)),t.select&&(e.data=u=t.select(u));let c=ne(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function at(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function qt(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 u=at(r);if(u!==null)return u}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?at(s):null}async function nt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=a,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=$(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await N(t);return o}async function ot(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await q(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&It(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===te)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function it(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===ee;}function It(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe={isFetching:true};async function ge(e,t=null){let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||a||o||p||n||i||m),f=null;if(h&&(f=$(r)),f&&p){let T=he(f,u,r);if(T)return T}if(f&&o){let T=xe(f,o);if(T)return T}let D=r.retry||{},{retries:ut=0,resetTimeout:lt}=D,Qe=async(T=false,V=0)=>{V||(f&&!T&&(c?he(f,u,r)||(Pe(f,Oe,u,c),U(f,Oe)):U(f,Oe)),r.cacheKey=f);let O=r.url,ft=Je(f,O,a,o||0,!!n,!!(a&&(!V||lt))),b=r;b.signal=ft.signal;let X,y=null;try{r.onRequest&&(f&&o&&!V&&await null,await q(r.onRequest,b));let Q=r.fetcher;if(y=Q?await Q(O,b):await fetch(O,b),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await rt(y):Q&&("data"in y&&"body"in y||(y={data:y})),y.config=b,y.ok!==void 0&&!y.ok))throw new ue(`${b.method} to ${O} failed! Status: ${y.status||null}`,b,y);X=Fe(y,b);let M=r.onResponse;M&&await q(M,X);}catch(Q){let M=Q;it(M,y,b),X=Fe(y,b,M);}return X},ct=ut>0?(T=false)=>nt((V,O)=>Qe(T,O),D):Qe,Z=(T=false)=>ot(T,ct,r),Se=l?st(Z,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):Z();return f&&(o&&ke(f,Se),Ye(f,Z,void 0,c,Z,!!i,!!m)),Se}function Bt(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=t[n],u=o||{url:String(n)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?(o==null?void 0:o.url)===c?Y(u,s):s:Y(Y(e,u),s);return ge(c,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=ze;exports.addTimeout=I;exports.buildConfig=qe;exports.createAbortError=oe;exports.createApiFetcher=Bt;exports.deleteCache=de;exports.fetchf=ge;exports.fetchff=ge;exports.generateCacheKey=$;exports.getCache=Re;exports.getCachedResponse=he;exports.getDefaultConfig=Ve;exports.getInFlightPromise=xe;exports.isSlowConnection=be;exports.mutate=Ie;exports.removeRevalidators=Rt;exports.revalidate=pe;exports.revalidateAll=We;exports.setCache=Pe;exports.setDefaultConfig=Et;exports.subscribe=bt;return exports;})({});//# sourceMappingURL=index.global.js.map +var fetchff=(function(exports){'use strict';var dt=Object.defineProperty;var yt=(e,t,r)=>t in e?dt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var j=(e,t,r)=>yt(e,typeof t!="symbol"?t+"":t,r);var C="application/",K=C+"json",Se="charset=utf-8",w="Content-Type",R="undefined",J="object",b="string",g="function",te="AbortError",Ne="TimeoutError",Q="GET",_e="HEAD",re="reject";var He=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===J}function z(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function ae(e){return e.includes("://")}var P=()=>Date.now(),S=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function se(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n]=r;});else if(d(e))for(let[r,n]of Object.entries(e))t[r.toLowerCase()]=n;return t}function Ke(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var ie=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;j(this,"status");j(this,"statusText");j(this,"config");j(this,"isCancelled");this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var ce=600,k=1e3,Rt=ce*k,Te=Array(ce).fill(0).map(()=>[]),A=new Map,le=0,x=null,Je=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(S);}catch(r){}},I=(e,t,r)=>{if(_(e),rRt||r%k!==0){A.set(e,[setTimeout(Je.bind(null,[e,t]),r)]);return}let n=r/k,a=(le+n)%ce;Te[a].push([e,t]),A.set(e,a),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Te[le];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function ze(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ke(e,oe(t+" aborted due to timeout",Ne));},r),i}async function ke(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),B.delete(e);}function Ge(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function be(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&Dt(n);});}function xe(e){if(U.has(e))return;let t=Ye.bind(null,e,true),r=We.get(e);if(r){let n=r(t);U.set(e,n);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function $e(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ze(e,t,r,n,a,s,o){W.set(e,[t,P(),Pt,n,a,s,o]),s&&xe("focus"),o&&xe("online"),n&&I("s:"+e,me.bind(null,e,true),n*1e3);}function Dt(e){W.delete(e),_("s:"+e);}var Y=new Map;function Et(e){let t=Y.get(e);return t||(t=new Set,Y.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=Y.get(e);r&&(r.delete(t),r.size===0&&Y.delete(e));}function H(e,t){let r=Y.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function xt(e,t){return e?(Tt(e,t),()=>{bt(e,t);}):S}var Ce=(Ee()?60:30)*1e3,M={strategy:re,timeout:Ce,headers:{Accept:K+", 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 Ct(e){let t=z(e);return Object.assign(M,t),M}function et(){return {...M}}function qe(e,t){if(!t)return Ve(e,et());let r=z(t),n=$(M,r);return Ve(e,n)}function Ve(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let n;r!==Q&&r!==_e&&(n=(i=t.body)!=null?i:t.data,n&&typeof n!==b&&ge(n)&&(n=JSON.stringify(n))),wt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function wt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(ge(t))r=K+";"+Se;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function $(e,t){let r=Object.assign({},e,t);return Xe("retry",r,e,t),Xe("headers",r,e,t),we("onRequest",r,e,t),we("onResponse",r,e,t),we("onError",r,e,t),r}function we(e,t,r,n){let a=r[e],s=n[e];if(!a&&!s)return;if(!a){t[e]=s;return}if(!s){t[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Xe(e,t,r,n){n[e]&&(t[e]={...r[e],...n[e]});}var de=new Map,F="|",Ae=64,tt=/[^\w\-_|/:@.?=&~%#]/g,rt=/[^\w\-_|/:@.?=&~%#]/,qt=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 Z(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:n="",method:a=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=se(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>Ae&&(i=G(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Me(o)):String(o);i=l.length>Ae?G(l):l;}let m=a+F+n+F+u+F+c+F+i;return rt.test(m)?m.replace(tt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function At(e){return e.stale?P()>e.stale:false}function ye(e){return de.get(e)}function Re(e,t,r,n){if(r===0){pe(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;de.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&I("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!nt(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let n=ye(e);if(!n)return null;let a=d(t)?z(t):t,s={...n.data,data:a},o={...n,data:s};return de.set(e,o),H(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||M.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=ye(e);if(!a)return null;let s=nt(a),o=At(a);return s?(pe(e),null):!o||o&&!s?a.data:null}function Be(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(n,e,a,t.staleTime),H(n,e),fe(n);let o=t._prevKey;o&&fe(o);}}async function at(e){var a;if(!e)return null;let t=(a=e.headers)==null?void 0:a.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(K)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===b){let s=n.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{n=JSON.parse(s);}catch(o){}}}catch(s){n=null;}return n}var Fe=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ie.bind(null,a);if(!e)return {ok:false,error:r,data:n!=null?n:null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===J&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let c=se(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function st(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function It(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 u=st(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?st(s):null}async function ot(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Z(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await N(t);return o}async function ut(e,t,r){let n=await t(e),a=n.error;if(!a)return Be(n,r),n;r.onError&&await q(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&Ft(r,"FETCH ERROR",a),Be(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===re)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function lt(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===te;}function Ft(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var ve={isFetching:true};async function he(e,t=null){let r=qe(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=Z(r)),f&&p){let E=Pe(f,u,r);if(E)return E}if(f&&o){let E=be(f,o);if(E)return E}let D=r.retry||{},{retries:ct=0,resetTimeout:ft}=D,Oe=async(E=false,X=0)=>{X||(f&&!E&&(c?Pe(f,u,r)||(Re(f,ve,u,c),H(f,ve)):H(f,ve)),r.cacheKey=f);let v=r.url,pt=ze(f,v,n,o||0,!!a,!!(n&&(!X||ft))),T=r;T.signal=pt.signal;let ee,y=null;try{r.onRequest&&(f&&o&&!X&&await null,await q(r.onRequest,T));let O=r.fetcher;if(y=O?await O(v,T):await fetch(v,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await at(y):O&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${v} failed! Status: ${y.status||null}`,T,y);ee=Fe(y,T);let L=r.onResponse;L&&await q(L,ee);}catch(O){let L=O;lt(L,y,T),ee=Fe(y,T,L);}return ee},mt=ct>0?(E=false)=>ot((X,v)=>Oe(E,v),D):Oe,V=(E=false)=>ut(E,mt,r),Qe=l?it(V,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):V();return f&&(o&&Ge(f,Qe),Ze(f,V,void 0,c,V,!!i,!!m)),Qe}function vt(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?(o==null?void 0:o.url)===c?$(u,s):s:$($(e,u),s);return he(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} +exports.abortRequest=ke;exports.addTimeout=I;exports.buildConfig=qe;exports.createAbortError=oe;exports.createApiFetcher=vt;exports.deleteCache=pe;exports.fetchf=he;exports.fetchff=he;exports.generateCacheKey=Z;exports.getCache=ye;exports.getCachedResponse=Pe;exports.getDefaultConfig=et;exports.getInFlightPromise=be;exports.isSlowConnection=Ee;exports.mutate=Ie;exports.removeRevalidators=gt;exports.revalidate=me;exports.revalidateAll=Ye;exports.setCache=Re;exports.setDefaultConfig=Ct;exports.setEventProvider=ht;exports.subscribe=xt;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 79492edf..04fcc736 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","revalidateAll","type","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/browser/index.mjs b/dist/browser/index.mjs index 4a9c89dc..3a35509e 100644 --- a/dist/browser/index.mjs +++ b/dist/browser/index.mjs @@ -1,3 +1,3 @@ -var mt=Object.defineProperty;var pt=(e,t,r)=>t in e?mt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var L=(e,t,r)=>pt(e,typeof t!="symbol"?t+"":t,r);var C="application/",j=C+"json",ve="charset=utf-8",w="Content-Type",R="undefined",K="object",E="string",g="function",ee="AbortError",Ne="TimeoutError",S="GET",_e="HEAD",te="reject";var He=10;function re(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===K}function J(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(c)+"="+a(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function ae(e){return e.includes("://")}var P=()=>Date.now(),v=()=>{};function De(e){let t=typeof e;return e==null?false:t===E||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||re(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function Te(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?Te(e.data,t+1):e}function ne(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a]=r;});else if(d(e))for(let[r,a]of Object.entries(e))t[r.toLowerCase()]=a;return t}function se(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var be=()=>{if(!se())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;L(this,"status");L(this,"statusText");L(this,"config");L(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,z=1e3,dt=ce*z,Ee=Array(ce).fill(0).map(()=>[]),A=new Map,le=0,x=null,Ke=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(v);}catch(r){}},I=(e,t,r)=>{if(_(e),rdt||r%z!==0){A.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let a=r/z,n=(le+a)%ce;Ee[n].push([e,t]),A.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Ee[le];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ze(e,oe(t+" aborted due to timeout",Ne));},r),i}async function ze(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),B.delete(e);}function ke(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function xe(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&ht(a);});}function Ge(e){if(!se()||me.has(e))return;let t=We.bind(null,e,true);me.set(e,t),window.addEventListener(e,t);}function Pt(e){if(!se())return;let t=me.get(e);t&&(window.removeEventListener(e,t),me.delete(e));}function Ye(e,t,r,a,n,s,o){G.set(e,[t,P(),yt,a,n,s,o]),s&&Ge("focus"),o&&Ge("online"),a&&I("s:"+e,pe.bind(null,e,true),a*1e3);}function ht(e){G.delete(e),_("s:"+e);}var W=new Map;function gt(e){let t=W.get(e);return t||(t=new Set,W.set(e,t)),t}function Dt(e,t){gt(e).add(t);}function Tt(e,t){let r=W.get(e);r&&(r.delete(t),r.size===0&&W.delete(e));}function U(e,t){let r=W.get(e);if(r)if(r.size===1){let a=r.values().next().value;a(t);}else r.forEach(a=>a(t));}function bt(e,t){return e?(Dt(e,t),()=>{Tt(e,t);}):v}var Ce=(be()?60:30)*1e3,H={strategy:te,timeout:Ce,headers:{Accept:j+", 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 Et(e){let t=J(e);return Object.assign(H,t),H}function Ve(){return {...H}}function qe(e,t){if(!t)return $e(e,Ve());let r=J(t),a=Y(H,r);return $e(e,a)}function $e(e,t){var i;let r=t.method;r=r?r.toUpperCase():S;let a;r!==S&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==E&&De(a)&&(a=JSON.stringify(a))),xt(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=n,t.body=a,t}function xt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(re(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(De(t))r=j+";"+ve;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function Y(e,t){let r=Object.assign({},e,t);return Ze("retry",r,e,t),Ze("headers",r,e,t),we("onRequest",r,e,t),we("onResponse",r,e,t),we("onError",r,e,t),r}function we(e,t,r,a){let n=r[e],s=a[e];if(!n&&!s)return;if(!n){t[e]=s;return}if(!s){t[e]=n;return}let o=Array.isArray(n)?n:[n],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Ze(e,t,r,a){a[e]&&(t[e]={...r[e],...a[e]});}var ye=new Map,F="|",Ae=64,Xe=/[^\w\-_|/:@.?=&~%#]/g,et=/[^\w\-_|/:@.?=&~%#]/,Ct=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 $(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===E?r:r(e);let{url:a="",method:n=S,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=ne(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>Ae&&(i=k(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Me(o)):String(o);i=l.length>Ae?k(l):l;}let m=n+F+a+F+u+F+c+F+i;return et.test(m)?m.replace(Xe,""):m}function tt(e){return e.expiry?P()>e.expiry:false}function wt(e){return e.stale?P()>e.stale:false}function Re(e){return ye.get(e)}function Pe(e,t,r,a){if(r===0){de(e);return}let n=P(),s=r?r*1e3:0,o=a?a*1e3:0;ye.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&I("c:"+e,()=>{de(e,true);},s);}function de(e,t=false){if(t){let r=Re(e);if(!r||!tt(r))return}ye.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=Re(e);if(!a)return null;let n=d(t)?J(t):t,s={...a.data,data:n},o={...a,data:s};return ye.set(e,o),U(e,s),r&&r.refetch?await pe(e):null}function he(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||H.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=Re(e);if(!n)return null;let s=tt(n),o=wt(n);return s?(de(e),null):!o||o&&!s?n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Pe(a,e,n,t.staleTime),U(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function rt(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(j)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===E){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===K&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=Te(u)),t.select&&(e.data=u=t.select(u));let c=ne(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function at(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function qt(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 u=at(r);if(u!==null)return u}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?at(s):null}async function nt(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=a,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=$(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await N(t);return o}async function ot(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await q(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&It(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===te)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function it(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===ee;}function It(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe={isFetching:true};async function ge(e,t=null){let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||a||o||p||n||i||m),f=null;if(h&&(f=$(r)),f&&p){let T=he(f,u,r);if(T)return T}if(f&&o){let T=xe(f,o);if(T)return T}let D=r.retry||{},{retries:ut=0,resetTimeout:lt}=D,Qe=async(T=false,V=0)=>{V||(f&&!T&&(c?he(f,u,r)||(Pe(f,Oe,u,c),U(f,Oe)):U(f,Oe)),r.cacheKey=f);let O=r.url,ft=Je(f,O,a,o||0,!!n,!!(a&&(!V||lt))),b=r;b.signal=ft.signal;let X,y=null;try{r.onRequest&&(f&&o&&!V&&await null,await q(r.onRequest,b));let Q=r.fetcher;if(y=Q?await Q(O,b):await fetch(O,b),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await rt(y):Q&&("data"in y&&"body"in y||(y={data:y})),y.config=b,y.ok!==void 0&&!y.ok))throw new ue(`${b.method} to ${O} failed! Status: ${y.status||null}`,b,y);X=Fe(y,b);let M=r.onResponse;M&&await q(M,X);}catch(Q){let M=Q;it(M,y,b),X=Fe(y,b,M);}return X},ct=ut>0?(T=false)=>nt((V,O)=>Qe(T,O),D):Qe,Z=(T=false)=>ot(T,ct,r),Se=l?st(Z,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):Z();return f&&(o&&ke(f,Se),Ye(f,Z,void 0,c,Z,!!i,!!m)),Se}function Bt(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=t[n],u=o||{url:String(n)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?(o==null?void 0:o.url)===c?Y(u,s):s:Y(Y(e,u),s);return ge(c,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} -export{ze as abortRequest,I as addTimeout,qe as buildConfig,oe as createAbortError,Bt as createApiFetcher,de as deleteCache,ge as fetchf,ge as fetchff,$ as generateCacheKey,Re as getCache,he as getCachedResponse,Ve as getDefaultConfig,xe as getInFlightPromise,be as isSlowConnection,Ie as mutate,Rt as removeRevalidators,pe as revalidate,We as revalidateAll,Pe as setCache,Et as setDefaultConfig,bt as subscribe};//# sourceMappingURL=index.mjs.map +var dt=Object.defineProperty;var yt=(e,t,r)=>t in e?dt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var j=(e,t,r)=>yt(e,typeof t!="symbol"?t+"":t,r);var C="application/",K=C+"json",Se="charset=utf-8",w="Content-Type",R="undefined",J="object",b="string",g="function",te="AbortError",Ne="TimeoutError",Q="GET",_e="HEAD",re="reject";var He=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===J}function z(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function ae(e){return e.includes("://")}var P=()=>Date.now(),S=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function se(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n]=r;});else if(d(e))for(let[r,n]of Object.entries(e))t[r.toLowerCase()]=n;return t}function Ke(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var ie=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;j(this,"status");j(this,"statusText");j(this,"config");j(this,"isCancelled");this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var ce=600,k=1e3,Rt=ce*k,Te=Array(ce).fill(0).map(()=>[]),A=new Map,le=0,x=null,Je=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(S);}catch(r){}},I=(e,t,r)=>{if(_(e),rRt||r%k!==0){A.set(e,[setTimeout(Je.bind(null,[e,t]),r)]);return}let n=r/k,a=(le+n)%ce;Te[a].push([e,t]),A.set(e,a),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Te[le];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function ze(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ke(e,oe(t+" aborted due to timeout",Ne));},r),i}async function ke(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),B.delete(e);}function Ge(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function be(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&Dt(n);});}function xe(e){if(U.has(e))return;let t=Ye.bind(null,e,true),r=We.get(e);if(r){let n=r(t);U.set(e,n);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function $e(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ze(e,t,r,n,a,s,o){W.set(e,[t,P(),Pt,n,a,s,o]),s&&xe("focus"),o&&xe("online"),n&&I("s:"+e,me.bind(null,e,true),n*1e3);}function Dt(e){W.delete(e),_("s:"+e);}var Y=new Map;function Et(e){let t=Y.get(e);return t||(t=new Set,Y.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=Y.get(e);r&&(r.delete(t),r.size===0&&Y.delete(e));}function H(e,t){let r=Y.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function xt(e,t){return e?(Tt(e,t),()=>{bt(e,t);}):S}var Ce=(Ee()?60:30)*1e3,M={strategy:re,timeout:Ce,headers:{Accept:K+", 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 Ct(e){let t=z(e);return Object.assign(M,t),M}function et(){return {...M}}function qe(e,t){if(!t)return Ve(e,et());let r=z(t),n=$(M,r);return Ve(e,n)}function Ve(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let n;r!==Q&&r!==_e&&(n=(i=t.body)!=null?i:t.data,n&&typeof n!==b&&ge(n)&&(n=JSON.stringify(n))),wt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function wt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(ge(t))r=K+";"+Se;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function $(e,t){let r=Object.assign({},e,t);return Xe("retry",r,e,t),Xe("headers",r,e,t),we("onRequest",r,e,t),we("onResponse",r,e,t),we("onError",r,e,t),r}function we(e,t,r,n){let a=r[e],s=n[e];if(!a&&!s)return;if(!a){t[e]=s;return}if(!s){t[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Xe(e,t,r,n){n[e]&&(t[e]={...r[e],...n[e]});}var de=new Map,F="|",Ae=64,tt=/[^\w\-_|/:@.?=&~%#]/g,rt=/[^\w\-_|/:@.?=&~%#]/,qt=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 Z(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:n="",method:a=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=se(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>Ae&&(i=G(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Me(o)):String(o);i=l.length>Ae?G(l):l;}let m=a+F+n+F+u+F+c+F+i;return rt.test(m)?m.replace(tt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function At(e){return e.stale?P()>e.stale:false}function ye(e){return de.get(e)}function Re(e,t,r,n){if(r===0){pe(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;de.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&I("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!nt(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let n=ye(e);if(!n)return null;let a=d(t)?z(t):t,s={...n.data,data:a},o={...n,data:s};return de.set(e,o),H(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||M.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=ye(e);if(!a)return null;let s=nt(a),o=At(a);return s?(pe(e),null):!o||o&&!s?a.data:null}function Be(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(n,e,a,t.staleTime),H(n,e),fe(n);let o=t._prevKey;o&&fe(o);}}async function at(e){var a;if(!e)return null;let t=(a=e.headers)==null?void 0:a.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(K)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===b){let s=n.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{n=JSON.parse(s);}catch(o){}}}catch(s){n=null;}return n}var Fe=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ie.bind(null,a);if(!e)return {ok:false,error:r,data:n!=null?n:null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===J&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let c=se(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function st(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function It(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 u=st(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?st(s):null}async function ot(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Z(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await N(t);return o}async function ut(e,t,r){let n=await t(e),a=n.error;if(!a)return Be(n,r),n;r.onError&&await q(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&Ft(r,"FETCH ERROR",a),Be(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===re)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function lt(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===te;}function Ft(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var ve={isFetching:true};async function he(e,t=null){let r=qe(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=Z(r)),f&&p){let E=Pe(f,u,r);if(E)return E}if(f&&o){let E=be(f,o);if(E)return E}let D=r.retry||{},{retries:ct=0,resetTimeout:ft}=D,Oe=async(E=false,X=0)=>{X||(f&&!E&&(c?Pe(f,u,r)||(Re(f,ve,u,c),H(f,ve)):H(f,ve)),r.cacheKey=f);let v=r.url,pt=ze(f,v,n,o||0,!!a,!!(n&&(!X||ft))),T=r;T.signal=pt.signal;let ee,y=null;try{r.onRequest&&(f&&o&&!X&&await null,await q(r.onRequest,T));let O=r.fetcher;if(y=O?await O(v,T):await fetch(v,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await at(y):O&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${v} failed! Status: ${y.status||null}`,T,y);ee=Fe(y,T);let L=r.onResponse;L&&await q(L,ee);}catch(O){let L=O;lt(L,y,T),ee=Fe(y,T,L);}return ee},mt=ct>0?(E=false)=>ot((X,v)=>Oe(E,v),D):Oe,V=(E=false)=>ut(E,mt,r),Qe=l?it(V,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):V();return f&&(o&&Ge(f,Qe),Ze(f,V,void 0,c,V,!!i,!!m)),Qe}function vt(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?(o==null?void 0:o.url)===c?$(u,s):s:$($(e,u),s);return he(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} +export{ke as abortRequest,I as addTimeout,qe as buildConfig,oe as createAbortError,vt as createApiFetcher,pe as deleteCache,he as fetchf,he as fetchff,Z as generateCacheKey,ye as getCache,Pe as getCachedResponse,et as getDefaultConfig,be as getInFlightPromise,Ee as isSlowConnection,Ie as mutate,gt as removeRevalidators,me as revalidate,Ye as revalidateAll,Re as setCache,Ct as setDefaultConfig,ht as setEventProvider,xt 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 069cf1c9..6aa953a2 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","revalidateAll","type","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/node/index.js b/dist/node/index.js index de261e22..07050136 100644 --- a/dist/node/index.js +++ b/dist/node/index.js @@ -1,3 +1,3 @@ -'use strict';var C="application/",L=C+"json",Se="charset=utf-8",w="Content-Type",R="undefined",j="object",E="string",g="function",X="AbortError",ve="TimeoutError",S="GET",Ne="HEAD",ee="reject";var Ue=10;function te(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===j}function K(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function He(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=Ue)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function re(e){return e.includes("://")}var P=()=>Date.now(),v=()=>{};function ge(e){let t=typeof e;return e==null?false:t===E||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||te(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function ne(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n]=r;});else if(d(e))for(let[r,n]of Object.entries(e))t[r.toLowerCase()]=n;return t}function ae(){return typeof window!==R&&typeof window.addEventListener===g}function se(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Te=()=>{if(!ae())return false;let e=navigator&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var oe=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}status;statusText;config;isCancelled};var ie=class extends oe{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var le=600,J=1e3,ft=le*J,be=Array(le).fill(0).map(()=>[]),A=new Map,ue=0,x=null,je=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(v);}catch{}},I=(e,t,r)=>{if(_(e),rft||r%J!==0){A.set(e,[setTimeout(je.bind(null,[e,t]),r)]);return}let n=r/J,a=(ue+n)%le;be[a].push([e,t]),A.set(e,a),x||(x=setInterval(()=>{ue=(ue+1)%le;let s=be[ue];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=be[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function Ke(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{Je(e,se(t+" aborted due to timeout",ve));},r),i}async function Je(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),ce(e));}}function ce(e){_(e),B.delete(e);}function ze(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function Ee(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&yt(n);});}function ke(e){if(!ae()||fe.has(e))return;let t=Ge.bind(null,e,true);fe.set(e,t),window.addEventListener(e,t);}function dt(e){if(!ae())return;let t=fe.get(e);t&&(window.removeEventListener(e,t),fe.delete(e));}function We(e,t,r,n,a,s,o){k.set(e,[t,P(),mt,n,a,s,o]),s&&ke("focus"),o&&ke("online"),n&&I("s:"+e,me.bind(null,e,true),n*1e3);}function yt(e){k.delete(e),_("s:"+e);}var G=new Map;function Rt(e){let t=G.get(e);return t||(t=new Set,G.set(e,t)),t}function Pt(e,t){Rt(e).add(t);}function ht(e,t){let r=G.get(e);r&&(r.delete(t),r.size===0&&G.delete(e));}function U(e,t){let r=G.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function gt(e,t){return e?(Pt(e,t),()=>{ht(e,t);}):v}var xe=(Te()?60:30)*1e3,H={strategy:ee,timeout:xe,headers:{Accept:L+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:xe/30,maxDelay:xe,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Dt(e){let t=K(e);return Object.assign(H,t),H}function Ze(){return {...H}}function we(e,t){if(!t)return Ye(e,Ze());let r=K(t),n=W(H,r);return Ye(e,n)}function Ye(e,t){let r=t.method;r=r?r.toUpperCase():S;let n;r!==S&&r!==Ne&&(n=t.body??t.data,n&&typeof n!==E&&ge(n)&&(n=JSON.stringify(n))),Tt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),c=re(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function Tt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(te(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(ge(t))r=L+";"+Se;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function W(e,t){let r=Object.assign({},e,t);return $e("retry",r,e,t),$e("headers",r,e,t),Ce("onRequest",r,e,t),Ce("onResponse",r,e,t),Ce("onError",r,e,t),r}function Ce(e,t,r,n){let a=r[e],s=n[e];if(!a&&!s)return;if(!a){t[e]=s;return}if(!s){t[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function $e(e,t,r,n){n[e]&&(t[e]={...r[e],...n[e]});}var de=new Map,F="|",qe=64,Ve=/[^\w\-_|/:@.?=&~%#]/g,Xe=/[^\w\-_|/:@.?=&~%#]/,bt=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 Y(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===E?r:r(e);let{url:n="",method:a=S,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=ne(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>qe&&(i=z(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(He(o)):String(o);i=l.length>qe?z(l):l;}let m=a+F+n+F+u+F+c+F+i;return Xe.test(m)?m.replace(Ve,""):m}function et(e){return e.expiry?P()>e.expiry:false}function Et(e){return e.stale?P()>e.stale:false}function ye(e){return de.get(e)}function Re(e,t,r,n){if(r===0){pe(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;de.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&I("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!et(r))return}de.delete(e);}async function Ae(e,t,r){if(!e)return null;let n=ye(e);if(!n)return null;let a=d(t)?K(t):t,s={...n.data,data:a},o={...n,data:s};return de.set(e,o),U(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||H.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=ye(e);if(!a)return null;let s=et(a),o=Et(a);return s?(pe(e),null):!o||o&&!s?a.data:null}function Ie(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(n,e,a,t.staleTime),U(n,e),ce(n);let o=t._prevKey;o&&ce(o);}}async function tt(e){if(!e)return null;let t=e.headers?.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(L)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===E){let a=n.trim();if(a.startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]"))try{n=JSON.parse(a);}catch{}}}catch{n=null;}return n}var Be=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ae.bind(null,a);if(!e)return {ok:false,error:r,data:n??null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===j&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let c=ne(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function rt(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function xt(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 u=rt(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?rt(s):null}async function nt(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Y(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await N(t);return o}async function st(e,t,r){let n=await t(e),a=n.error;if(!a)return Ie(n,r),n;r.onError&&await q(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&wt(r,"FETCH ERROR",a),Ie(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ee)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function ot(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===X;}function wt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Fe={isFetching:true};async function he(e,t=null){let r=we(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=Y(r)),f&&p){let T=Pe(f,u,r);if(T)return T}if(f&&o){let T=Ee(f,o);if(T)return T}let D=r.retry||{},{retries:it=0,resetTimeout:ut}=D,Oe=async(T=false,Z=0)=>{Z||(f&&!T&&(c?Pe(f,u,r)||(Re(f,Fe,u,c),U(f,Fe)):U(f,Fe)),r.cacheKey=f);let O=r.url,ct=Ke(f,O,n,o||0,!!a,!!(n&&(!Z||ut))),b=r;b.signal=ct.signal;let V,y=null;try{r.onRequest&&(f&&o&&!Z&&await null,await q(r.onRequest,b));let Q=r.fetcher;if(y=Q?await Q(O,b):await fetch(O,b),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await tt(y):Q&&("data"in y&&"body"in y||(y={data:y})),y.config=b,y.ok!==void 0&&!y.ok))throw new ie(`${b.method} to ${O} failed! Status: ${y.status||null}`,b,y);V=Be(y,b);let M=r.onResponse;M&&await q(M,V);}catch(Q){let M=Q;ot(M,y,b),V=Be(y,b,M);}return V},lt=it>0?(T=false)=>nt((Z,O)=>Oe(T,O),D):Oe,$=(T=false)=>st(T,lt,r),Qe=l?at($,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):$();return f&&(o&&ze(f,Qe),We(f,$,void 0,c,$,!!i,!!m)),Qe}function qt(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=re(c)?o?.url===c?W(u,s):s:W(W(e,u),s);return he(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=Je;exports.addTimeout=I;exports.buildConfig=we;exports.createAbortError=se;exports.createApiFetcher=qt;exports.deleteCache=pe;exports.fetchf=he;exports.fetchff=he;exports.generateCacheKey=Y;exports.getCache=ye;exports.getCachedResponse=Pe;exports.getDefaultConfig=Ze;exports.getInFlightPromise=Ee;exports.isSlowConnection=Te;exports.mutate=Ae;exports.removeRevalidators=pt;exports.revalidate=me;exports.revalidateAll=Ge;exports.setCache=Re;exports.setDefaultConfig=Dt;exports.subscribe=gt;//# sourceMappingURL=index.js.map +'use strict';var C="application/",j=C+"json",Qe="charset=utf-8",w="Content-Type",R="undefined",K="object",b="string",g="function",ee="AbortError",Se="TimeoutError",Q="GET",Ne="HEAD",te="reject";var Ue=10;function re(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===K}function J(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function He(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=Ue)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function ne(e){return e.includes("://")}var P=()=>Date.now(),S=()=>{};function he(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||re(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function ge(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==R?ge(e.data,t+1):e}function ae(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n]=r;});else if(d(e))for(let[r,n]of Object.entries(e))t[r.toLowerCase()]=n;return t}function je(){return typeof window!==R&&typeof window.addEventListener===g}function se(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var De=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var oe=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}status;statusText;config;isCancelled};var ie=class extends oe{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var le=600,z=1e3,pt=le*z,Ee=Array(le).fill(0).map(()=>[]),A=new Map,ue=0,x=null,Ke=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(S);}catch{}},I=(e,t,r)=>{if(_(e),rpt||r%z!==0){A.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let n=r/z,a=(ue+n)%le;Ee[a].push([e,t]),A.set(e,a),x||(x=setInterval(()=>{ue=(ue+1)%le;let s=Ee[ue];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function Je(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ze(e,se(t+" aborted due to timeout",Se));},r),i}async function ze(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),ce(e));}}function ce(e){_(e),B.delete(e);}function ke(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function Te(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&Pt(n);});}function be(e){if(U.has(e))return;let t=We.bind(null,e,true),r=Ge.get(e);if(r){let n=r(t);U.set(e,n);return}je()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function Ye(e){let t=U.get(e);t&&(t(),U.delete(e));}function $e(e,t,r,n,a,s,o){G.set(e,[t,P(),dt,n,a,s,o]),s&&be("focus"),o&&be("online"),n&&I("s:"+e,fe.bind(null,e,true),n*1e3);}function Pt(e){G.delete(e),_("s:"+e);}var W=new Map;function ht(e){let t=W.get(e);return t||(t=new Set,W.set(e,t)),t}function gt(e,t){ht(e).add(t);}function Dt(e,t){let r=W.get(e);r&&(r.delete(t),r.size===0&&W.delete(e));}function H(e,t){let r=W.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function Et(e,t){return e?(gt(e,t),()=>{Dt(e,t);}):S}var xe=(De()?60:30)*1e3,M={strategy:te,timeout:xe,headers:{Accept:j+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:xe/30,maxDelay:xe,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Tt(e){let t=J(e);return Object.assign(M,t),M}function Xe(){return {...M}}function we(e,t){if(!t)return Ze(e,Xe());let r=J(t),n=Y(M,r);return Ze(e,n)}function Ze(e,t){let r=t.method;r=r?r.toUpperCase():Q;let n;r!==Q&&r!==Ne&&(n=t.body??t.data,n&&typeof n!==b&&he(n)&&(n=JSON.stringify(n))),bt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),c=ne(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function bt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(re(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(he(t))r=j+";"+Qe;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function Y(e,t){let r=Object.assign({},e,t);return Ve("retry",r,e,t),Ve("headers",r,e,t),Ce("onRequest",r,e,t),Ce("onResponse",r,e,t),Ce("onError",r,e,t),r}function Ce(e,t,r,n){let a=r[e],s=n[e];if(!a&&!s)return;if(!a){t[e]=s;return}if(!s){t[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Ve(e,t,r,n){n[e]&&(t[e]={...r[e],...n[e]});}var pe=new Map,F="|",qe=64,et=/[^\w\-_|/:@.?=&~%#]/g,tt=/[^\w\-_|/:@.?=&~%#]/,xt=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 $(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:n="",method:a=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=ae(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>qe&&(i=k(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(He(o)):String(o);i=l.length>qe?k(l):l;}let m=a+F+n+F+u+F+c+F+i;return tt.test(m)?m.replace(et,""):m}function rt(e){return e.expiry?P()>e.expiry:false}function Ct(e){return e.stale?P()>e.stale:false}function de(e){return pe.get(e)}function ye(e,t,r,n){if(r===0){me(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;pe.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&I("c:"+e,()=>{me(e,true);},s);}function me(e,t=false){if(t){let r=de(e);if(!r||!rt(r))return}pe.delete(e);}async function Ae(e,t,r){if(!e)return null;let n=de(e);if(!n)return null;let a=d(t)?J(t):t,s={...n.data,data:a},o={...n,data:s};return pe.set(e,o),H(e,s),r&&r.refetch?await fe(e):null}function Re(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||M.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=de(e);if(!a)return null;let s=rt(a),o=Ct(a);return s?(me(e),null):!o||o&&!s?a.data:null}function Ie(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&ye(n,e,a,t.staleTime),H(n,e),ce(n);let o=t._prevKey;o&&ce(o);}}async function nt(e){if(!e)return null;let t=e.headers?.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(j)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===b){let a=n.trim();if(a.startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]"))try{n=JSON.parse(a);}catch{}}}catch{n=null;}return n}var Be=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ae.bind(null,a);if(!e)return {ok:false,error:r,data:n??null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===K&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=ge(u)),t.select&&(e.data=u=t.select(u));let c=ae(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function at(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function wt(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 u=at(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?at(s):null}async function st(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=$(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await N(t);return o}async function it(e,t,r){let n=await t(e),a=n.error;if(!a)return Ie(n,r),n;r.onError&&await q(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&At(r,"FETCH ERROR",a),Ie(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===te)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function ut(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===ee;}function At(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Fe={isFetching:true};async function Pe(e,t=null){let r=we(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=$(r)),f&&p){let E=Re(f,u,r);if(E)return E}if(f&&o){let E=Te(f,o);if(E)return E}let D=r.retry||{},{retries:lt=0,resetTimeout:ct}=D,ve=async(E=false,V=0)=>{V||(f&&!E&&(c?Re(f,u,r)||(ye(f,Fe,u,c),H(f,Fe)):H(f,Fe)),r.cacheKey=f);let v=r.url,mt=Je(f,v,n,o||0,!!a,!!(n&&(!V||ct))),T=r;T.signal=mt.signal;let X,y=null;try{r.onRequest&&(f&&o&&!V&&await null,await q(r.onRequest,T));let O=r.fetcher;if(y=O?await O(v,T):await fetch(v,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await nt(y):O&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ie(`${T.method} to ${v} failed! Status: ${y.status||null}`,T,y);X=Be(y,T);let L=r.onResponse;L&&await q(L,X);}catch(O){let L=O;ut(L,y,T),X=Be(y,T,L);}return X},ft=lt>0?(E=false)=>st((V,v)=>ve(E,v),D):ve,Z=(E=false)=>it(E,ft,r),Oe=l?ot(Z,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):Z();return f&&(o&&ke(f,Oe),$e(f,Z,void 0,c,Z,!!i,!!m)),Oe}function It(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ne(c)?o?.url===c?Y(u,s):s:Y(Y(e,u),s);return Pe(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} +exports.abortRequest=ze;exports.addTimeout=I;exports.buildConfig=we;exports.createAbortError=se;exports.createApiFetcher=It;exports.deleteCache=me;exports.fetchf=Pe;exports.fetchff=Pe;exports.generateCacheKey=$;exports.getCache=de;exports.getCachedResponse=Re;exports.getDefaultConfig=Xe;exports.getInFlightPromise=Te;exports.isSlowConnection=De;exports.mutate=Ae;exports.removeRevalidators=Rt;exports.revalidate=fe;exports.revalidateAll=We;exports.setCache=ye;exports.setDefaultConfig=Tt;exports.setEventProvider=yt;exports.subscribe=Et;//# 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 dfc2ed66..35681b0f 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","revalidateAll","type","isStaleRevalidation","flagIndex","entry","revalidator","revalidate","removeRevalidators","removeEventHandler","removeRevalidator","addEventHandler","event","handler","addRevalidator","revalidatorFn","ttl","staleTime","bgRevalidatorFn","refetchOnFocus","refetchOnReconnect","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","_error","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 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 // Only works in browser environments\n if (!isBrowser()) {\n return false;\n }\n\n const conn = navigator && (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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 global event handlers for cache revalidation events (e.g., focus, online).\n * This avoids attaching multiple event listeners by maintaining a single handler per event type.\n * Event handlers are registered as needed when revalidators are registered with the corresponding flags.\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/**\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 * Ensures the handler is only added once and only in browser environments.\n *\n * @param event - The type of event to listen for (e.g., 'focus', 'visibilitychange').\n */\nfunction addEventHandler(event: EventType) {\n if (!isBrowser() || eventHandlers.has(event)) {\n return;\n }\n\n const handler = revalidateAll.bind(null, event, true);\n\n eventHandlers.set(event, handler);\n window.addEventListener(event, handler);\n}\n\n/**\n * Removes the generic event handler for the specified event type from the window object.\n *\n * @param event - The type of event whose handler should be removed.\n */\nfunction removeEventHandler(event: EventType) {\n if (!isBrowser()) {\n return;\n }\n\n const handler = eventHandlers.get(event);\n\n if (handler) {\n window.removeEventListener(event, handler);\n\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","_error","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file From 8f5a389b0cb8c5590d69bcb520eb83012416cd64 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 8 Feb 2026 05:10:59 +0100 Subject: [PATCH 19/30] fix: freeze inFlightResponse object and conditionally register revalidator --- src/request-handler.ts | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/request-handler.ts b/src/request-handler.ts index 876fdfad..2ce0db3f 100644 --- a/src/request-handler.ts +++ b/src/request-handler.ts @@ -26,9 +26,9 @@ import { enhanceError, withErrorHandling } from './error-handler'; import { FUNCTION } from './constants'; import { buildConfig } from './config-handler'; -const inFlightResponse = { +const inFlightResponse = Object.freeze({ isFetching: true, -}; +}); /** * Sends an HTTP request to the specified URL using the provided configuration and returns a typed response. @@ -331,15 +331,18 @@ export async function fetchf< setInFlightPromise(_cacheKey, doRequestPromise); } - addRevalidator( - _cacheKey, - requestWithErrorHandling, - undefined, - staleTime, - requestWithErrorHandling, - !!refetchOnFocus, - !!refetchOnReconnect, - ); + // Only register revalidator when revalidation features are actually requested + if (staleTime || refetchOnFocus || refetchOnReconnect) { + addRevalidator( + _cacheKey, + requestWithErrorHandling, + undefined, + staleTime, + requestWithErrorHandling, + !!refetchOnFocus, + !!refetchOnReconnect, + ); + } } return doRequestPromise; From bcd1fda310e28b6b502c1c786846a621479d4605 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 9 Feb 2026 00:53:49 +0100 Subject: [PATCH 20/30] perf: simplify promise storage logic in setInFlightPromise function --- src/inflight-manager.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/inflight-manager.ts b/src/inflight-manager.ts index 8015704a..4f5744ac 100644 --- a/src/inflight-manager.ts +++ b/src/inflight-manager.ts @@ -174,10 +174,8 @@ export function setInFlightPromise( ): void { const item = inFlight.get(key); if (item) { - // store the promise at index 4 + // store the promise at index 4 — item is already the Map's reference, no need to re-set item[4] = promise; - - inFlight.set(key, item); } } From 12172112e1d45d26bc84b83f88ae4d6e25ffeb62 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 9 Feb 2026 23:15:17 +0100 Subject: [PATCH 21/30] =?UTF-8?q?perf:=20remove=20redundant=20=E2=80=9Csta?= =?UTF-8?q?le=E2=80=9D=20check=20for=20cache=20reads=20as=20it's=20handled?= =?UTF-8?q?=20by=20timer=20yielded=20revalidator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cache-manager.ts | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/src/cache-manager.ts b/src/cache-manager.ts index adc47dc9..1942b1e4 100644 --- a/src/cache-manager.ts +++ b/src/cache-manager.ts @@ -223,20 +223,6 @@ function isCacheExpired(entry: CacheEntry): boolean { return timeNow() > entry.expiry; } -/** - * Checks if the cache entry is stale based on its timestamp and the stale time. - * - * @param {CacheEntry} entry - The cache entry to check. - * @returns {boolean} - Returns true if the cache entry is stale, false otherwise. - */ -function isCacheStale(entry: CacheEntry): boolean { - if (!entry.stale) { - return false; - } - - return timeNow() > entry.stale; -} - /** * Retrieves a cached response from the internal cache using the provided key. * @@ -453,7 +439,6 @@ export function getCachedResponse< } const isExpired = isCacheExpired(entry); - const isStale = isCacheStale(entry); // If completely expired, delete and return null if (isExpired) { @@ -461,19 +446,8 @@ export function getCachedResponse< return null; } - // If fresh (not stale), return immediately - if (!isStale) { - return entry.data; - } - - // SWR: Data is stale but not expired - if (isStale && !isExpired) { - // Triggering background revalidation here could cause race conditions - // So we return stale data immediately and leave it up to implementers to handle revalidation - return entry.data; - } - - return null; + // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven) + return entry.data; } /** From 0c5eccd9711cfe7d07f0342b4f2a13223803782d Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 9 Feb 2026 23:37:00 +0100 Subject: [PATCH 22/30] perf: update existing revalidator entries in-place for improved memory and performance --- src/revalidator-manager.ts | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/revalidator-manager.ts b/src/revalidator-manager.ts index ff9332c6..a5cb8f72 100644 --- a/src/revalidator-manager.ts +++ b/src/revalidator-manager.ts @@ -224,15 +224,28 @@ export function addRevalidator( refetchOnFocus?: boolean, refetchOnReconnect?: boolean, ) { - revalidators.set(key, [ - revalidatorFn, - timeNow(), - ttl ?? DEFAULT_TTL, - staleTime, - bgRevalidatorFn, - refetchOnFocus, - refetchOnReconnect, - ]); + const existing = revalidators.get(key); + + if (existing) { + // Update in-place to avoid allocating a new tuple array + existing[0] = revalidatorFn; + existing[1] = timeNow(); + existing[2] = ttl ?? DEFAULT_TTL; + existing[3] = staleTime; + existing[4] = bgRevalidatorFn; + existing[5] = refetchOnFocus; + existing[6] = refetchOnReconnect; + } else { + revalidators.set(key, [ + revalidatorFn, + timeNow(), + ttl ?? DEFAULT_TTL, + staleTime, + bgRevalidatorFn, + refetchOnFocus, + refetchOnReconnect, + ]); + } if (refetchOnFocus) { addEventHandler('focus'); From 7303a8033b6dfd65a343fde7b31639608ab42ccd Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Feb 2026 00:37:31 +0100 Subject: [PATCH 23/30] refactor: improve config merging logic in setDefaultConfig and mergeConfigs functions --- src/config-handler.ts | 46 +++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/config-handler.ts b/src/config-handler.ts index f2534cdd..baa920c0 100644 --- a/src/config-handler.ts +++ b/src/config-handler.ts @@ -65,9 +65,7 @@ export function setDefaultConfig( ): Partial { const sanitized = sanitizeObject(customConfig); - Object.assign(defaultConfig, sanitized); - - return defaultConfig; + return mergeConfigs({}, sanitized, defaultConfig); } /** @@ -208,26 +206,40 @@ function setContentTypeIfNeeded( } } +/** + * Merges two request configurations, applying overrides from the second config to the first. + * Handles special merging for nested properties like 'retry' and 'headers' (deep merge), + * and concatenates interceptor arrays for 'onRequest', 'onResponse', and 'onError'. + * If a target config is provided, it mutates that object; otherwise, creates a new one. + * + * @param {RequestConfig} baseConfig - The base configuration object to merge from. + * @param {RequestConfig} overrideConfig - The override configuration object to apply on top of the base. + * @param {RequestConfig} [targetConfig={}] - Optional target configuration object to merge into (mutated in place). + * @returns {RequestConfig} The merged configuration object. + * + * @example + * const base = { timeout: 5000, headers: { 'Accept': 'application/json' } }; + * const override = { timeout: 10000, headers: { 'Authorization': 'Bearer token' } }; + * const merged = mergeConfigs(base, override); + * // Result: { timeout: 10000, headers: { Accept: 'application/json', Authorization: 'Bearer token' } } + */ export function mergeConfigs( baseConfig: RequestConfig, overrideConfig: RequestConfig, + targetConfig: RequestConfig = {}, ): RequestConfig { - const mergedConfig: RequestConfig = Object.assign( - {}, - baseConfig, - overrideConfig, - ); + Object.assign(targetConfig, baseConfig, overrideConfig); // Ensure that retry and headers are merged correctly - mergeConfig('retry', mergedConfig, baseConfig, overrideConfig); - mergeConfig('headers', mergedConfig, baseConfig, overrideConfig); + mergeConfig('retry', baseConfig, overrideConfig, targetConfig); + mergeConfig('headers', baseConfig, overrideConfig, targetConfig); // Merge interceptors efficiently - mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig); - mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig); - mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig); + mergeInterceptors('onRequest', baseConfig, overrideConfig, targetConfig); + mergeInterceptors('onResponse', baseConfig, overrideConfig, targetConfig); + mergeInterceptors('onError', baseConfig, overrideConfig, targetConfig); - return mergedConfig; + return targetConfig; } /** @@ -237,9 +249,9 @@ function mergeInterceptors< K extends 'onRequest' | 'onResponse' | 'onError' | 'onRetry', >( property: K, - targetConfig: RequestConfig, baseConfig: RequestConfig, overrideConfig: RequestConfig, + targetConfig: RequestConfig, ): void { const baseInterceptor = baseConfig[property]; const newInterceptor = overrideConfig[property]; @@ -274,15 +286,15 @@ function mergeInterceptors< * Merges the specified property from the base configuration and the override configuration into the target configuration. * * @param {K} property - The property key to merge from the base and override configurations. Must be a key of RequestConfig. - * @param {RequestConfig} targetConfig - The configuration object that will receive the merged properties. * @param {RequestConfig} baseConfig - The base configuration object that provides default values. * @param {RequestConfig} overrideConfig - The override configuration object that contains user-specific settings to merge. + * @param {RequestConfig} targetConfig - The configuration object that will receive the merged properties. */ export function mergeConfig( property: K, - targetConfig: RequestConfig, baseConfig: RequestConfig, overrideConfig: RequestConfig, + targetConfig: RequestConfig, ): void { if (overrideConfig[property]) { targetConfig[property] = { From 6d4c0fc72b950df009b37276aaa68aa3ccfa82c8 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Feb 2026 00:53:26 +0100 Subject: [PATCH 24/30] revert: convert revalidator and timeout iteration for improved clarity --- src/revalidator-manager.ts | 6 +++--- src/timeout-wheel.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/revalidator-manager.ts b/src/revalidator-manager.ts index a5cb8f72..ebab3c0d 100644 --- a/src/revalidator-manager.ts +++ b/src/revalidator-manager.ts @@ -88,9 +88,9 @@ export function revalidateAll( const flagIndex = type === 'focus' ? 5 : 6; const now = timeNow(); - for (const entry of revalidators.values()) { + revalidators.forEach((entry) => { if (!entry[flagIndex]) { - continue; + return; } entry[1] = now; @@ -101,7 +101,7 @@ export function revalidateAll( if (revalidator) { Promise.resolve(revalidator(isStaleRevalidation)).catch(noop); } - } + }); } /** diff --git a/src/timeout-wheel.ts b/src/timeout-wheel.ts index e1492afc..c94e9ded 100644 --- a/src/timeout-wheel.ts +++ b/src/timeout-wheel.ts @@ -119,11 +119,11 @@ export const removeTimeout = (key: string): void => { export const clearAllTimeouts = () => { // Clear native setTimeout timeouts first! - for (const value of keyMap.values()) { + keyMap.forEach((value) => { if (Array.isArray(value)) { clearTimeout(value[0]); } - } + }); if (timer) { clearInterval(timer); From 04abb0d571722f6e653cef1efcc8f15075baf59d Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Feb 2026 00:54:31 +0100 Subject: [PATCH 25/30] fix: normalize header keys to lowercase for compliance with RFC 2616 --- src/utils.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index cf8d459a..b64a59b2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -343,17 +343,18 @@ export function processHeaders( const headersObject: HeadersObject = {}; - // Handle Headers object with entries() method + // Normalize keys to lowercase as per RFC 2616 4.2 + // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2 if (headers instanceof Headers) { headers.forEach((value, key) => { - headersObject[key] = value; + headersObject[key.toLowerCase()] = value; }); } else if (isObject(headers)) { - // Handle plain object - for (const [key, value] of Object.entries(headers)) { - // Normalize keys to lowercase as per RFC 2616 4.2 - // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2 - headersObject[key.toLowerCase()] = value; + // Handle plain object — use for...in to avoid Object.entries() allocation + for (const key in headers) { + if (Object.prototype.hasOwnProperty.call(headers, key)) { + headersObject[key.toLowerCase()] = headers[key]; + } } } From b5d31cace11d5b25ceb5c15df88741b1d00f82f7 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Feb 2026 00:54:50 +0100 Subject: [PATCH 26/30] feat: enhance mergeConfig to handle Headers instances and normalize headers --- src/config-handler.ts | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/config-handler.ts b/src/config-handler.ts index baa920c0..89dad4ee 100644 --- a/src/config-handler.ts +++ b/src/config-handler.ts @@ -1,3 +1,4 @@ +import { processHeaders } from './utils'; import { GET, APPLICATION_JSON, @@ -297,9 +298,27 @@ export function mergeConfig( targetConfig: RequestConfig, ): void { if (overrideConfig[property]) { - targetConfig[property] = { - ...baseConfig[property], - ...overrideConfig[property], - }; + const base = baseConfig[property]; + const override = overrideConfig[property]; + + // Handle Headers instances which don't expose entries as own enumerable properties + if ( + property === 'headers' && + ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers || + (override as Headers | (HeadersObject & HeadersInit)) instanceof + Headers) + ) { + const baseNormalized = processHeaders(base); + const overrideNormalized = processHeaders(override); + targetConfig[property] = { + ...baseNormalized, + ...overrideNormalized, + } as RequestConfig[K]; + } else { + targetConfig[property] = { + ...base, + ...override, + }; + } } } From 5496dd43f62ea63663459ee7ee56b50dfcdbe0eb Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Feb 2026 01:05:03 +0100 Subject: [PATCH 27/30] chore: Build --- dist/browser/index.global.js | 4 ++-- dist/browser/index.global.js.map | 2 +- dist/browser/index.mjs | 4 ++-- dist/browser/index.mjs.map | 2 +- dist/node/index.js | 4 ++-- dist/node/index.js.map | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dist/browser/index.global.js b/dist/browser/index.global.js index b4ea3e05..430364d0 100644 --- a/dist/browser/index.global.js +++ b/dist/browser/index.global.js @@ -1,3 +1,3 @@ -var fetchff=(function(exports){'use strict';var dt=Object.defineProperty;var yt=(e,t,r)=>t in e?dt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var j=(e,t,r)=>yt(e,typeof t!="symbol"?t+"":t,r);var C="application/",K=C+"json",Se="charset=utf-8",w="Content-Type",R="undefined",J="object",b="string",g="function",te="AbortError",Ne="TimeoutError",Q="GET",_e="HEAD",re="reject";var He=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===J}function z(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function ae(e){return e.includes("://")}var P=()=>Date.now(),S=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function se(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n]=r;});else if(d(e))for(let[r,n]of Object.entries(e))t[r.toLowerCase()]=n;return t}function Ke(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var ie=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;j(this,"status");j(this,"statusText");j(this,"config");j(this,"isCancelled");this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var ce=600,k=1e3,Rt=ce*k,Te=Array(ce).fill(0).map(()=>[]),A=new Map,le=0,x=null,Je=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(S);}catch(r){}},I=(e,t,r)=>{if(_(e),rRt||r%k!==0){A.set(e,[setTimeout(Je.bind(null,[e,t]),r)]);return}let n=r/k,a=(le+n)%ce;Te[a].push([e,t]),A.set(e,a),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Te[le];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function ze(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ke(e,oe(t+" aborted due to timeout",Ne));},r),i}async function ke(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),B.delete(e);}function Ge(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function be(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&Dt(n);});}function xe(e){if(U.has(e))return;let t=Ye.bind(null,e,true),r=We.get(e);if(r){let n=r(t);U.set(e,n);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function $e(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ze(e,t,r,n,a,s,o){W.set(e,[t,P(),Pt,n,a,s,o]),s&&xe("focus"),o&&xe("online"),n&&I("s:"+e,me.bind(null,e,true),n*1e3);}function Dt(e){W.delete(e),_("s:"+e);}var Y=new Map;function Et(e){let t=Y.get(e);return t||(t=new Set,Y.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=Y.get(e);r&&(r.delete(t),r.size===0&&Y.delete(e));}function H(e,t){let r=Y.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function xt(e,t){return e?(Tt(e,t),()=>{bt(e,t);}):S}var Ce=(Ee()?60:30)*1e3,M={strategy:re,timeout:Ce,headers:{Accept:K+", 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 Ct(e){let t=z(e);return Object.assign(M,t),M}function et(){return {...M}}function qe(e,t){if(!t)return Ve(e,et());let r=z(t),n=$(M,r);return Ve(e,n)}function Ve(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let n;r!==Q&&r!==_e&&(n=(i=t.body)!=null?i:t.data,n&&typeof n!==b&&ge(n)&&(n=JSON.stringify(n))),wt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function wt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(ge(t))r=K+";"+Se;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function $(e,t){let r=Object.assign({},e,t);return Xe("retry",r,e,t),Xe("headers",r,e,t),we("onRequest",r,e,t),we("onResponse",r,e,t),we("onError",r,e,t),r}function we(e,t,r,n){let a=r[e],s=n[e];if(!a&&!s)return;if(!a){t[e]=s;return}if(!s){t[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Xe(e,t,r,n){n[e]&&(t[e]={...r[e],...n[e]});}var de=new Map,F="|",Ae=64,tt=/[^\w\-_|/:@.?=&~%#]/g,rt=/[^\w\-_|/:@.?=&~%#]/,qt=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 Z(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:n="",method:a=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=se(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>Ae&&(i=G(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Me(o)):String(o);i=l.length>Ae?G(l):l;}let m=a+F+n+F+u+F+c+F+i;return rt.test(m)?m.replace(tt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function At(e){return e.stale?P()>e.stale:false}function ye(e){return de.get(e)}function Re(e,t,r,n){if(r===0){pe(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;de.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&I("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!nt(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let n=ye(e);if(!n)return null;let a=d(t)?z(t):t,s={...n.data,data:a},o={...n,data:s};return de.set(e,o),H(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||M.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=ye(e);if(!a)return null;let s=nt(a),o=At(a);return s?(pe(e),null):!o||o&&!s?a.data:null}function Be(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(n,e,a,t.staleTime),H(n,e),fe(n);let o=t._prevKey;o&&fe(o);}}async function at(e){var a;if(!e)return null;let t=(a=e.headers)==null?void 0:a.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(K)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===b){let s=n.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{n=JSON.parse(s);}catch(o){}}}catch(s){n=null;}return n}var Fe=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ie.bind(null,a);if(!e)return {ok:false,error:r,data:n!=null?n:null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===J&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let c=se(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function st(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function It(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 u=st(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?st(s):null}async function ot(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Z(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await N(t);return o}async function ut(e,t,r){let n=await t(e),a=n.error;if(!a)return Be(n,r),n;r.onError&&await q(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&Ft(r,"FETCH ERROR",a),Be(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===re)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function lt(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===te;}function Ft(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var ve={isFetching:true};async function he(e,t=null){let r=qe(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=Z(r)),f&&p){let E=Pe(f,u,r);if(E)return E}if(f&&o){let E=be(f,o);if(E)return E}let D=r.retry||{},{retries:ct=0,resetTimeout:ft}=D,Oe=async(E=false,X=0)=>{X||(f&&!E&&(c?Pe(f,u,r)||(Re(f,ve,u,c),H(f,ve)):H(f,ve)),r.cacheKey=f);let v=r.url,pt=ze(f,v,n,o||0,!!a,!!(n&&(!X||ft))),T=r;T.signal=pt.signal;let ee,y=null;try{r.onRequest&&(f&&o&&!X&&await null,await q(r.onRequest,T));let O=r.fetcher;if(y=O?await O(v,T):await fetch(v,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await at(y):O&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${v} failed! Status: ${y.status||null}`,T,y);ee=Fe(y,T);let L=r.onResponse;L&&await q(L,ee);}catch(O){let L=O;lt(L,y,T),ee=Fe(y,T,L);}return ee},mt=ct>0?(E=false)=>ot((X,v)=>Oe(E,v),D):Oe,V=(E=false)=>ut(E,mt,r),Qe=l?it(V,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):V();return f&&(o&&Ge(f,Qe),Ze(f,V,void 0,c,V,!!i,!!m)),Qe}function vt(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?(o==null?void 0:o.url)===c?$(u,s):s:$($(e,u),s);return he(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=ke;exports.addTimeout=I;exports.buildConfig=qe;exports.createAbortError=oe;exports.createApiFetcher=vt;exports.deleteCache=pe;exports.fetchf=he;exports.fetchff=he;exports.generateCacheKey=Z;exports.getCache=ye;exports.getCachedResponse=Pe;exports.getDefaultConfig=et;exports.getInFlightPromise=be;exports.isSlowConnection=Ee;exports.mutate=Ie;exports.removeRevalidators=gt;exports.revalidate=me;exports.revalidateAll=Ye;exports.setCache=Re;exports.setDefaultConfig=Ct;exports.setEventProvider=ht;exports.subscribe=xt;return exports;})({});//# sourceMappingURL=index.global.js.map +var fetchff=(function(exports){'use strict';var yt=Object.defineProperty;var Rt=(e,t,r)=>t in e?yt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var z=(e,t,r)=>Rt(e,typeof t!="symbol"?t+"":t,r);var w="application/",J=w+"json",Ne="charset=utf-8",C="Content-Type",R="undefined",k="object",b="string",g="function",re="AbortError",Se="TimeoutError",Q="GET",_e="HEAD",ae="reject";var Ue=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===k}function G(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=Ue)return r;let c,p,h;if(l)if(Array.isArray(i))for(c=0,p=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function se(e){return e.includes("://")}var P=()=>Date.now(),N=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function q(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function Ke(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function A(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;z(this,"status");z(this,"statusText");z(this,"config");z(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,W=1e3,Pt=ce*W,Te=Array(ce).fill(0).map(()=>[]),I=new Map,le=0,x=null,ze=([e,t])=>{I.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch(r){}},B=(e,t,r)=>{if(_(e),rPt||r%W!==0){I.set(e,[setTimeout(ze.bind(null,[e,t]),r)]);return}let a=r/W,n=(le+a)%ce;Te[n].push([e,t]),I.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Te[le];for(let o=0;o{let t=I.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}I.delete(e),!I.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=P(),u=H.get(e),l=null;if(u){let m=u[0],c=u[3];if(!c&&o-u[2]{ke(e,oe(t+" aborted due to timeout",Se));},r),i}async function ke(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),H.delete(e);}function Ge(e,t){let r=H.get(e);r&&(r[4]=t);}function be(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(N);});}async function me(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=P();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function gt(e){Ze(e);let t=e==="focus"?5:6;M.forEach((r,a)=>{r[t]&&Dt(a);});}function xe(e){if(U.has(e))return;let t=$e.bind(null,e,true),r=Ye.get(e);if(r){let a=r(t);U.set(e,a);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function Ze(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ve(e,t,r,a,n,s,o){let u=M.get(e);u?(u[0]=t,u[1]=P(),u[2]=We,u[3]=a,u[4]=n,u[5]=s,u[6]=o):M.set(e,[t,P(),We,a,n,s,o]),s&&xe("focus"),o&&xe("online"),a&&B("s:"+e,me.bind(null,e,true),a*1e3);}function Dt(e){M.delete(e),_("s:"+e);}var $=new Map;function Et(e){let t=$.get(e);return t||(t=new Set,$.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=$.get(e);r&&(r.delete(t),r.size===0&&$.delete(e));}function L(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?(Tt(e,t),()=>{bt(e,t);}):N}var we=(Ee()?60:30)*1e3,Z={strategy:ae,timeout:we,headers:{Accept:J+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:we/30,maxDelay:we,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function wt(e){let t=G(e);return j({},t,Z)}function tt(){return {...Z}}function qe(e,t){if(!t)return Xe(e,tt());let r=G(t),a=j(Z,r);return Xe(e,a)}function Xe(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let a;r!==Q&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==b&&ge(a)&&(a=JSON.stringify(a))),Ct(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),l=se(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function Ct(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(ge(t))r=J+";"+Ne;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),et("retry",e,t,r),et("headers",e,t,r),Ce("onRequest",e,t,r),Ce("onResponse",e,t,r),Ce("onError",e,t,r),r}function Ce(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],u=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?u.concat(o):o.concat(u);}function et(e,t,r,a){if(r[e]){let n=t[e],s=r[e];if(e==="headers"&&(n instanceof Headers||s instanceof Headers)){let o=q(n),u=q(s);a[e]={...o,...u};}else a[e]={...n,...s};}}var de=new Map,F="|",Ae=64,rt=/[^\w\-_|/:@.?=&~%#]/g,at=/[^\w\-_|/:@.?=&~%#]/,qt=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 V(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let c;s instanceof Headers?c=q(s):c=s;let p=Object.keys(c),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+c+"&";}),i.length>Ae&&(i=Y(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let c=d(o)?JSON.stringify(Me(o)):String(o);i=c.length>Ae?Y(c):c;}let m=n+F+a+F+u+F+l+F+i;return at.test(m)?m.replace(rt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function ye(e){return de.get(e)}function Re(e,t,r,a){if(r===0){pe(e);return}let n=P(),s=r?r*1e3:0,o=a?a*1e3:0;de.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&B("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!nt(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=ye(e);if(!a)return null;let n=d(t)?G(t):t,s={...a.data,data:n},o={...a,data:s};return de.set(e,o),L(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||Z.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=ye(e);return n?nt(n)?(pe(e),null):n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(a,e,n,t.staleTime),L(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function st(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(J)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===b){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===k&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let l=q(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function ot(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function At(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 u=ot(r);if(u!==null)return u}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?ot(s):null}async function it(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,D=f.onRetry;D&&(await A(D,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=V(f,false)));}c=await e(l>0,l);let p=c.error;if(!p){if(u&&l0&&await S(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await S(t);return o}async function lt(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await A(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&Bt(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ae)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function ct(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===re;}function Bt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe=Object.freeze({isFetching:true});async function he(e,t=null){let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,p=u!==void 0||l!==void 0,h=!!(s||a||o||p||n||i||m),f=null;if(h&&(f=V(r)),f&&p){let E=Pe(f,u,r);if(E)return E}if(f&&o){let E=be(f,o);if(E)return E}let D=r.retry||{},{retries:ft=0,resetTimeout:mt}=D,ve=async(E=false,ee=0)=>{ee||(f&&!E&&(l?Pe(f,u,r)||(Re(f,Oe,u,l),L(f,Oe)):L(f,Oe)),r.cacheKey=f);let O=r.url,dt=Je(f,O,a,o||0,!!n,!!(a&&(!ee||mt))),T=r;T.signal=dt.signal;let te,y=null;try{r.onRequest&&(f&&o&&!ee&&await null,await A(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await st(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);te=Fe(y,T);let K=r.onResponse;K&&await A(K,te);}catch(v){let K=v;ct(K,y,T),te=Fe(y,T,K);}return te},pt=ft>0?(E=false)=>it((ee,O)=>ve(E,O),D):ve,X=(E=false)=>lt(E,pt,r),Qe=c?ut(X,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):X();return f&&(o&&Ge(f,Qe),(l||i||m)&&Ve(f,X,void 0,l,X,!!i,!!m)),Qe}function Ft(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=se(l)?(o==null?void 0:o.url)===l?j(u,s):s:j(j(e,u),s);return he(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} +exports.abortRequest=ke;exports.addTimeout=B;exports.buildConfig=qe;exports.createAbortError=oe;exports.createApiFetcher=Ft;exports.deleteCache=pe;exports.fetchf=he;exports.fetchff=he;exports.generateCacheKey=V;exports.getCache=ye;exports.getCachedResponse=Pe;exports.getDefaultConfig=tt;exports.getInFlightPromise=be;exports.isSlowConnection=Ee;exports.mutate=Ie;exports.removeRevalidators=gt;exports.revalidate=me;exports.revalidateAll=$e;exports.setCache=Re;exports.setDefaultConfig=wt;exports.setEventProvider=ht;exports.subscribe=xt;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 04fcc736..816337f8 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/browser/index.mjs b/dist/browser/index.mjs index 3a35509e..7a5f477a 100644 --- a/dist/browser/index.mjs +++ b/dist/browser/index.mjs @@ -1,3 +1,3 @@ -var dt=Object.defineProperty;var yt=(e,t,r)=>t in e?dt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var j=(e,t,r)=>yt(e,typeof t!="symbol"?t+"":t,r);var C="application/",K=C+"json",Se="charset=utf-8",w="Content-Type",R="undefined",J="object",b="string",g="function",te="AbortError",Ne="TimeoutError",Q="GET",_e="HEAD",re="reject";var He=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===J}function z(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function ae(e){return e.includes("://")}var P=()=>Date.now(),S=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function se(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n]=r;});else if(d(e))for(let[r,n]of Object.entries(e))t[r.toLowerCase()]=n;return t}function Ke(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var ie=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;j(this,"status");j(this,"statusText");j(this,"config");j(this,"isCancelled");this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var ce=600,k=1e3,Rt=ce*k,Te=Array(ce).fill(0).map(()=>[]),A=new Map,le=0,x=null,Je=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(S);}catch(r){}},I=(e,t,r)=>{if(_(e),rRt||r%k!==0){A.set(e,[setTimeout(Je.bind(null,[e,t]),r)]);return}let n=r/k,a=(le+n)%ce;Te[a].push([e,t]),A.set(e,a),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Te[le];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function ze(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ke(e,oe(t+" aborted due to timeout",Ne));},r),i}async function ke(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),B.delete(e);}function Ge(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function be(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&Dt(n);});}function xe(e){if(U.has(e))return;let t=Ye.bind(null,e,true),r=We.get(e);if(r){let n=r(t);U.set(e,n);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function $e(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ze(e,t,r,n,a,s,o){W.set(e,[t,P(),Pt,n,a,s,o]),s&&xe("focus"),o&&xe("online"),n&&I("s:"+e,me.bind(null,e,true),n*1e3);}function Dt(e){W.delete(e),_("s:"+e);}var Y=new Map;function Et(e){let t=Y.get(e);return t||(t=new Set,Y.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=Y.get(e);r&&(r.delete(t),r.size===0&&Y.delete(e));}function H(e,t){let r=Y.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function xt(e,t){return e?(Tt(e,t),()=>{bt(e,t);}):S}var Ce=(Ee()?60:30)*1e3,M={strategy:re,timeout:Ce,headers:{Accept:K+", 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 Ct(e){let t=z(e);return Object.assign(M,t),M}function et(){return {...M}}function qe(e,t){if(!t)return Ve(e,et());let r=z(t),n=$(M,r);return Ve(e,n)}function Ve(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let n;r!==Q&&r!==_e&&(n=(i=t.body)!=null?i:t.data,n&&typeof n!==b&&ge(n)&&(n=JSON.stringify(n))),wt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function wt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(ge(t))r=K+";"+Se;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function $(e,t){let r=Object.assign({},e,t);return Xe("retry",r,e,t),Xe("headers",r,e,t),we("onRequest",r,e,t),we("onResponse",r,e,t),we("onError",r,e,t),r}function we(e,t,r,n){let a=r[e],s=n[e];if(!a&&!s)return;if(!a){t[e]=s;return}if(!s){t[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Xe(e,t,r,n){n[e]&&(t[e]={...r[e],...n[e]});}var de=new Map,F="|",Ae=64,tt=/[^\w\-_|/:@.?=&~%#]/g,rt=/[^\w\-_|/:@.?=&~%#]/,qt=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 Z(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:n="",method:a=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=se(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>Ae&&(i=G(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Me(o)):String(o);i=l.length>Ae?G(l):l;}let m=a+F+n+F+u+F+c+F+i;return rt.test(m)?m.replace(tt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function At(e){return e.stale?P()>e.stale:false}function ye(e){return de.get(e)}function Re(e,t,r,n){if(r===0){pe(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;de.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&I("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!nt(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let n=ye(e);if(!n)return null;let a=d(t)?z(t):t,s={...n.data,data:a},o={...n,data:s};return de.set(e,o),H(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||M.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=ye(e);if(!a)return null;let s=nt(a),o=At(a);return s?(pe(e),null):!o||o&&!s?a.data:null}function Be(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(n,e,a,t.staleTime),H(n,e),fe(n);let o=t._prevKey;o&&fe(o);}}async function at(e){var a;if(!e)return null;let t=(a=e.headers)==null?void 0:a.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(K)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===b){let s=n.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{n=JSON.parse(s);}catch(o){}}}catch(s){n=null;}return n}var Fe=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ie.bind(null,a);if(!e)return {ok:false,error:r,data:n!=null?n:null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===J&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let c=se(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function st(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function It(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 u=st(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?st(s):null}async function ot(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Z(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await N(t);return o}async function ut(e,t,r){let n=await t(e),a=n.error;if(!a)return Be(n,r),n;r.onError&&await q(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&Ft(r,"FETCH ERROR",a),Be(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===re)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function lt(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===te;}function Ft(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var ve={isFetching:true};async function he(e,t=null){let r=qe(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=Z(r)),f&&p){let E=Pe(f,u,r);if(E)return E}if(f&&o){let E=be(f,o);if(E)return E}let D=r.retry||{},{retries:ct=0,resetTimeout:ft}=D,Oe=async(E=false,X=0)=>{X||(f&&!E&&(c?Pe(f,u,r)||(Re(f,ve,u,c),H(f,ve)):H(f,ve)),r.cacheKey=f);let v=r.url,pt=ze(f,v,n,o||0,!!a,!!(n&&(!X||ft))),T=r;T.signal=pt.signal;let ee,y=null;try{r.onRequest&&(f&&o&&!X&&await null,await q(r.onRequest,T));let O=r.fetcher;if(y=O?await O(v,T):await fetch(v,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await at(y):O&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${v} failed! Status: ${y.status||null}`,T,y);ee=Fe(y,T);let L=r.onResponse;L&&await q(L,ee);}catch(O){let L=O;lt(L,y,T),ee=Fe(y,T,L);}return ee},mt=ct>0?(E=false)=>ot((X,v)=>Oe(E,v),D):Oe,V=(E=false)=>ut(E,mt,r),Qe=l?it(V,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):V();return f&&(o&&Ge(f,Qe),Ze(f,V,void 0,c,V,!!i,!!m)),Qe}function vt(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?(o==null?void 0:o.url)===c?$(u,s):s:$($(e,u),s);return he(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} -export{ke as abortRequest,I as addTimeout,qe as buildConfig,oe as createAbortError,vt as createApiFetcher,pe as deleteCache,he as fetchf,he as fetchff,Z as generateCacheKey,ye as getCache,Pe as getCachedResponse,et as getDefaultConfig,be as getInFlightPromise,Ee as isSlowConnection,Ie as mutate,gt as removeRevalidators,me as revalidate,Ye as revalidateAll,Re as setCache,Ct as setDefaultConfig,ht as setEventProvider,xt as subscribe};//# sourceMappingURL=index.mjs.map +var yt=Object.defineProperty;var Rt=(e,t,r)=>t in e?yt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var z=(e,t,r)=>Rt(e,typeof t!="symbol"?t+"":t,r);var w="application/",J=w+"json",Ne="charset=utf-8",C="Content-Type",R="undefined",k="object",b="string",g="function",re="AbortError",Se="TimeoutError",Q="GET",_e="HEAD",ae="reject";var Ue=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===k}function G(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=Ue)return r;let c,p,h;if(l)if(Array.isArray(i))for(c=0,p=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function se(e){return e.includes("://")}var P=()=>Date.now(),N=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function q(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function Ke(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function A(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;z(this,"status");z(this,"statusText");z(this,"config");z(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,W=1e3,Pt=ce*W,Te=Array(ce).fill(0).map(()=>[]),I=new Map,le=0,x=null,ze=([e,t])=>{I.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch(r){}},B=(e,t,r)=>{if(_(e),rPt||r%W!==0){I.set(e,[setTimeout(ze.bind(null,[e,t]),r)]);return}let a=r/W,n=(le+a)%ce;Te[n].push([e,t]),I.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Te[le];for(let o=0;o{let t=I.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}I.delete(e),!I.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=P(),u=H.get(e),l=null;if(u){let m=u[0],c=u[3];if(!c&&o-u[2]{ke(e,oe(t+" aborted due to timeout",Se));},r),i}async function ke(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),H.delete(e);}function Ge(e,t){let r=H.get(e);r&&(r[4]=t);}function be(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(N);});}async function me(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=P();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function gt(e){Ze(e);let t=e==="focus"?5:6;M.forEach((r,a)=>{r[t]&&Dt(a);});}function xe(e){if(U.has(e))return;let t=$e.bind(null,e,true),r=Ye.get(e);if(r){let a=r(t);U.set(e,a);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function Ze(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ve(e,t,r,a,n,s,o){let u=M.get(e);u?(u[0]=t,u[1]=P(),u[2]=We,u[3]=a,u[4]=n,u[5]=s,u[6]=o):M.set(e,[t,P(),We,a,n,s,o]),s&&xe("focus"),o&&xe("online"),a&&B("s:"+e,me.bind(null,e,true),a*1e3);}function Dt(e){M.delete(e),_("s:"+e);}var $=new Map;function Et(e){let t=$.get(e);return t||(t=new Set,$.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=$.get(e);r&&(r.delete(t),r.size===0&&$.delete(e));}function L(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?(Tt(e,t),()=>{bt(e,t);}):N}var we=(Ee()?60:30)*1e3,Z={strategy:ae,timeout:we,headers:{Accept:J+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:we/30,maxDelay:we,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function wt(e){let t=G(e);return j({},t,Z)}function tt(){return {...Z}}function qe(e,t){if(!t)return Xe(e,tt());let r=G(t),a=j(Z,r);return Xe(e,a)}function Xe(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let a;r!==Q&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==b&&ge(a)&&(a=JSON.stringify(a))),Ct(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),l=se(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function Ct(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(ge(t))r=J+";"+Ne;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),et("retry",e,t,r),et("headers",e,t,r),Ce("onRequest",e,t,r),Ce("onResponse",e,t,r),Ce("onError",e,t,r),r}function Ce(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],u=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?u.concat(o):o.concat(u);}function et(e,t,r,a){if(r[e]){let n=t[e],s=r[e];if(e==="headers"&&(n instanceof Headers||s instanceof Headers)){let o=q(n),u=q(s);a[e]={...o,...u};}else a[e]={...n,...s};}}var de=new Map,F="|",Ae=64,rt=/[^\w\-_|/:@.?=&~%#]/g,at=/[^\w\-_|/:@.?=&~%#]/,qt=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 V(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let c;s instanceof Headers?c=q(s):c=s;let p=Object.keys(c),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+c+"&";}),i.length>Ae&&(i=Y(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let c=d(o)?JSON.stringify(Me(o)):String(o);i=c.length>Ae?Y(c):c;}let m=n+F+a+F+u+F+l+F+i;return at.test(m)?m.replace(rt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function ye(e){return de.get(e)}function Re(e,t,r,a){if(r===0){pe(e);return}let n=P(),s=r?r*1e3:0,o=a?a*1e3:0;de.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&B("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!nt(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=ye(e);if(!a)return null;let n=d(t)?G(t):t,s={...a.data,data:n},o={...a,data:s};return de.set(e,o),L(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||Z.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=ye(e);return n?nt(n)?(pe(e),null):n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(a,e,n,t.staleTime),L(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function st(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(J)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===b){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===k&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let l=q(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function ot(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function At(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 u=ot(r);if(u!==null)return u}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?ot(s):null}async function it(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,D=f.onRetry;D&&(await A(D,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=V(f,false)));}c=await e(l>0,l);let p=c.error;if(!p){if(u&&l0&&await S(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await S(t);return o}async function lt(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await A(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&Bt(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ae)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function ct(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===re;}function Bt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe=Object.freeze({isFetching:true});async function he(e,t=null){let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,p=u!==void 0||l!==void 0,h=!!(s||a||o||p||n||i||m),f=null;if(h&&(f=V(r)),f&&p){let E=Pe(f,u,r);if(E)return E}if(f&&o){let E=be(f,o);if(E)return E}let D=r.retry||{},{retries:ft=0,resetTimeout:mt}=D,ve=async(E=false,ee=0)=>{ee||(f&&!E&&(l?Pe(f,u,r)||(Re(f,Oe,u,l),L(f,Oe)):L(f,Oe)),r.cacheKey=f);let O=r.url,dt=Je(f,O,a,o||0,!!n,!!(a&&(!ee||mt))),T=r;T.signal=dt.signal;let te,y=null;try{r.onRequest&&(f&&o&&!ee&&await null,await A(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await st(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);te=Fe(y,T);let K=r.onResponse;K&&await A(K,te);}catch(v){let K=v;ct(K,y,T),te=Fe(y,T,K);}return te},pt=ft>0?(E=false)=>it((ee,O)=>ve(E,O),D):ve,X=(E=false)=>lt(E,pt,r),Qe=c?ut(X,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):X();return f&&(o&&Ge(f,Qe),(l||i||m)&&Ve(f,X,void 0,l,X,!!i,!!m)),Qe}function Ft(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=se(l)?(o==null?void 0:o.url)===l?j(u,s):s:j(j(e,u),s);return he(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} +export{ke as abortRequest,B as addTimeout,qe as buildConfig,oe as createAbortError,Ft as createApiFetcher,pe as deleteCache,he as fetchf,he as fetchff,V as generateCacheKey,ye as getCache,Pe as getCachedResponse,tt as getDefaultConfig,be as getInFlightPromise,Ee as isSlowConnection,Ie as mutate,gt as removeRevalidators,me as revalidate,$e as revalidateAll,Re as setCache,wt as setDefaultConfig,ht as setEventProvider,xt 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 6aa953a2..7ab60d97 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/node/index.js b/dist/node/index.js index 07050136..d8f16b39 100644 --- a/dist/node/index.js +++ b/dist/node/index.js @@ -1,3 +1,3 @@ -'use strict';var C="application/",j=C+"json",Qe="charset=utf-8",w="Content-Type",R="undefined",K="object",b="string",g="function",ee="AbortError",Se="TimeoutError",Q="GET",Ne="HEAD",te="reject";var Ue=10;function re(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===K}function J(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function He(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=Ue)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function ne(e){return e.includes("://")}var P=()=>Date.now(),S=()=>{};function he(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||re(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function N(e){return new Promise(t=>setTimeout(()=>t(true),e))}function ge(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==R?ge(e.data,t+1):e}function ae(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n]=r;});else if(d(e))for(let[r,n]of Object.entries(e))t[r.toLowerCase()]=n;return t}function je(){return typeof window!==R&&typeof window.addEventListener===g}function se(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var De=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function q(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var oe=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}status;statusText;config;isCancelled};var ie=class extends oe{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var le=600,z=1e3,pt=le*z,Ee=Array(le).fill(0).map(()=>[]),A=new Map,ue=0,x=null,Ke=([e,t])=>{A.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(S);}catch{}},I=(e,t,r)=>{if(_(e),rpt||r%z!==0){A.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let n=r/z,a=(ue+n)%le;Ee[a].push([e,t]),A.set(e,a),x||(x=setInterval(()=>{ue=(ue+1)%le;let s=Ee[ue];for(let o=0;o{let t=A.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}A.delete(e),!A.size&&x&&(clearInterval(x),x=null);}};var B=new Map;function Je(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=B.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{ze(e,se(t+" aborted due to timeout",Se));},r),i}async function ze(e,t=null){if(e){let r=B.get(e);r&&(t&&r[0].abort(t),ce(e));}}function ce(e){_(e),B.delete(e);}function ke(e,t){let r=B.get(e);r&&(r[4]=t,B.set(e,r));}function Te(e,t){if(!e)return null;let r=B.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{r[t]&&Pt(n);});}function be(e){if(U.has(e))return;let t=We.bind(null,e,true),r=Ge.get(e);if(r){let n=r(t);U.set(e,n);return}je()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function Ye(e){let t=U.get(e);t&&(t(),U.delete(e));}function $e(e,t,r,n,a,s,o){G.set(e,[t,P(),dt,n,a,s,o]),s&&be("focus"),o&&be("online"),n&&I("s:"+e,fe.bind(null,e,true),n*1e3);}function Pt(e){G.delete(e),_("s:"+e);}var W=new Map;function ht(e){let t=W.get(e);return t||(t=new Set,W.set(e,t)),t}function gt(e,t){ht(e).add(t);}function Dt(e,t){let r=W.get(e);r&&(r.delete(t),r.size===0&&W.delete(e));}function H(e,t){let r=W.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function Et(e,t){return e?(gt(e,t),()=>{Dt(e,t);}):S}var xe=(De()?60:30)*1e3,M={strategy:te,timeout:xe,headers:{Accept:j+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:xe/30,maxDelay:xe,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Tt(e){let t=J(e);return Object.assign(M,t),M}function Xe(){return {...M}}function we(e,t){if(!t)return Ze(e,Xe());let r=J(t),n=Y(M,r);return Ze(e,n)}function Ze(e,t){let r=t.method;r=r?r.toUpperCase():Q;let n;r!==Q&&r!==Ne&&(n=t.body??t.data,n&&typeof n!==b&&he(n)&&(n=JSON.stringify(n))),bt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),c=ne(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function bt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(re(t))r=C+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=C+"octet-stream";else if(he(t))r=j+";"+Qe;else return;e instanceof Headers?e.has(w)||e.set(w,r):d(e)&&!Array.isArray(e)&&!e[w]&&(e[w]=r);}function Y(e,t){let r=Object.assign({},e,t);return Ve("retry",r,e,t),Ve("headers",r,e,t),Ce("onRequest",r,e,t),Ce("onResponse",r,e,t),Ce("onError",r,e,t),r}function Ce(e,t,r,n){let a=r[e],s=n[e];if(!a&&!s)return;if(!a){t[e]=s;return}if(!s){t[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];t[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Ve(e,t,r,n){n[e]&&(t[e]={...r[e],...n[e]});}var pe=new Map,F="|",qe=64,et=/[^\w\-_|/:@.?=&~%#]/g,tt=/[^\w\-_|/:@.?=&~%#]/,xt=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 $(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:n="",method:a=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=ae(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>qe&&(i=k(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(He(o)):String(o);i=l.length>qe?k(l):l;}let m=a+F+n+F+u+F+c+F+i;return tt.test(m)?m.replace(et,""):m}function rt(e){return e.expiry?P()>e.expiry:false}function Ct(e){return e.stale?P()>e.stale:false}function de(e){return pe.get(e)}function ye(e,t,r,n){if(r===0){me(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;pe.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&I("c:"+e,()=>{me(e,true);},s);}function me(e,t=false){if(t){let r=de(e);if(!r||!rt(r))return}pe.delete(e);}async function Ae(e,t,r){if(!e)return null;let n=de(e);if(!n)return null;let a=d(t)?J(t):t,s={...n.data,data:a},o={...n,data:s};return pe.set(e,o),H(e,s),r&&r.refetch?await fe(e):null}function Re(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||M.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=de(e);if(!a)return null;let s=rt(a),o=Ct(a);return s?(me(e),null):!o||o&&!s?a.data:null}function Ie(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&ye(n,e,a,t.staleTime),H(n,e),ce(n);let o=t._prevKey;o&&ce(o);}}async function nt(e){if(!e)return null;let t=e.headers?.get(w);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(j)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(C+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(C+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===b){let a=n.trim();if(a.startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]"))try{n=JSON.parse(a);}catch{}}}catch{n=null;}return n}var Be=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ae.bind(null,a);if(!e)return {ok:false,error:r,data:n??null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===K&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=ge(u)),t.select&&(e.data=u=t.select(u));let c=ae(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function at(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function wt(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 u=at(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?at(s):null}async function st(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await q(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=$(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await N(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await N(t);return o}async function it(e,t,r){let n=await t(e),a=n.error;if(!a)return Ie(n,r),n;r.onError&&await q(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&At(r,"FETCH ERROR",a),Ie(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===te)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function ut(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===ee;}function At(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Fe={isFetching:true};async function Pe(e,t=null){let r=we(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=$(r)),f&&p){let E=Re(f,u,r);if(E)return E}if(f&&o){let E=Te(f,o);if(E)return E}let D=r.retry||{},{retries:lt=0,resetTimeout:ct}=D,ve=async(E=false,V=0)=>{V||(f&&!E&&(c?Re(f,u,r)||(ye(f,Fe,u,c),H(f,Fe)):H(f,Fe)),r.cacheKey=f);let v=r.url,mt=Je(f,v,n,o||0,!!a,!!(n&&(!V||ct))),T=r;T.signal=mt.signal;let X,y=null;try{r.onRequest&&(f&&o&&!V&&await null,await q(r.onRequest,T));let O=r.fetcher;if(y=O?await O(v,T):await fetch(v,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await nt(y):O&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ie(`${T.method} to ${v} failed! Status: ${y.status||null}`,T,y);X=Be(y,T);let L=r.onResponse;L&&await q(L,X);}catch(O){let L=O;ut(L,y,T),X=Be(y,T,L);}return X},ft=lt>0?(E=false)=>st((V,v)=>ve(E,v),D):ve,Z=(E=false)=>it(E,ft,r),Oe=l?ot(Z,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):Z();return f&&(o&&ke(f,Oe),$e(f,Z,void 0,c,Z,!!i,!!m)),Oe}function It(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ne(c)?o?.url===c?Y(u,s):s:Y(Y(e,u),s);return Pe(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=ze;exports.addTimeout=I;exports.buildConfig=we;exports.createAbortError=se;exports.createApiFetcher=It;exports.deleteCache=me;exports.fetchf=Pe;exports.fetchff=Pe;exports.generateCacheKey=$;exports.getCache=de;exports.getCachedResponse=Re;exports.getDefaultConfig=Xe;exports.getInFlightPromise=Te;exports.isSlowConnection=De;exports.mutate=Ae;exports.removeRevalidators=Rt;exports.revalidate=fe;exports.revalidateAll=We;exports.setCache=ye;exports.setDefaultConfig=Tt;exports.setEventProvider=yt;exports.subscribe=Et;//# sourceMappingURL=index.js.map +'use strict';var w="application/",z=w+"json",Qe="charset=utf-8",C="Content-Type",R="undefined",J="object",b="string",g="function",te="AbortError",Ne="TimeoutError",Q="GET",Se="HEAD",re="reject";var He=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===J}function k(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function Ue(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function ae(e){return e.includes("://")}var P=()=>Date.now(),N=()=>{};function he(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function ge(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?ge(e.data,t+1):e}function q(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function je(){return typeof window!==R&&typeof window.addEventListener===g}function se(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var De=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function A(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var oe=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}status;statusText;config;isCancelled};var ie=class extends oe{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var le=600,G=1e3,dt=le*G,Ee=Array(le).fill(0).map(()=>[]),I=new Map,ue=0,x=null,Ke=([e,t])=>{I.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch{}},B=(e,t,r)=>{if(_(e),rdt||r%G!==0){I.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let n=r/G,a=(ue+n)%le;Ee[a].push([e,t]),I.set(e,a),x||(x=setInterval(()=>{ue=(ue+1)%le;let s=Ee[ue];for(let o=0;o{let t=I.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}I.delete(e),!I.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function ze(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=H.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{Je(e,se(t+" aborted due to timeout",Ne));},r),i}async function Je(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),ce(e));}}function ce(e){_(e),H.delete(e);}function ke(e,t){let r=H.get(e);r&&(r[4]=t);}function Te(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{if(!a[r])return;a[1]=n;let s=t?a[4]:a[0];s&&Promise.resolve(s(t)).catch(N);});}async function fe(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=P();let n=t?r[4]:r[0];if(n)return await n(t)}return null}function Rt(e){$e(e);let t=e==="focus"?5:6;M.forEach((r,n)=>{r[t]&&Pt(n);});}function be(e){if(U.has(e))return;let t=Ye.bind(null,e,true),r=We.get(e);if(r){let n=r(t);U.set(e,n);return}je()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function $e(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ze(e,t,r,n,a,s,o){let u=M.get(e);u?(u[0]=t,u[1]=P(),u[2]=Ge,u[3]=n,u[4]=a,u[5]=s,u[6]=o):M.set(e,[t,P(),Ge,n,a,s,o]),s&&be("focus"),o&&be("online"),n&&B("s:"+e,fe.bind(null,e,true),n*1e3);}function Pt(e){M.delete(e),_("s:"+e);}var Y=new Map;function ht(e){let t=Y.get(e);return t||(t=new Set,Y.set(e,t)),t}function gt(e,t){ht(e).add(t);}function Dt(e,t){let r=Y.get(e);r&&(r.delete(t),r.size===0&&Y.delete(e));}function L(e,t){let r=Y.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function Et(e,t){return e?(gt(e,t),()=>{Dt(e,t);}):N}var xe=(De()?60:30)*1e3,$={strategy:re,timeout:xe,headers:{Accept:z+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:xe/30,maxDelay:xe,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Tt(e){let t=k(e);return j({},t,$)}function et(){return {...$}}function Ce(e,t){if(!t)return Ve(e,et());let r=k(t),n=j($,r);return Ve(e,n)}function Ve(e,t){let r=t.method;r=r?r.toUpperCase():Q;let n;r!==Q&&r!==Se&&(n=t.body??t.data,n&&typeof n!==b&&he(n)&&(n=JSON.stringify(n))),bt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function bt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(he(t))r=z+";"+Qe;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),Xe("retry",e,t,r),Xe("headers",e,t,r),we("onRequest",e,t,r),we("onResponse",e,t,r),we("onError",e,t,r),r}function we(e,t,r,n){let a=t[e],s=r[e];if(!a&&!s)return;if(!a){n[e]=s;return}if(!s){n[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];n[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Xe(e,t,r,n){if(r[e]){let a=t[e],s=r[e];if(e==="headers"&&(a instanceof Headers||s instanceof Headers)){let o=q(a),u=q(s);n[e]={...o,...u};}else n[e]={...a,...s};}}var pe=new Map,F="|",qe=64,tt=/[^\w\-_|/:@.?=&~%#]/g,rt=/[^\w\-_|/:@.?=&~%#]/,xt=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 Z(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:n="",method:a=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=q(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>qe&&(i=W(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Ue(o)):String(o);i=l.length>qe?W(l):l;}let m=a+F+n+F+u+F+c+F+i;return rt.test(m)?m.replace(tt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function de(e){return pe.get(e)}function ye(e,t,r,n){if(r===0){me(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;pe.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&B("c:"+e,()=>{me(e,true);},s);}function me(e,t=false){if(t){let r=de(e);if(!r||!nt(r))return}pe.delete(e);}async function Ae(e,t,r){if(!e)return null;let n=de(e);if(!n)return null;let a=d(t)?k(t):t,s={...n.data,data:a},o={...n,data:s};return pe.set(e,o),L(e,s),r&&r.refetch?await fe(e):null}function Re(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||$.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=de(e);return a?nt(a)?(me(e),null):a.data:null}function Ie(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&ye(n,e,a,t.staleTime),L(n,e),ce(n);let o=t._prevKey;o&&ce(o);}}async function at(e){if(!e)return null;let t=e.headers?.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(z)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===b){let a=n.trim();if(a.startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]"))try{n=JSON.parse(a);}catch{}}}catch{n=null;}return n}var Be=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ae.bind(null,a);if(!e)return {ok:false,error:r,data:n??null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===J&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=ge(u)),t.select&&(e.data=u=t.select(u));let c=q(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function st(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function wt(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 u=st(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?st(s):null}async function ot(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await A(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Z(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await S(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await S(t);return o}async function ut(e,t,r){let n=await t(e),a=n.error;if(!a)return Ie(n,r),n;r.onError&&await A(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&qt(r,"FETCH ERROR",a),Ie(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===re)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function lt(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===te;}function qt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Fe=Object.freeze({isFetching:true});async function Pe(e,t=null){let r=Ce(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=Z(r)),f&&p){let E=Re(f,u,r);if(E)return E}if(f&&o){let E=Te(f,o);if(E)return E}let D=r.retry||{},{retries:ct=0,resetTimeout:ft}=D,Oe=async(E=false,X=0)=>{X||(f&&!E&&(c?Re(f,u,r)||(ye(f,Fe,u,c),L(f,Fe)):L(f,Fe)),r.cacheKey=f);let O=r.url,pt=ze(f,O,n,o||0,!!a,!!(n&&(!X||ft))),T=r;T.signal=pt.signal;let ee,y=null;try{r.onRequest&&(f&&o&&!X&&await null,await A(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await at(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ie(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);ee=Be(y,T);let K=r.onResponse;K&&await A(K,ee);}catch(v){let K=v;lt(K,y,T),ee=Be(y,T,K);}return ee},mt=ct>0?(E=false)=>ot((X,O)=>Oe(E,O),D):Oe,V=(E=false)=>ut(E,mt,r),ve=l?it(V,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):V();return f&&(o&&ke(f,ve),(c||i||m)&&Ze(f,V,void 0,c,V,!!i,!!m)),ve}function At(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?o?.url===c?j(u,s):s:j(j(e,u),s);return Pe(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} +exports.abortRequest=Je;exports.addTimeout=B;exports.buildConfig=Ce;exports.createAbortError=se;exports.createApiFetcher=At;exports.deleteCache=me;exports.fetchf=Pe;exports.fetchff=Pe;exports.generateCacheKey=Z;exports.getCache=de;exports.getCachedResponse=Re;exports.getDefaultConfig=et;exports.getInFlightPromise=Te;exports.isSlowConnection=De;exports.mutate=Ae;exports.removeRevalidators=Rt;exports.revalidate=fe;exports.revalidateAll=Ye;exports.setCache=ye;exports.setDefaultConfig=Tt;exports.setEventProvider=yt;exports.subscribe=Et;//# 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 35681b0f..6b56b7d3 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","listeners","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","mergeConfigs","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","mergedConfig","mergeConfig","mergeInterceptors","property","targetConfig","baseInterceptor","newInterceptor","baseArr","newArr","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","isCacheExpired","isCacheStale","getCache","setCache","deleteCache","time","ttlMs","staleTimeMs","removeExpired","mutate","newData","settings","updatedData","updatedResponse","updatedEntry","getCachedResponse","cacheKey","cacheTime","buster","isExpired","isStale","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","_error","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","_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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 // Handle Headers object with entries() method\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n headersObject[key] = value;\n });\n } else if (isObject(headers)) {\n // Handle plain object\n for (const [key, value] of Object.entries(headers)) {\n // Normalize keys to lowercase as per RFC 2616 4.2\n // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2\n headersObject[key.toLowerCase()] = value;\n }\n }\n\n return headersObject;\n}\n\n/**\n * 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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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 for (const value of keyMap.values()) {\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\n item[4] = promise;\n\n inFlight.set(key, item);\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 for (const entry of revalidators.values()) {\n if (!entry[flagIndex]) {\n continue;\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 revalidators.set(key, [\n revalidatorFn,\n timeNow(),\n ttl ?? DEFAULT_TTL,\n staleTime,\n bgRevalidatorFn,\n refetchOnFocus,\n refetchOnReconnect,\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 {\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 Object.assign(defaultConfig, sanitized);\n\n return defaultConfig;\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\n ) {\n headers[CONTENT_TYPE] = contentTypeValue;\n }\n}\n\nexport function mergeConfigs(\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): RequestConfig {\n const mergedConfig: RequestConfig = Object.assign(\n {},\n baseConfig,\n overrideConfig,\n );\n\n // Ensure that retry and headers are merged correctly\n mergeConfig('retry', mergedConfig, baseConfig, overrideConfig);\n mergeConfig('headers', mergedConfig, baseConfig, overrideConfig);\n\n // Merge interceptors efficiently\n mergeInterceptors('onRequest', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onResponse', mergedConfig, baseConfig, overrideConfig);\n mergeInterceptors('onError', mergedConfig, baseConfig, overrideConfig);\n\n return mergedConfig;\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 targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: 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} targetConfig - The configuration object that will receive the merged properties.\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 */\nexport function mergeConfig(\n property: K,\n targetConfig: RequestConfig,\n baseConfig: RequestConfig,\n overrideConfig: RequestConfig,\n): void {\n if (overrideConfig[property]) {\n targetConfig[property] = {\n ...baseConfig[property],\n ...overrideConfig[property],\n };\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 * Checks if the cache entry is stale based on its timestamp and the stale time.\n *\n * @param {CacheEntry} entry - The cache entry to check.\n * @returns {boolean} - Returns true if the cache entry is stale, false otherwise.\n */\nfunction isCacheStale(entry: CacheEntry): boolean {\n if (!entry.stale) {\n return false;\n }\n\n return timeNow() > entry.stale;\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 const isStale = isCacheStale(entry);\n\n // If completely expired, delete and return null\n if (isExpired) {\n deleteCache(cacheKey);\n return null;\n }\n\n // If fresh (not stale), return immediately\n if (!isStale) {\n return entry.data;\n }\n\n // SWR: Data is stale but not expired\n if (isStale && !isExpired) {\n // Triggering background revalidation here could cause race conditions\n // So we return stale data immediately and leave it up to implementers to handle revalidation\n return entry.data;\n }\n\n return null;\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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = {\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 addRevalidator(\n _cacheKey,\n requestWithErrorHandling,\n undefined,\n staleTime,\n requestWithErrorHandling,\n !!refetchOnFocus,\n !!refetchOnReconnect,\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","_error","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file From 563fb9ab7778385e81c4947573d3af0845acffa8 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Feb 2026 01:05:10 +0100 Subject: [PATCH 28/30] docs: update benchmark command in fetchf.bench.mjs for accuracy --- test/benchmarks/fetchf.bench.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/fetchf.bench.mjs b/test/benchmarks/fetchf.bench.mjs index ed59701c..0125e1be 100644 --- a/test/benchmarks/fetchf.bench.mjs +++ b/test/benchmarks/fetchf.bench.mjs @@ -1,5 +1,5 @@ // To run this benchmark, use the following command: -// npx tsx test/benchmarks/generic.bench.mjs +// npx tsx test/benchmarks/fetchf.bench.mjs import Benchmark from 'benchmark'; import { fetchf } from '../../dist/browser/index.mjs'; import { onComplete } from './utils.mjs'; From 5d57ca744afd3c983c20bdd3f04843d46936041f Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Feb 2026 01:42:14 +0100 Subject: [PATCH 29/30] feat: add string caching optimization to fetchf function and benchmark test --- src/request-handler.ts | 16 ++++++++++++++++ test/benchmarks/fetchf.bench.mjs | 10 ++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/request-handler.ts b/src/request-handler.ts index 2ce0db3f..d4fb8673 100644 --- a/src/request-handler.ts +++ b/src/request-handler.ts @@ -63,6 +63,22 @@ export async function fetchf< RequestBody > | null = null, ): Promise> { + // Ultra-fast early cache check if cacheKey is provided as a string + // For workloads dominated by repeated requests, this string caching optimization + // can potentially support millions of requests per second with minimal CPU overhead + if (reqConfig && typeof reqConfig.cacheKey === 'string') { + const cached = getCachedResponse< + ResponseData, + RequestBody, + QueryParams, + PathParams + >(reqConfig.cacheKey, reqConfig.cacheTime, reqConfig); + + if (cached) { + return cached; + } + } + const fetcherConfig = buildConfig< ResponseData, RequestBody, diff --git a/test/benchmarks/fetchf.bench.mjs b/test/benchmarks/fetchf.bench.mjs index 0125e1be..29167461 100644 --- a/test/benchmarks/fetchf.bench.mjs +++ b/test/benchmarks/fetchf.bench.mjs @@ -37,6 +37,13 @@ const requestWithCache = () => strategy: 'softFail', }); +const requestWithStringCache = () => + fetchf('https://api.example.com/posts/1', { + cacheKey: 'post-1', + cacheTime: 300, + strategy: 'softFail', + }); + suite .add('Simple fetchf request', () => { return simpleRequest(); @@ -47,6 +54,9 @@ suite .add('fetchf with caching enabled', () => { return requestWithCache(); }) + .add('fetchf with string cache key', () => { + return requestWithStringCache(); + }) .on('cycle', (event) => { console.log(String(event.target)); }) From 767130b3dd408fc278910a43ca1159b2ed7fc72a Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Feb 2026 01:55:54 +0100 Subject: [PATCH 30/30] chore: Build --- dist/browser/index.global.js | 4 ++-- dist/browser/index.global.js.map | 2 +- dist/browser/index.mjs | 4 ++-- dist/browser/index.mjs.map | 2 +- dist/node/index.js | 4 ++-- dist/node/index.js.map | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dist/browser/index.global.js b/dist/browser/index.global.js index 430364d0..6736400c 100644 --- a/dist/browser/index.global.js +++ b/dist/browser/index.global.js @@ -1,3 +1,3 @@ -var fetchff=(function(exports){'use strict';var yt=Object.defineProperty;var Rt=(e,t,r)=>t in e?yt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var z=(e,t,r)=>Rt(e,typeof t!="symbol"?t+"":t,r);var w="application/",J=w+"json",Ne="charset=utf-8",C="Content-Type",R="undefined",k="object",b="string",g="function",re="AbortError",Se="TimeoutError",Q="GET",_e="HEAD",ae="reject";var Ue=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===k}function G(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=Ue)return r;let c,p,h;if(l)if(Array.isArray(i))for(c=0,p=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function se(e){return e.includes("://")}var P=()=>Date.now(),N=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function q(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function Ke(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function A(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;z(this,"status");z(this,"statusText");z(this,"config");z(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,W=1e3,Pt=ce*W,Te=Array(ce).fill(0).map(()=>[]),I=new Map,le=0,x=null,ze=([e,t])=>{I.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch(r){}},B=(e,t,r)=>{if(_(e),rPt||r%W!==0){I.set(e,[setTimeout(ze.bind(null,[e,t]),r)]);return}let a=r/W,n=(le+a)%ce;Te[n].push([e,t]),I.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Te[le];for(let o=0;o{let t=I.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}I.delete(e),!I.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=P(),u=H.get(e),l=null;if(u){let m=u[0],c=u[3];if(!c&&o-u[2]{ke(e,oe(t+" aborted due to timeout",Se));},r),i}async function ke(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),H.delete(e);}function Ge(e,t){let r=H.get(e);r&&(r[4]=t);}function be(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(N);});}async function me(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=P();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function gt(e){Ze(e);let t=e==="focus"?5:6;M.forEach((r,a)=>{r[t]&&Dt(a);});}function xe(e){if(U.has(e))return;let t=$e.bind(null,e,true),r=Ye.get(e);if(r){let a=r(t);U.set(e,a);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function Ze(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ve(e,t,r,a,n,s,o){let u=M.get(e);u?(u[0]=t,u[1]=P(),u[2]=We,u[3]=a,u[4]=n,u[5]=s,u[6]=o):M.set(e,[t,P(),We,a,n,s,o]),s&&xe("focus"),o&&xe("online"),a&&B("s:"+e,me.bind(null,e,true),a*1e3);}function Dt(e){M.delete(e),_("s:"+e);}var $=new Map;function Et(e){let t=$.get(e);return t||(t=new Set,$.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=$.get(e);r&&(r.delete(t),r.size===0&&$.delete(e));}function L(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?(Tt(e,t),()=>{bt(e,t);}):N}var we=(Ee()?60:30)*1e3,Z={strategy:ae,timeout:we,headers:{Accept:J+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:we/30,maxDelay:we,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function wt(e){let t=G(e);return j({},t,Z)}function tt(){return {...Z}}function qe(e,t){if(!t)return Xe(e,tt());let r=G(t),a=j(Z,r);return Xe(e,a)}function Xe(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let a;r!==Q&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==b&&ge(a)&&(a=JSON.stringify(a))),Ct(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),l=se(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function Ct(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(ge(t))r=J+";"+Ne;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),et("retry",e,t,r),et("headers",e,t,r),Ce("onRequest",e,t,r),Ce("onResponse",e,t,r),Ce("onError",e,t,r),r}function Ce(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],u=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?u.concat(o):o.concat(u);}function et(e,t,r,a){if(r[e]){let n=t[e],s=r[e];if(e==="headers"&&(n instanceof Headers||s instanceof Headers)){let o=q(n),u=q(s);a[e]={...o,...u};}else a[e]={...n,...s};}}var de=new Map,F="|",Ae=64,rt=/[^\w\-_|/:@.?=&~%#]/g,at=/[^\w\-_|/:@.?=&~%#]/,qt=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 V(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let c;s instanceof Headers?c=q(s):c=s;let p=Object.keys(c),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+c+"&";}),i.length>Ae&&(i=Y(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let c=d(o)?JSON.stringify(Me(o)):String(o);i=c.length>Ae?Y(c):c;}let m=n+F+a+F+u+F+l+F+i;return at.test(m)?m.replace(rt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function ye(e){return de.get(e)}function Re(e,t,r,a){if(r===0){pe(e);return}let n=P(),s=r?r*1e3:0,o=a?a*1e3:0;de.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&B("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!nt(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=ye(e);if(!a)return null;let n=d(t)?G(t):t,s={...a.data,data:n},o={...a,data:s};return de.set(e,o),L(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||Z.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=ye(e);return n?nt(n)?(pe(e),null):n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(a,e,n,t.staleTime),L(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function st(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(J)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===b){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===k&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let l=q(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function ot(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function At(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 u=ot(r);if(u!==null)return u}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?ot(s):null}async function it(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,D=f.onRetry;D&&(await A(D,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=V(f,false)));}c=await e(l>0,l);let p=c.error;if(!p){if(u&&l0&&await S(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await S(t);return o}async function lt(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await A(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&Bt(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ae)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function ct(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===re;}function Bt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe=Object.freeze({isFetching:true});async function he(e,t=null){let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,p=u!==void 0||l!==void 0,h=!!(s||a||o||p||n||i||m),f=null;if(h&&(f=V(r)),f&&p){let E=Pe(f,u,r);if(E)return E}if(f&&o){let E=be(f,o);if(E)return E}let D=r.retry||{},{retries:ft=0,resetTimeout:mt}=D,ve=async(E=false,ee=0)=>{ee||(f&&!E&&(l?Pe(f,u,r)||(Re(f,Oe,u,l),L(f,Oe)):L(f,Oe)),r.cacheKey=f);let O=r.url,dt=Je(f,O,a,o||0,!!n,!!(a&&(!ee||mt))),T=r;T.signal=dt.signal;let te,y=null;try{r.onRequest&&(f&&o&&!ee&&await null,await A(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await st(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);te=Fe(y,T);let K=r.onResponse;K&&await A(K,te);}catch(v){let K=v;ct(K,y,T),te=Fe(y,T,K);}return te},pt=ft>0?(E=false)=>it((ee,O)=>ve(E,O),D):ve,X=(E=false)=>lt(E,pt,r),Qe=c?ut(X,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):X();return f&&(o&&Ge(f,Qe),(l||i||m)&&Ve(f,X,void 0,l,X,!!i,!!m)),Qe}function Ft(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=se(l)?(o==null?void 0:o.url)===l?j(u,s):s:j(j(e,u),s);return he(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=ke;exports.addTimeout=B;exports.buildConfig=qe;exports.createAbortError=oe;exports.createApiFetcher=Ft;exports.deleteCache=pe;exports.fetchf=he;exports.fetchff=he;exports.generateCacheKey=V;exports.getCache=ye;exports.getCachedResponse=Pe;exports.getDefaultConfig=tt;exports.getInFlightPromise=be;exports.isSlowConnection=Ee;exports.mutate=Ie;exports.removeRevalidators=gt;exports.revalidate=me;exports.revalidateAll=$e;exports.setCache=Re;exports.setDefaultConfig=wt;exports.setEventProvider=ht;exports.subscribe=xt;return exports;})({});//# sourceMappingURL=index.global.js.map +var fetchff=(function(exports){'use strict';var yt=Object.defineProperty;var Rt=(e,t,r)=>t in e?yt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var z=(e,t,r)=>Rt(e,typeof t!="symbol"?t+"":t,r);var w="application/",J=w+"json",Ne="charset=utf-8",C="Content-Type",P="undefined",k="object",b="string",D="function",ae="AbortError",Se="TimeoutError",Q="GET",_e="HEAD",ne="reject";var Ue=10;function se(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===k}function G(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===D?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=Ue)return r;let c,p,g;if(l)if(Array.isArray(i))for(c=0,p=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function oe(e){return e.includes("://")}var h=()=>Date.now(),N=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==P&&typeof globalThis.Buffer!==P&&globalThis.Buffer.isBuffer(e)||e instanceof Date||se(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===D))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==P?De(e.data,t+1):e}function A(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function Ke(){return typeof window!==P&&typeof window.addEventListener===D}function ie(e,t){if(typeof DOMException!==P)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==P&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function I(e,t,...r){if(e){if(typeof e===D){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ue=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;z(this,"status");z(this,"statusText");z(this,"config");z(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var le=class extends ue{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var fe=600,W=1e3,Pt=fe*W,Te=Array(fe).fill(0).map(()=>[]),q=new Map,ce=0,x=null,ze=([e,t])=>{q.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch(r){}},B=(e,t,r)=>{if(_(e),rPt||r%W!==0){q.set(e,[setTimeout(ze.bind(null,[e,t]),r)]);return}let a=r/W,n=(ce+a)%fe;Te[n].push([e,t]),q.set(e,n),x||(x=setInterval(()=>{ce=(ce+1)%fe;let s=Te[ce];for(let o=0;o{let t=q.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}q.delete(e),!q.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=h(),u=H.get(e),l=null;if(u){let m=u[0],c=u[3];if(!c&&o-u[2]{ke(e,ie(t+" aborted due to timeout",Se));},r),i}async function ke(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),me(e));}}function me(e){_(e),H.delete(e);}function Ge(e,t){let r=H.get(e);r&&(r[4]=t);}function be(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&h()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(N);});}async function pe(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=h();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function gt(e){Ze(e);let t=e==="focus"?5:6;M.forEach((r,a)=>{r[t]&&Dt(a);});}function xe(e){if(U.has(e))return;let t=$e.bind(null,e,true),r=Ye.get(e);if(r){let a=r(t);U.set(e,a);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function Ze(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ve(e,t,r,a,n,s,o){let u=M.get(e);u?(u[0]=t,u[1]=h(),u[2]=We,u[3]=a,u[4]=n,u[5]=s,u[6]=o):M.set(e,[t,h(),We,a,n,s,o]),s&&xe("focus"),o&&xe("online"),a&&B("s:"+e,pe.bind(null,e,true),a*1e3);}function Dt(e){M.delete(e),_("s:"+e);}var $=new Map;function Et(e){let t=$.get(e);return t||(t=new Set,$.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=$.get(e);r&&(r.delete(t),r.size===0&&$.delete(e));}function L(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?(Tt(e,t),()=>{bt(e,t);}):N}var we=(Ee()?60:30)*1e3,Z={strategy:ne,timeout:we,headers:{Accept:J+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:we/30,maxDelay:we,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function wt(e){let t=G(e);return j({},t,Z)}function tt(){return {...Z}}function Ae(e,t){if(!t)return Xe(e,tt());let r=G(t),a=j(Z,r);return Xe(e,a)}function Xe(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let a;r!==Q&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==b&&ge(a)&&(a=JSON.stringify(a))),Ct(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),l=oe(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function Ct(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==P&&t instanceof Blob||typeof File!==P&&t instanceof File||typeof ReadableStream!==P&&t instanceof ReadableStream)return;let r;if(se(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(ge(t))r=J+";"+Ne;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),et("retry",e,t,r),et("headers",e,t,r),Ce("onRequest",e,t,r),Ce("onResponse",e,t,r),Ce("onError",e,t,r),r}function Ce(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],u=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?u.concat(o):o.concat(u);}function et(e,t,r,a){if(r[e]){let n=t[e],s=r[e];if(e==="headers"&&(n instanceof Headers||s instanceof Headers)){let o=A(n),u=A(s);a[e]={...o,...u};}else a[e]={...n,...s};}}var ye=new Map,F="|",Ie=64,rt=/[^\w\-_|/:@.?=&~%#]/g,at=/[^\w\-_|/:@.?=&~%#]/,At=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 V(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let c;s instanceof Headers?c=A(s):c=s;let p=Object.keys(c),g=p.length;g>1&&p.sort();let f="";for(let E=0;E{i+=p+"="+c+"&";}),i.length>Ie&&(i=Y(i));else if(typeof Blob!==P&&o instanceof Blob||typeof File!==P&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let c=d(o)?JSON.stringify(Me(o)):String(o);i=c.length>Ie?Y(c):c;}let m=n+F+a+F+u+F+l+F+i;return at.test(m)?m.replace(rt,""):m}function nt(e){return e.expiry?h()>e.expiry:false}function Re(e){return ye.get(e)}function Pe(e,t,r,a){if(r===0){de(e);return}let n=h(),s=r?r*1e3:0,o=a?a*1e3:0;ye.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&B("c:"+e,()=>{de(e,true);},s);}function de(e,t=false){if(t){let r=Re(e);if(!r||!nt(r))return}ye.delete(e);}async function qe(e,t,r){if(!e)return null;let a=Re(e);if(!a)return null;let n=d(t)?G(t):t,s={...a.data,data:n},o={...a,data:s};return ye.set(e,o),L(e,s),r&&r.refetch?await pe(e):null}function X(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||Z.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=Re(e);return n?nt(n)?(de(e),null):n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Pe(a,e,n,t.staleTime),L(a,e),me(a);let o=t._prevKey;o&&me(o);}}async function st(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(J)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===D)a=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===D)a=await e.blob();else if(a=await e.text(),typeof a===b){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=qe.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===D&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===k&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let l=A(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,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 It(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 u=ot(r);if(u!==null)return u}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?ot(s):null}async function it(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,E=f.onRetry;E&&(await I(E,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=V(f,false)));}c=await e(l>0,l);let p=c.error;if(!p){if(u&&l0&&await S(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await S(t);return o}async function lt(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await I(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&Bt(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ne)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function ct(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===ae;}function Bt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe=Object.freeze({isFetching:true});async function he(e,t=null){if(t&&typeof t.cacheKey=="string"){let R=X(t.cacheKey,t.cacheTime,t);if(R)return R}let r=Ae(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,p=u!==void 0||l!==void 0,g=!!(s||a||o||p||n||i||m),f=null;if(g&&(f=V(r)),f&&p){let R=X(f,u,r);if(R)return R}if(f&&o){let R=be(f,o);if(R)return R}let E=r.retry||{},{retries:ft=0,resetTimeout:mt}=E,ve=async(R=false,te=0)=>{te||(f&&!R&&(l?X(f,u,r)||(Pe(f,Oe,u,l),L(f,Oe)):L(f,Oe)),r.cacheKey=f);let O=r.url,dt=Je(f,O,a,o||0,!!n,!!(a&&(!te||mt))),T=r;T.signal=dt.signal;let re,y=null;try{r.onRequest&&(f&&o&&!te&&await null,await I(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===D&&y instanceof Response?y.data=await st(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new le(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);re=Fe(y,T);let K=r.onResponse;K&&await I(K,re);}catch(v){let K=v;ct(K,y,T),re=Fe(y,T,K);}return re},pt=ft>0?(R=false)=>it((te,O)=>ve(R,O),E):ve,ee=(R=false)=>lt(R,pt,r),Qe=c?ut(ee,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):ee();return f&&(o&&Ge(f,Qe),(l||i||m)&&Ve(f,ee,void 0,l,ee,!!i,!!m)),Qe}function Ft(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=oe(l)?(o==null?void 0:o.url)===l?j(u,s):s:j(j(e,u),s);return he(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} +exports.abortRequest=ke;exports.addTimeout=B;exports.buildConfig=Ae;exports.createAbortError=ie;exports.createApiFetcher=Ft;exports.deleteCache=de;exports.fetchf=he;exports.fetchff=he;exports.generateCacheKey=V;exports.getCache=Re;exports.getCachedResponse=X;exports.getDefaultConfig=tt;exports.getInFlightPromise=be;exports.isSlowConnection=Ee;exports.mutate=qe;exports.removeRevalidators=gt;exports.revalidate=pe;exports.revalidateAll=$e;exports.setCache=Pe;exports.setDefaultConfig=wt;exports.setEventProvider=ht;exports.subscribe=xt;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 816337f8..6d022f4a 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","cached","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/browser/index.mjs b/dist/browser/index.mjs index 7a5f477a..281457ad 100644 --- a/dist/browser/index.mjs +++ b/dist/browser/index.mjs @@ -1,3 +1,3 @@ -var yt=Object.defineProperty;var Rt=(e,t,r)=>t in e?yt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var z=(e,t,r)=>Rt(e,typeof t!="symbol"?t+"":t,r);var w="application/",J=w+"json",Ne="charset=utf-8",C="Content-Type",R="undefined",k="object",b="string",g="function",re="AbortError",Se="TimeoutError",Q="GET",_e="HEAD",ae="reject";var Ue=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===k}function G(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=Ue)return r;let c,p,h;if(l)if(Array.isArray(i))for(c=0,p=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function se(e){return e.includes("://")}var P=()=>Date.now(),N=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==R?De(e.data,t+1):e}function q(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function Ke(){return typeof window!==R&&typeof window.addEventListener===g}function oe(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function A(e,t,...r){if(e){if(typeof e===g){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;z(this,"status");z(this,"statusText");z(this,"config");z(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,W=1e3,Pt=ce*W,Te=Array(ce).fill(0).map(()=>[]),I=new Map,le=0,x=null,ze=([e,t])=>{I.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch(r){}},B=(e,t,r)=>{if(_(e),rPt||r%W!==0){I.set(e,[setTimeout(ze.bind(null,[e,t]),r)]);return}let a=r/W,n=(le+a)%ce;Te[n].push([e,t]),I.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Te[le];for(let o=0;o{let t=I.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}I.delete(e),!I.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=P(),u=H.get(e),l=null;if(u){let m=u[0],c=u[3];if(!c&&o-u[2]{ke(e,oe(t+" aborted due to timeout",Se));},r),i}async function ke(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),H.delete(e);}function Ge(e,t){let r=H.get(e);r&&(r[4]=t);}function be(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(N);});}async function me(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=P();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function gt(e){Ze(e);let t=e==="focus"?5:6;M.forEach((r,a)=>{r[t]&&Dt(a);});}function xe(e){if(U.has(e))return;let t=$e.bind(null,e,true),r=Ye.get(e);if(r){let a=r(t);U.set(e,a);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function Ze(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ve(e,t,r,a,n,s,o){let u=M.get(e);u?(u[0]=t,u[1]=P(),u[2]=We,u[3]=a,u[4]=n,u[5]=s,u[6]=o):M.set(e,[t,P(),We,a,n,s,o]),s&&xe("focus"),o&&xe("online"),a&&B("s:"+e,me.bind(null,e,true),a*1e3);}function Dt(e){M.delete(e),_("s:"+e);}var $=new Map;function Et(e){let t=$.get(e);return t||(t=new Set,$.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=$.get(e);r&&(r.delete(t),r.size===0&&$.delete(e));}function L(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?(Tt(e,t),()=>{bt(e,t);}):N}var we=(Ee()?60:30)*1e3,Z={strategy:ae,timeout:we,headers:{Accept:J+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:we/30,maxDelay:we,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function wt(e){let t=G(e);return j({},t,Z)}function tt(){return {...Z}}function qe(e,t){if(!t)return Xe(e,tt());let r=G(t),a=j(Z,r);return Xe(e,a)}function Xe(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let a;r!==Q&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==b&&ge(a)&&(a=JSON.stringify(a))),Ct(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),l=se(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function Ct(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(ge(t))r=J+";"+Ne;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),et("retry",e,t,r),et("headers",e,t,r),Ce("onRequest",e,t,r),Ce("onResponse",e,t,r),Ce("onError",e,t,r),r}function Ce(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],u=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?u.concat(o):o.concat(u);}function et(e,t,r,a){if(r[e]){let n=t[e],s=r[e];if(e==="headers"&&(n instanceof Headers||s instanceof Headers)){let o=q(n),u=q(s);a[e]={...o,...u};}else a[e]={...n,...s};}}var de=new Map,F="|",Ae=64,rt=/[^\w\-_|/:@.?=&~%#]/g,at=/[^\w\-_|/:@.?=&~%#]/,qt=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 V(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let c;s instanceof Headers?c=q(s):c=s;let p=Object.keys(c),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+c+"&";}),i.length>Ae&&(i=Y(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let c=d(o)?JSON.stringify(Me(o)):String(o);i=c.length>Ae?Y(c):c;}let m=n+F+a+F+u+F+l+F+i;return at.test(m)?m.replace(rt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function ye(e){return de.get(e)}function Re(e,t,r,a){if(r===0){pe(e);return}let n=P(),s=r?r*1e3:0,o=a?a*1e3:0;de.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&B("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!nt(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=ye(e);if(!a)return null;let n=d(t)?G(t):t,s={...a.data,data:n},o={...a,data:s};return de.set(e,o),L(e,s),r&&r.refetch?await me(e):null}function Pe(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||Z.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=ye(e);return n?nt(n)?(pe(e),null):n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(a,e,n,t.staleTime),L(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function st(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(J)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===g)a=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===g)a=await e.blob();else if(a=await e.text(),typeof a===b){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.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===g&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===k&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let l=q(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function ot(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function At(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 u=ot(r);if(u!==null)return u}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?ot(s):null}async function it(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,D=f.onRetry;D&&(await A(D,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=V(f,false)));}c=await e(l>0,l);let p=c.error;if(!p){if(u&&l0&&await S(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await S(t);return o}async function lt(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await A(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&Bt(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ae)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function ct(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===re;}function Bt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe=Object.freeze({isFetching:true});async function he(e,t=null){let r=qe(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,p=u!==void 0||l!==void 0,h=!!(s||a||o||p||n||i||m),f=null;if(h&&(f=V(r)),f&&p){let E=Pe(f,u,r);if(E)return E}if(f&&o){let E=be(f,o);if(E)return E}let D=r.retry||{},{retries:ft=0,resetTimeout:mt}=D,ve=async(E=false,ee=0)=>{ee||(f&&!E&&(l?Pe(f,u,r)||(Re(f,Oe,u,l),L(f,Oe)):L(f,Oe)),r.cacheKey=f);let O=r.url,dt=Je(f,O,a,o||0,!!n,!!(a&&(!ee||mt))),T=r;T.signal=dt.signal;let te,y=null;try{r.onRequest&&(f&&o&&!ee&&await null,await A(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await st(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);te=Fe(y,T);let K=r.onResponse;K&&await A(K,te);}catch(v){let K=v;ct(K,y,T),te=Fe(y,T,K);}return te},pt=ft>0?(E=false)=>it((ee,O)=>ve(E,O),D):ve,X=(E=false)=>lt(E,pt,r),Qe=c?ut(X,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):X();return f&&(o&&Ge(f,Qe),(l||i||m)&&Ve(f,X,void 0,l,X,!!i,!!m)),Qe}function Ft(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=se(l)?(o==null?void 0:o.url)===l?j(u,s):s:j(j(e,u),s);return he(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} -export{ke as abortRequest,B as addTimeout,qe as buildConfig,oe as createAbortError,Ft as createApiFetcher,pe as deleteCache,he as fetchf,he as fetchff,V as generateCacheKey,ye as getCache,Pe as getCachedResponse,tt as getDefaultConfig,be as getInFlightPromise,Ee as isSlowConnection,Ie as mutate,gt as removeRevalidators,me as revalidate,$e as revalidateAll,Re as setCache,wt as setDefaultConfig,ht as setEventProvider,xt as subscribe};//# sourceMappingURL=index.mjs.map +var yt=Object.defineProperty;var Rt=(e,t,r)=>t in e?yt(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var z=(e,t,r)=>Rt(e,typeof t!="symbol"?t+"":t,r);var w="application/",J=w+"json",Ne="charset=utf-8",C="Content-Type",P="undefined",k="object",b="string",D="function",ae="AbortError",Se="TimeoutError",Q="GET",_e="HEAD",ne="reject";var Ue=10;function se(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===k}function G(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Me(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===D?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(l)+"="+a(i);},s=(l,i,m=0)=>{if(m>=Ue)return r;let c,p,g;if(l)if(Array.isArray(i))for(c=0,p=i.length;c{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function oe(e){return e.includes("://")}var h=()=>Date.now(),N=()=>{};function ge(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==P&&typeof globalThis.Buffer!==P&&globalThis.Buffer.isBuffer(e)||e instanceof Date||se(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===D))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function De(e,t=0){return t>=Ue?e:e&&d(e)&&typeof e.data!==P?De(e.data,t+1):e}function A(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function Ke(){return typeof window!==P&&typeof window.addEventListener===D}function ie(e,t){if(typeof DOMException!==P)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var Ee=()=>{let e=typeof navigator!==P&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function I(e,t,...r){if(e){if(typeof e===D){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ue=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;z(this,"status");z(this,"statusText");z(this,"config");z(this,"isCancelled");this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}};var le=class extends ue{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var fe=600,W=1e3,Pt=fe*W,Te=Array(fe).fill(0).map(()=>[]),q=new Map,ce=0,x=null,ze=([e,t])=>{q.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch(r){}},B=(e,t,r)=>{if(_(e),rPt||r%W!==0){q.set(e,[setTimeout(ze.bind(null,[e,t]),r)]);return}let a=r/W,n=(ce+a)%fe;Te[n].push([e,t]),q.set(e,n),x||(x=setInterval(()=>{ce=(ce+1)%fe;let s=Te[ce];for(let o=0;o{let t=q.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Te[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}q.delete(e),!q.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function Je(e,t,r,a,n,s){if(!e)return new AbortController;let o=h(),u=H.get(e),l=null;if(u){let m=u[0],c=u[3];if(!c&&o-u[2]{ke(e,ie(t+" aborted due to timeout",Se));},r),i}async function ke(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),me(e));}}function me(e){_(e),H.delete(e);}function Ge(e,t){let r=H.get(e);r&&(r[4]=t);}function be(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&h()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(N);});}async function pe(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=h();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function gt(e){Ze(e);let t=e==="focus"?5:6;M.forEach((r,a)=>{r[t]&&Dt(a);});}function xe(e){if(U.has(e))return;let t=$e.bind(null,e,true),r=Ye.get(e);if(r){let a=r(t);U.set(e,a);return}Ke()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function Ze(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ve(e,t,r,a,n,s,o){let u=M.get(e);u?(u[0]=t,u[1]=h(),u[2]=We,u[3]=a,u[4]=n,u[5]=s,u[6]=o):M.set(e,[t,h(),We,a,n,s,o]),s&&xe("focus"),o&&xe("online"),a&&B("s:"+e,pe.bind(null,e,true),a*1e3);}function Dt(e){M.delete(e),_("s:"+e);}var $=new Map;function Et(e){let t=$.get(e);return t||(t=new Set,$.set(e,t)),t}function Tt(e,t){Et(e).add(t);}function bt(e,t){let r=$.get(e);r&&(r.delete(t),r.size===0&&$.delete(e));}function L(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?(Tt(e,t),()=>{bt(e,t);}):N}var we=(Ee()?60:30)*1e3,Z={strategy:ne,timeout:we,headers:{Accept:J+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:we/30,maxDelay:we,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function wt(e){let t=G(e);return j({},t,Z)}function tt(){return {...Z}}function Ae(e,t){if(!t)return Xe(e,tt());let r=G(t),a=j(Z,r);return Xe(e,a)}function Xe(e,t){var i;let r=t.method;r=r?r.toUpperCase():Q;let a;r!==Q&&r!==_e&&(a=(i=t.body)!=null?i:t.data,a&&typeof a!==b&&ge(a)&&(a=JSON.stringify(a))),Ct(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=je(e,t.urlPathParams),o=Le(s,t.params),l=oe(e)?"":t.baseURL||t.apiUrl||"";return t.url=l+o,t.method=r,t.credentials=n,t.body=a,t}function Ct(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==P&&t instanceof Blob||typeof File!==P&&t instanceof File||typeof ReadableStream!==P&&t instanceof ReadableStream)return;let r;if(se(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(ge(t))r=J+";"+Ne;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),et("retry",e,t,r),et("headers",e,t,r),Ce("onRequest",e,t,r),Ce("onResponse",e,t,r),Ce("onError",e,t,r),r}function Ce(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],u=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?u.concat(o):o.concat(u);}function et(e,t,r,a){if(r[e]){let n=t[e],s=r[e];if(e==="headers"&&(n instanceof Headers||s instanceof Headers)){let o=A(n),u=A(s);a[e]={...o,...u};}else a[e]={...n,...s};}}var ye=new Map,F="|",Ie=64,rt=/[^\w\-_|/:@.?=&~%#]/g,at=/[^\w\-_|/:@.?=&~%#]/,At=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 V(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,l="";if(s){let c;s instanceof Headers?c=A(s):c=s;let p=Object.keys(c),g=p.length;g>1&&p.sort();let f="";for(let E=0;E{i+=p+"="+c+"&";}),i.length>Ie&&(i=Y(i));else if(typeof Blob!==P&&o instanceof Blob||typeof File!==P&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let c=d(o)?JSON.stringify(Me(o)):String(o);i=c.length>Ie?Y(c):c;}let m=n+F+a+F+u+F+l+F+i;return at.test(m)?m.replace(rt,""):m}function nt(e){return e.expiry?h()>e.expiry:false}function Re(e){return ye.get(e)}function Pe(e,t,r,a){if(r===0){de(e);return}let n=h(),s=r?r*1e3:0,o=a?a*1e3:0;ye.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&B("c:"+e,()=>{de(e,true);},s);}function de(e,t=false){if(t){let r=Re(e);if(!r||!nt(r))return}ye.delete(e);}async function qe(e,t,r){if(!e)return null;let a=Re(e);if(!a)return null;let n=d(t)?G(t):t,s={...a.data,data:n},o={...a,data:s};return ye.set(e,o),L(e,s),r&&r.refetch?await pe(e):null}function X(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||Z.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=Re(e);return n?nt(n)?(de(e),null):n.data:null}function Be(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Pe(a,e,n,t.staleTime),L(a,e),me(a);let o=t._prevKey;o&&me(o);}}async function st(e){var n;if(!e)return null;let t=(n=e.headers)==null?void 0:n.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(J)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===D)a=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===D)a=await e.blob();else if(a=await e.text(),typeof a===b){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 Fe=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=qe.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===D&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===k&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=De(u)),t.select&&(e.data=u=t.select(u));let l=A(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:l,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=l,e.isFetching=false,e.mutate=s,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 It(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 u=ot(r);if(u!==null)return u}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?ot(s):null}async function it(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,l=0,i=a,m=r>0?r:0,c;for(;l<=m;){if(l>0&&c){let f=c.config,E=f.onRetry;E&&(await I(E,c,l),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=V(f,false)));}c=await e(l>0,l);let p=c.error;if(!p){if(u&&l0&&await S(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await S(t);return o}async function lt(e,t,r){let a=await t(e),n=a.error;if(!n)return Be(a,r),a;r.onError&&await I(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&Bt(r,"FETCH ERROR",n),Be(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ne)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function ct(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===ae;}function Bt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Oe=Object.freeze({isFetching:true});async function he(e,t=null){if(t&&typeof t.cacheKey=="string"){let R=X(t.cacheKey,t.cacheTime,t);if(R)return R}let r=Ae(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:l,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:c=0}=r,p=u!==void 0||l!==void 0,g=!!(s||a||o||p||n||i||m),f=null;if(g&&(f=V(r)),f&&p){let R=X(f,u,r);if(R)return R}if(f&&o){let R=be(f,o);if(R)return R}let E=r.retry||{},{retries:ft=0,resetTimeout:mt}=E,ve=async(R=false,te=0)=>{te||(f&&!R&&(l?X(f,u,r)||(Pe(f,Oe,u,l),L(f,Oe)):L(f,Oe)),r.cacheKey=f);let O=r.url,dt=Je(f,O,a,o||0,!!n,!!(a&&(!te||mt))),T=r;T.signal=dt.signal;let re,y=null;try{r.onRequest&&(f&&o&&!te&&await null,await I(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===D&&y instanceof Response?y.data=await st(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new le(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);re=Fe(y,T);let K=r.onResponse;K&&await I(K,re);}catch(v){let K=v;ct(K,y,T),re=Fe(y,T,K);}return re},pt=ft>0?(R=false)=>it((te,O)=>ve(R,O),E):ve,ee=(R=false)=>lt(R,pt,r),Qe=c?ut(ee,c,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):ee();return f&&(o&&Ge(f,Qe),(l||i||m)&&Ve(f,ee,void 0,l,ee,!!i,!!m)),Qe}function Ft(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=t[n],u=o||{url:String(n)},l=u.url;if(l.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=oe(l)?(o==null?void 0:o.url)===l?j(u,s):s:j(j(e,u),s);return he(l,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} +export{ke as abortRequest,B as addTimeout,Ae as buildConfig,ie as createAbortError,Ft as createApiFetcher,de as deleteCache,he as fetchf,he as fetchff,V as generateCacheKey,Re as getCache,X as getCachedResponse,tt as getDefaultConfig,be as getInFlightPromise,Ee as isSlowConnection,qe as mutate,gt as removeRevalidators,pe as revalidate,$e as revalidateAll,Pe as setCache,wt as setDefaultConfig,ht as setEventProvider,xt 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 7ab60d97..b2c6a805 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","__publicField","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","e","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","_a","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","cached","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file diff --git a/dist/node/index.js b/dist/node/index.js index d8f16b39..a340480b 100644 --- a/dist/node/index.js +++ b/dist/node/index.js @@ -1,3 +1,3 @@ -'use strict';var w="application/",z=w+"json",Qe="charset=utf-8",C="Content-Type",R="undefined",J="object",b="string",g="function",te="AbortError",Ne="TimeoutError",Q="GET",Se="HEAD",re="reject";var He=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===J}function k(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),n=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!n)return e;let a={...e};return t&&delete a.__proto__,r&&delete a.constructor,n&&delete a.prototype,a}function Ue(e){let t=Object.keys(e);t.sort();let r={};for(let n=0,a=t.length;n{i=typeof i===g?i():i,i=i===null||i===void 0?"":i,r[r.length]=n(c)+"="+n(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,h;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,a)){let s=r[a];if(s!=null)return encodeURIComponent(String(s))}return n})}function ae(e){return e.includes("://")}var P=()=>Date.now(),N=()=>{};function he(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==R&&typeof globalThis.Buffer!==R&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===g))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function ge(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==R?ge(e.data,t+1):e}function q(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,n)=>{t[n.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function je(){return typeof window!==R&&typeof window.addEventListener===g}function se(e,t){if(typeof DOMException!==R)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var De=()=>{let e=typeof navigator!==R&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function A(e,t,...r){if(e){if(typeof e===g){let n=await e(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}else if(Array.isArray(e))for(let n of e){let a=await n(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}}}var oe=class extends Error{constructor(r,n,a){super(r);this.request=n;this.response=a;this.name="FetchError",this.status=a?a.status:0,this.statusText=a?a.statusText:"",this.config=n,this.isCancelled=false;}status;statusText;config;isCancelled};var ie=class extends oe{constructor(t,r,n){super(t,r,n),this.name="ResponseError";}};var le=600,G=1e3,dt=le*G,Ee=Array(le).fill(0).map(()=>[]),I=new Map,ue=0,x=null,Ke=([e,t])=>{I.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch{}},B=(e,t,r)=>{if(_(e),rdt||r%G!==0){I.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let n=r/G,a=(ue+n)%le;Ee[a].push([e,t]),I.set(e,a),x||(x=setInterval(()=>{ue=(ue+1)%le;let s=Ee[ue];for(let o=0;o{let t=I.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],n=r.findIndex(([a])=>a===e);n!==-1&&r.splice(n,1);}I.delete(e),!I.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function ze(e,t,r,n,a,s){if(!e)return new AbortController;let o=P(),u=H.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{Je(e,se(t+" aborted due to timeout",Ne));},r),i}async function Je(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),ce(e));}}function ce(e){_(e),H.delete(e);}function ke(e,t){let r=H.get(e);r&&(r[4]=t);}function Te(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&P()-r[2]{if(!a[r])return;a[1]=n;let s=t?a[4]:a[0];s&&Promise.resolve(s(t)).catch(N);});}async function fe(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=P();let n=t?r[4]:r[0];if(n)return await n(t)}return null}function Rt(e){$e(e);let t=e==="focus"?5:6;M.forEach((r,n)=>{r[t]&&Pt(n);});}function be(e){if(U.has(e))return;let t=Ye.bind(null,e,true),r=We.get(e);if(r){let n=r(t);U.set(e,n);return}je()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function $e(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ze(e,t,r,n,a,s,o){let u=M.get(e);u?(u[0]=t,u[1]=P(),u[2]=Ge,u[3]=n,u[4]=a,u[5]=s,u[6]=o):M.set(e,[t,P(),Ge,n,a,s,o]),s&&be("focus"),o&&be("online"),n&&B("s:"+e,fe.bind(null,e,true),n*1e3);}function Pt(e){M.delete(e),_("s:"+e);}var Y=new Map;function ht(e){let t=Y.get(e);return t||(t=new Set,Y.set(e,t)),t}function gt(e,t){ht(e).add(t);}function Dt(e,t){let r=Y.get(e);r&&(r.delete(t),r.size===0&&Y.delete(e));}function L(e,t){let r=Y.get(e);if(r)if(r.size===1){let n=r.values().next().value;n(t);}else r.forEach(n=>n(t));}function Et(e,t){return e?(gt(e,t),()=>{Dt(e,t);}):N}var xe=(De()?60:30)*1e3,$={strategy:re,timeout:xe,headers:{Accept:z+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:xe/30,maxDelay:xe,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Tt(e){let t=k(e);return j({},t,$)}function et(){return {...$}}function Ce(e,t){if(!t)return Ve(e,et());let r=k(t),n=j($,r);return Ve(e,n)}function Ve(e,t){let r=t.method;r=r?r.toUpperCase():Q;let n;r!==Q&&r!==Se&&(n=t.body??t.data,n&&typeof n!==b&&he(n)&&(n=JSON.stringify(n))),bt(t.headers,n);let a=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),c=ae(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=a,t.body=n,t}function bt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==R&&t instanceof Blob||typeof File!==R&&t instanceof File||typeof ReadableStream!==R&&t instanceof ReadableStream)return;let r;if(ne(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(he(t))r=z+";"+Qe;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),Xe("retry",e,t,r),Xe("headers",e,t,r),we("onRequest",e,t,r),we("onResponse",e,t,r),we("onError",e,t,r),r}function we(e,t,r,n){let a=t[e],s=r[e];if(!a&&!s)return;if(!a){n[e]=s;return}if(!s){n[e]=a;return}let o=Array.isArray(a)?a:[a],u=Array.isArray(s)?s:[s];n[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Xe(e,t,r,n){if(r[e]){let a=t[e],s=r[e];if(e==="headers"&&(a instanceof Headers||s instanceof Headers)){let o=q(a),u=q(s);n[e]={...o,...u};}else n[e]={...a,...s};}}var pe=new Map,F="|",qe=64,tt=/[^\w\-_|/:@.?=&~%#]/g,rt=/[^\w\-_|/:@.?=&~%#]/,xt=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 Z(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:n="",method:a=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=q(s):l=s;let p=Object.keys(l),h=p.length;h>1&&p.sort();let f="";for(let D=0;D{i+=p+"="+l+"&";}),i.length>qe&&(i=W(i));else if(typeof Blob!==R&&o instanceof Blob||typeof File!==R&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Ue(o)):String(o);i=l.length>qe?W(l):l;}let m=a+F+n+F+u+F+c+F+i;return rt.test(m)?m.replace(tt,""):m}function nt(e){return e.expiry?P()>e.expiry:false}function de(e){return pe.get(e)}function ye(e,t,r,n){if(r===0){me(e);return}let a=P(),s=r?r*1e3:0,o=n?n*1e3:0;pe.set(e,{data:t,time:a,stale:o>0?a+o:void 0,expiry:r===-1?void 0:a+s}),s>0&&B("c:"+e,()=>{me(e,true);},s);}function me(e,t=false){if(t){let r=de(e);if(!r||!nt(r))return}pe.delete(e);}async function Ae(e,t,r){if(!e)return null;let n=de(e);if(!n)return null;let a=d(t)?k(t):t,s={...n.data,data:a},o={...n,data:s};return pe.set(e,o),L(e,s),r&&r.refetch?await fe(e):null}function Re(e,t,r){if(!e||t===void 0||t===null)return null;let n=r.cacheBuster||$.cacheBuster;if(n&&n(r)||r.cache&&r.cache==="reload")return null;let a=de(e);return a?nt(a)?(me(e),null):a.data:null}function Ie(e,t,r=false){let n=t.cacheKey;if(n){let a=t.cacheTime,s=t.skipCache;a&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&ye(n,e,a,t.staleTime),L(n,e),ce(n);let o=t._prevKey;o&&ce(o);}}async function at(e){if(!e)return null;let t=e.headers?.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],n;try{if(r.includes(z)||r.includes("+json"))n=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===g)n=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===g)n=await e.blob();else if(n=await e.text(),typeof n===b){let a=n.trim();if(a.startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]"))try{n=JSON.parse(a);}catch{}}}catch{n=null;}return n}var Be=(e,t,r=null)=>{let n=t.defaultResponse,a=t.cacheKey,s=Ae.bind(null,a);if(!e)return {ok:false,error:r,data:n??null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===g&&e instanceof Response,u=e.data;n!==void 0&&(u==null||typeof u===J&&Object.keys(u).length===0)&&(e.data=u=n),t.flattenResponse&&(e.data=u=ge(u)),t.select&&(e.data=u=t.select(u));let c=q(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function st(e){let t=Date.parse(e)-P();return isNaN(t)?null:Math.max(0,Math.floor(t))}function wt(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 u=st(r);if(u!==null)return u}let n="ratelimit-reset",a=t[n+"-after"]||t["x-"+n+"-after"];if(a){let o=Number(a);if(!isNaN(o))return o*1e3}let s=t[n+"-at"]||t["x-"+n+"-at"];return s?st(s):null}async function ot(e,t){let{retries:r=0,delay:n=0,backoff:a=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=n,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,D=f.onRetry;D&&(await A(D,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Z(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await S(a),o=await e(),s++,!(n>0&&s>=n||!t||r&&r(o,s)));)await S(t);return o}async function ut(e,t,r){let n=await t(e),a=n.error;if(!a)return Ie(n,r),n;r.onError&&await A(r.onError,a);let s=a.isCancelled;if(!s&&r.logger&&qt(r,"FETCH ERROR",a),Ie(n,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===re)return Promise.reject(a);u==="silent"&&await new Promise(()=>null);}return n}function lt(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===te;}function qt(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Fe=Object.freeze({isFetching:true});async function Pe(e,t=null){let r=Ce(e,t),{timeout:n,cancellable:a,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,h=!!(s||n||o||p||a||i||m),f=null;if(h&&(f=Z(r)),f&&p){let E=Re(f,u,r);if(E)return E}if(f&&o){let E=Te(f,o);if(E)return E}let D=r.retry||{},{retries:ct=0,resetTimeout:ft}=D,Oe=async(E=false,X=0)=>{X||(f&&!E&&(c?Re(f,u,r)||(ye(f,Fe,u,c),L(f,Fe)):L(f,Fe)),r.cacheKey=f);let O=r.url,pt=ze(f,O,n,o||0,!!a,!!(n&&(!X||ft))),T=r;T.signal=pt.signal;let ee,y=null;try{r.onRequest&&(f&&o&&!X&&await null,await A(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===g&&y instanceof Response?y.data=await at(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ie(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);ee=Be(y,T);let K=r.onResponse;K&&await A(K,ee);}catch(v){let K=v;lt(K,y,T),ee=Be(y,T,K);}return ee},mt=ct>0?(E=false)=>ot((X,O)=>Oe(E,O),D):Oe,V=(E=false)=>ut(E,mt,r),ve=l?it(V,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):V();return f&&(o&&ke(f,ve),(c||i||m)&&Ze(f,V,void 0,c,V,!!i,!!m)),ve}function At(e){let t=e.endpoints;function r(a){return console.error(`Add ${a} to 'endpoints'.`),Promise.resolve(null)}let n={config:e,endpoints:t,async request(a,s={}){let o=t[a],u=o||{url:String(a)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=ae(c)?o?.url===c?j(u,s):s:j(j(e,u),s);return Pe(c,i)}};return new Proxy(n,{get(a,s){return s in n?n[s]:t[s]?n.request.bind(null,s):r.bind(null,s)}})} -exports.abortRequest=Je;exports.addTimeout=B;exports.buildConfig=Ce;exports.createAbortError=se;exports.createApiFetcher=At;exports.deleteCache=me;exports.fetchf=Pe;exports.fetchff=Pe;exports.generateCacheKey=Z;exports.getCache=de;exports.getCachedResponse=Re;exports.getDefaultConfig=et;exports.getInFlightPromise=Te;exports.isSlowConnection=De;exports.mutate=Ae;exports.removeRevalidators=Rt;exports.revalidate=fe;exports.revalidateAll=Ye;exports.setCache=ye;exports.setDefaultConfig=Tt;exports.setEventProvider=yt;exports.subscribe=Et;//# sourceMappingURL=index.js.map +'use strict';var w="application/",z=w+"json",Qe="charset=utf-8",C="Content-Type",P="undefined",J="object",b="string",D="function",re="AbortError",Ne="TimeoutError",Q="GET",Se="HEAD",ae="reject";var He=10;function ne(e){return e instanceof URLSearchParams}function d(e){return e!==null&&typeof e===J}function k(e){let t=Object.prototype.hasOwnProperty.call(e,"__proto__"),r=Object.prototype.hasOwnProperty.call(e,"constructor"),a=Object.prototype.hasOwnProperty.call(e,"prototype");if(!t&&!r&&!a)return e;let n={...e};return t&&delete n.__proto__,r&&delete n.constructor,a&&delete n.prototype,n}function Ue(e){let t=Object.keys(e);t.sort();let r={};for(let a=0,n=t.length;a{i=typeof i===D?i():i,i=i===null||i===void 0?"":i,r[r.length]=a(c)+"="+a(i);},s=(c,i,m=0)=>{if(m>=He)return r;let l,p,g;if(c)if(Array.isArray(i))for(l=0,p=i.length;l{if(Object.prototype.hasOwnProperty.call(r,n)){let s=r[n];if(s!=null)return encodeURIComponent(String(s))}return a})}function se(e){return e.includes("://")}var h=()=>Date.now(),N=()=>{};function he(e){let t=typeof e;return e==null?false:t===b||t==="number"||t==="boolean"||Array.isArray(e)?true:typeof globalThis!==P&&typeof globalThis.Buffer!==P&&globalThis.Buffer.isBuffer(e)||e instanceof Date||ne(e)?false:!!(d(e)&&(Object.getPrototypeOf(e)===Object.prototype||typeof e.toJSON===D))}async function S(e){return new Promise(t=>setTimeout(()=>t(true),e))}function ge(e,t=0){return t>=He?e:e&&d(e)&&typeof e.data!==P?ge(e.data,t+1):e}function A(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((r,a)=>{t[a.toLowerCase()]=r;});else if(d(e))for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r.toLowerCase()]=e[r]);return t}function je(){return typeof window!==P&&typeof window.addEventListener===D}function oe(e,t){if(typeof DOMException!==P)return new DOMException(e,t);let r=new Error(e);return r.name=t,r}var De=()=>{let e=typeof navigator!==P&&navigator.connection;return e&&["slow-2g","2g","3g"].includes(e.effectiveType)};async function I(e,t,...r){if(e){if(typeof e===D){let a=await e(t,...r);a&&d(t)&&d(a)&&Object.assign(t,a);}else if(Array.isArray(e))for(let a of e){let n=await a(t,...r);n&&d(t)&&d(n)&&Object.assign(t,n);}}}var ie=class extends Error{constructor(r,a,n){super(r);this.request=a;this.response=n;this.name="FetchError",this.status=n?n.status:0,this.statusText=n?n.statusText:"",this.config=a,this.isCancelled=false;}status;statusText;config;isCancelled};var ue=class extends ie{constructor(t,r,a){super(t,r,a),this.name="ResponseError";}};var ce=600,G=1e3,dt=ce*G,Ee=Array(ce).fill(0).map(()=>[]),q=new Map,le=0,x=null,Ke=([e,t])=>{q.delete(e);try{let r=t();r&&r instanceof Promise&&r.catch(N);}catch{}},B=(e,t,r)=>{if(_(e),rdt||r%G!==0){q.set(e,[setTimeout(Ke.bind(null,[e,t]),r)]);return}let a=r/G,n=(le+a)%ce;Ee[n].push([e,t]),q.set(e,n),x||(x=setInterval(()=>{le=(le+1)%ce;let s=Ee[le];for(let o=0;o{let t=q.get(e);if(t!==void 0){if(Array.isArray(t))clearTimeout(t[0]);else {let r=Ee[t],a=r.findIndex(([n])=>n===e);a!==-1&&r.splice(a,1);}q.delete(e),!q.size&&x&&(clearInterval(x),x=null);}};var H=new Map;function ze(e,t,r,a,n,s){if(!e)return new AbortController;let o=h(),u=H.get(e),c=null;if(u){let m=u[0],l=u[3];if(!l&&o-u[2]{Je(e,oe(t+" aborted due to timeout",Ne));},r),i}async function Je(e,t=null){if(e){let r=H.get(e);r&&(t&&r[0].abort(t),fe(e));}}function fe(e){_(e),H.delete(e);}function ke(e,t){let r=H.get(e);r&&(r[4]=t);}function Te(e,t){if(!e)return null;let r=H.get(e);return r&&r[4]&&!r[3]&&h()-r[2]{if(!n[r])return;n[1]=a;let s=t?n[4]:n[0];s&&Promise.resolve(s(t)).catch(N);});}async function me(e,t=false){if(!e)return null;let r=M.get(e);if(r){r[1]=h();let a=t?r[4]:r[0];if(a)return await a(t)}return null}function Rt(e){$e(e);let t=e==="focus"?5:6;M.forEach((r,a)=>{r[t]&&Pt(a);});}function be(e){if(U.has(e))return;let t=Ye.bind(null,e,true),r=We.get(e);if(r){let a=r(t);U.set(e,a);return}je()&&(window.addEventListener(e,t),U.set(e,()=>window.removeEventListener(e,t)));}function $e(e){let t=U.get(e);t&&(t(),U.delete(e));}function Ze(e,t,r,a,n,s,o){let u=M.get(e);u?(u[0]=t,u[1]=h(),u[2]=Ge,u[3]=a,u[4]=n,u[5]=s,u[6]=o):M.set(e,[t,h(),Ge,a,n,s,o]),s&&be("focus"),o&&be("online"),a&&B("s:"+e,me.bind(null,e,true),a*1e3);}function Pt(e){M.delete(e),_("s:"+e);}var Y=new Map;function ht(e){let t=Y.get(e);return t||(t=new Set,Y.set(e,t)),t}function gt(e,t){ht(e).add(t);}function Dt(e,t){let r=Y.get(e);r&&(r.delete(t),r.size===0&&Y.delete(e));}function L(e,t){let r=Y.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);}):N}var xe=(De()?60:30)*1e3,$={strategy:ae,timeout:xe,headers:{Accept:z+", text/plain, */*","Accept-Encoding":"gzip, deflate, br"},retry:{delay:xe/30,maxDelay:xe,resetTimeout:true,backoff:1.5,retryOn:[408,409,425,429,500,502,503,504]}};function Tt(e){let t=k(e);return j({},t,$)}function et(){return {...$}}function Ce(e,t){if(!t)return Ve(e,et());let r=k(t),a=j($,r);return Ve(e,a)}function Ve(e,t){let r=t.method;r=r?r.toUpperCase():Q;let a;r!==Q&&r!==Se&&(a=t.body??t.data,a&&typeof a!==b&&he(a)&&(a=JSON.stringify(a))),bt(t.headers,a);let n=t.withCredentials?"include":t.credentials,s=Le(e,t.urlPathParams),o=Me(s,t.params),c=se(e)?"":t.baseURL||t.apiUrl||"";return t.url=c+o,t.method=r,t.credentials=n,t.body=a,t}function bt(e,t){if(!e||!t||t instanceof FormData||typeof Blob!==P&&t instanceof Blob||typeof File!==P&&t instanceof File||typeof ReadableStream!==P&&t instanceof ReadableStream)return;let r;if(ne(t))r=w+"x-www-form-urlencoded";else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))r=w+"octet-stream";else if(he(t))r=z+";"+Qe;else return;e instanceof Headers?e.has(C)||e.set(C,r):d(e)&&!Array.isArray(e)&&!e[C]&&(e[C]=r);}function j(e,t,r={}){return Object.assign(r,e,t),Xe("retry",e,t,r),Xe("headers",e,t,r),we("onRequest",e,t,r),we("onResponse",e,t,r),we("onError",e,t,r),r}function we(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],u=Array.isArray(s)?s:[s];a[e]=e==="onResponse"?u.concat(o):o.concat(u);}function Xe(e,t,r,a){if(r[e]){let n=t[e],s=r[e];if(e==="headers"&&(n instanceof Headers||s instanceof Headers)){let o=A(n),u=A(s);a[e]={...o,...u};}else a[e]={...n,...s};}}var de=new Map,F="|",Ae=64,tt=/[^\w\-_|/:@.?=&~%#]/g,rt=/[^\w\-_|/:@.?=&~%#]/,xt=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 Z(e,t=true){let r=e.cacheKey;if(r&&t)return typeof r===b?r:r(e);let{url:a="",method:n=Q,headers:s=null,body:o=null,credentials:u="same-origin"}=e,c="";if(s){let l;s instanceof Headers?l=A(s):l=s;let p=Object.keys(l),g=p.length;g>1&&p.sort();let f="";for(let E=0;E{i+=p+"="+l+"&";}),i.length>Ae&&(i=W(i));else if(typeof Blob!==P&&o instanceof Blob||typeof File!==P&&o instanceof File)i="BF"+o.size+o.type;else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))i="AB"+o.byteLength;else {let l=d(o)?JSON.stringify(Ue(o)):String(o);i=l.length>Ae?W(l):l;}let m=n+F+a+F+u+F+c+F+i;return rt.test(m)?m.replace(tt,""):m}function at(e){return e.expiry?h()>e.expiry:false}function ye(e){return de.get(e)}function Re(e,t,r,a){if(r===0){pe(e);return}let n=h(),s=r?r*1e3:0,o=a?a*1e3:0;de.set(e,{data:t,time:n,stale:o>0?n+o:void 0,expiry:r===-1?void 0:n+s}),s>0&&B("c:"+e,()=>{pe(e,true);},s);}function pe(e,t=false){if(t){let r=ye(e);if(!r||!at(r))return}de.delete(e);}async function Ie(e,t,r){if(!e)return null;let a=ye(e);if(!a)return null;let n=d(t)?k(t):t,s={...a.data,data:n},o={...a,data:s};return de.set(e,o),L(e,s),r&&r.refetch?await me(e):null}function V(e,t,r){if(!e||t===void 0||t===null)return null;let a=r.cacheBuster||$.cacheBuster;if(a&&a(r)||r.cache&&r.cache==="reload")return null;let n=ye(e);return n?at(n)?(pe(e),null):n.data:null}function qe(e,t,r=false){let a=t.cacheKey;if(a){let n=t.cacheTime,s=t.skipCache;n&&(!r||t.cacheErrors)&&!(s&&s(e,t))&&Re(a,e,n,t.staleTime),L(a,e),fe(a);let o=t._prevKey;o&&fe(o);}}async function nt(e){if(!e)return null;let t=e.headers?.get(C);t?t=t.toLowerCase().trim():t="";let r=t.split(";",1)[0],a;try{if(r.includes(z)||r.includes("+json"))a=await e.json();else if((r.includes("multipart/form-data")||r.includes(w+"x-www-form-urlencoded"))&&typeof e.formData===D)a=await e.formData();else if(r.includes(w+"octet-stream")&&typeof e.blob===D)a=await e.blob();else if(a=await e.text(),typeof a===b){let n=a.trim();if(n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]"))try{a=JSON.parse(n);}catch{}}}catch{a=null;}return a}var Be=(e,t,r=null)=>{let a=t.defaultResponse,n=t.cacheKey,s=Ie.bind(null,n);if(!e)return {ok:false,error:r,data:a??null,headers:null,config:t,mutate:s,isFetching:false,isSuccess:false,isError:true};let o=typeof Response===D&&e instanceof Response,u=e.data;a!==void 0&&(u==null||typeof u===J&&Object.keys(u).length===0)&&(e.data=u=a),t.flattenResponse&&(e.data=u=ge(u)),t.select&&(e.data=u=t.select(u));let c=A(e.headers);return o?{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:()=>e.blob(),json:()=>e.json(),text:()=>e.text(),clone:()=>e.clone(),arrayBuffer:()=>e.arrayBuffer(),formData:()=>e.formData(),bytes:()=>e.bytes(),error:r,data:u,headers:c,config:t,mutate:s,isFetching:false,isSuccess:e.ok&&!r,isError:!!r}:(d(e)&&(e.error=r,e.headers=c,e.isFetching=false,e.mutate=s,e.isSuccess=e.ok&&!r,e.isError=!!r),e)};function st(e){let t=Date.parse(e)-h();return isNaN(t)?null:Math.max(0,Math.floor(t))}function wt(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 u=st(r);if(u!==null)return u}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?st(s):null}async function ot(e,t){let{retries:r=0,delay:a=0,backoff:n=1,maxDelay:s,retryOn:o=[],shouldRetry:u}=t,c=0,i=a,m=r>0?r:0,l;for(;c<=m;){if(c>0&&l){let f=l.config,E=f.onRetry;E&&(await I(E,l,c),f._isAutoKey&&(f._prevKey=f.cacheKey,f.cacheKey=Z(f,false)));}l=await e(c>0,c);let p=l.error;if(!p){if(u&&c0&&await S(n),o=await e(),s++,!(a>0&&s>=a||!t||r&&r(o,s)));)await S(t);return o}async function ut(e,t,r){let a=await t(e),n=a.error;if(!n)return qe(a,r),a;r.onError&&await I(r.onError,n);let s=n.isCancelled;if(!s&&r.logger&&At(r,"FETCH ERROR",n),qe(a,r,true),!s||r.rejectCancelled){let u=r.strategy;if(u===ae)return Promise.reject(n);u==="silent"&&await new Promise(()=>null);}return a}function lt(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===re;}function At(e,...t){let r=e.logger;r&&r.warn&&r.warn(...t);}var Fe=Object.freeze({isFetching:true});async function Pe(e,t=null){if(t&&typeof t.cacheKey=="string"){let R=V(t.cacheKey,t.cacheTime,t);if(R)return R}let r=Ce(e,t),{timeout:a,cancellable:n,cacheKey:s,dedupeTime:o,cacheTime:u,staleTime:c,refetchOnFocus:i,refetchOnReconnect:m,pollingInterval:l=0}=r,p=u!==void 0||c!==void 0,g=!!(s||a||o||p||n||i||m),f=null;if(g&&(f=Z(r)),f&&p){let R=V(f,u,r);if(R)return R}if(f&&o){let R=Te(f,o);if(R)return R}let E=r.retry||{},{retries:ct=0,resetTimeout:ft}=E,Oe=async(R=false,ee=0)=>{ee||(f&&!R&&(c?V(f,u,r)||(Re(f,Fe,u,c),L(f,Fe)):L(f,Fe)),r.cacheKey=f);let O=r.url,pt=ze(f,O,a,o||0,!!n,!!(a&&(!ee||ft))),T=r;T.signal=pt.signal;let te,y=null;try{r.onRequest&&(f&&o&&!ee&&await null,await I(r.onRequest,T));let v=r.fetcher;if(y=v?await v(O,T):await fetch(O,T),d(y)&&(typeof Response===D&&y instanceof Response?y.data=await nt(y):v&&("data"in y&&"body"in y||(y={data:y})),y.config=T,y.ok!==void 0&&!y.ok))throw new ue(`${T.method} to ${O} failed! Status: ${y.status||null}`,T,y);te=Be(y,T);let K=r.onResponse;K&&await I(K,te);}catch(v){let K=v;lt(K,y,T),te=Be(y,T,K);}return te},mt=ct>0?(R=false)=>ot((ee,O)=>Oe(R,O),E):Oe,X=(R=false)=>ut(R,mt,r),ve=l?it(X,l,r.shouldStopPolling,r.maxPollingAttempts,r.pollingDelay):X();return f&&(o&&ke(f,ve),(c||i||m)&&Ze(f,X,void 0,c,X,!!i,!!m)),ve}function It(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=t[n],u=o||{url:String(n)},c=u.url;if(c.startsWith("//"))throw new Error("Protocol-relative URLs are not allowed.");let i=se(c)?o?.url===c?j(u,s):s:j(j(e,u),s);return Pe(c,i)}};return new Proxy(a,{get(n,s){return s in a?a[s]:t[s]?a.request.bind(null,s):r.bind(null,s)}})} +exports.abortRequest=Je;exports.addTimeout=B;exports.buildConfig=Ce;exports.createAbortError=oe;exports.createApiFetcher=It;exports.deleteCache=pe;exports.fetchf=Pe;exports.fetchff=Pe;exports.generateCacheKey=Z;exports.getCache=ye;exports.getCachedResponse=V;exports.getDefaultConfig=et;exports.getInFlightPromise=Te;exports.isSlowConnection=De;exports.mutate=Ie;exports.removeRevalidators=Rt;exports.revalidate=me;exports.revalidateAll=Ye;exports.setCache=Re;exports.setDefaultConfig=Tt;exports.setEventProvider=yt;exports.subscribe=Et;//# 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 6b56b7d3..b68d3441 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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","enhanceError","inFlightResponse","fetchf","fetcherConfig","cancellable","isCacheEnabled","needsCacheKey","_cacheKey","cached","inflight","retryConfig","resetTimeout","doRequestOnce","onResponse","_error","baseRequest","_","requestWithErrorHandling","doRequestPromise","createApiFetcher","endpoints","handleNonImplemented","endpointName","apiHandler","endpointConfig","_endpointConfig","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ 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/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_DEPTH","isSearchParams","data","isObject","value","sanitizeObject","obj","hasProto","hasCtor","hasPrototype","safeObj","sortObject","keys","sortedObj","i","len","key","appendQueryStringToUrl","baseUrl","queryString","appendQueryParams","url","params","encodedQueryString","s","encode","add","k","v","buildParams","prefix","depth","replaceUrlPathParams","urlPathParams","match","isAbsoluteUrl","timeNow","noop","isJSONSerializable","delayInvocation","ms","resolve","flattenData","processHeaders","headers","headersObject","isBrowser","createAbortError","message","name","error","isSlowConnection","conn","applyInterceptors","interceptors","args","interceptor","FetchError","request","response","ResponseError","WHEEL_SIZE","SECOND","MAX_WHEEL_MS","wheel","keyMap","position","timer","handleCallback","callback","result","addTimeout","cb","removeTimeout","seconds","slot","slotOrTimeout","slotArr","idx","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","ensureListenerSet","set","addListener","fn","removeListener","notifySubscribers","fns","subscribe","defaultTimeoutMs","defaultConfig","setDefaultConfig","customConfig","sanitized","mergeConfigs","getDefaultConfig","buildConfig","reqConfig","buildFetcherConfig","merged","requestConfig","method","body","setContentTypeIfNeeded","credentials","dynamicUrl","urlPath","baseURL","contentTypeValue","baseConfig","overrideConfig","targetConfig","mergeConfig","mergeInterceptors","property","baseInterceptor","newInterceptor","baseArr","newArr","base","override","baseNormalized","overrideNormalized","_cache","DELIMITER","MIN_LENGTH_TO_HASH","CACHE_KEY_SANITIZE_PATTERN","CACHE_KEY_NEEDS_SANITIZE","CACHE_KEY_HEADER_WHITELIST","generateCacheKey","config","cacheKeyCheck","headersString","cacheStr","bodyString","o","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","customDecision","withPolling","pollingInterval","shouldStopPolling","maxAttempts","pollingDelay","pollingAttempt","withErrorHandling","isCancelled","logger","strategy","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","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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { FUNCTION, 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 function isSearchParams(data: unknown): boolean {\n return data instanceof URLSearchParams;\n}\n\n/**\n * Determines if a value is a non-null object.\n *\n * @param {any} value - The value to check.\n * @returns {boolean} - True if the value is a non-null object.\n */\nexport function isObject(value: any): value is Record {\n return value !== null && typeof value === OBJECT;\n}\n\n/**\n * Shallowly serializes an object by converting its key-value pairs into a string representation.\n * This function does not recursively serialize nested objects.\n *\n * @param obj - The object to serialize.\n * @returns A string representation of the object's top-level properties.\n */\nexport function shallowSerialize(obj: Record): string {\n let result = '';\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result += key + ':' + obj[key];\n }\n }\n\n return result;\n}\n\n/**\n * 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 = Object.prototype.hasOwnProperty.call(obj, '__proto__');\n const hasCtor = Object.prototype.hasOwnProperty.call(obj, 'constructor');\n const hasPrototype = Object.prototype.hasOwnProperty.call(obj, 'prototype');\n\n if (!hasProto && !hasCtor && !hasPrototype) {\n return obj;\n }\n\n const safeObj = { ...obj };\n\n if (hasProto) delete safeObj.__proto__;\n if (hasCtor) delete (safeObj as any).constructor;\n if (hasPrototype) delete safeObj.prototype;\n\n return safeObj;\n}\n\n/**\n * Sorts the keys of an object and returns a new object with sorted keys.\n *\n * This function is optimized for performance by minimizing the number of object operations\n * and using a single pass to create the sorted object.\n *\n * @param {Object} obj - The object to be sorted by keys.\n * @returns {Object} - A new object with keys sorted in ascending order.\n */\nexport function sortObject(obj: Record): object {\n const keys = Object.keys(obj);\n\n keys.sort();\n\n const sortedObj = {} as Record;\n\n for (let i = 0, len = keys.length; i < len; i++) {\n const key = keys[i];\n\n sortedObj[key] = obj[key];\n }\n\n return sortedObj;\n}\n\n/**\n * Appends a query string to a URL, ensuring proper handling of existing query parameters.\n *\n * @param baseUrl - The base URL to which the query string will be appended.\n * @param queryString - The encoded query string to append.\n * @returns The URL with the appended query string, or the original URL if no query string is provided.\n */\nfunction appendQueryStringToUrl(baseUrl: string, queryString: string): string {\n if (!queryString) {\n return baseUrl;\n }\n\n return baseUrl.includes('?')\n ? `${baseUrl}&${queryString}`\n : `${baseUrl}?${queryString}`;\n}\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {QueryParams} params - An object containing the query parameters to append.\n * @returns {string} - The URL with the appended query parameters.\n */\nexport function appendQueryParams(url: string, params: QueryParams): string {\n if (!params) {\n return url;\n }\n\n // Check if `params` is an instance of URLSearchParams and bail early if it is\n if (isSearchParams(params)) {\n const encodedQueryString = params.toString();\n\n return appendQueryStringToUrl(url, encodedQueryString);\n }\n\n // This is exact copy of what JQ used to do. It works much better than URLSearchParams\n const s: string[] = [];\n const encode = encodeURIComponent;\n const add = (k: string, v: any) => {\n v = typeof v === FUNCTION ? v() : v;\n v = v === null ? '' : v === undefined ? '' : v;\n s[s.length] = encode(k) + '=' + encode(v);\n };\n\n const buildParams = (prefix: string, obj: any, 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 (Object.prototype.hasOwnProperty.call(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 return encodeURIComponent(String(value));\n }\n }\n\n return match;\n });\n}\n\n/**\n * Determines whether the provided URL is absolute.\n *\n * An absolute URL contains a scheme (e.g., \"http://\", \"https://\").\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 url.includes('://');\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 async function delayInvocation(ms: number): Promise {\n return new Promise((resolve) =>\n setTimeout(() => {\n return resolve(true);\n }, ms),\n );\n}\n\n/**\n * Recursively flattens the data object if it meets specific criteria.\n *\n * The method checks if the provided `data` is an object with exactly one property named `data`.\n * If so, it recursively flattens the `data` property. Otherwise, it returns the `data` as-is.\n *\n * @param {any} data - The data to be flattened. Can be of any type, including objects, arrays, or primitives.\n * @returns {any} - The flattened data if the criteria are met; otherwise, the original `data`.\n */\nexport function flattenData(data: any, 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 if (isObject(headers)) {\n // Handle plain object — use for...in to avoid Object.entries() allocation\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\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 } 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 if (typeof interceptors === FUNCTION) {\n const value = await (interceptors as InterceptorFunction)(\n data,\n ...args,\n );\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\n } else if (Array.isArray(interceptors)) {\n for (const interceptor of interceptors) {\n const value = await interceptor(data, ...args);\n\n if (value && isObject(data) && isObject(value)) {\n Object.assign(data, value);\n }\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 exceeds 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 * - Automatically stops the internal timer when no timeouts remain.\n */\n\nimport { noop } 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 MAX_WHEEL_MS = WHEEL_SIZE * SECOND;\nconst wheel: TimeoutItem[][] = Array(WHEEL_SIZE)\n .fill(0)\n .map(() => []);\n\nconst keyMap = new Map();\nlet position = 0;\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 // Fallback to setTimeout if wheel size is exceeded, ms is sub-second, or ms is not divisible by SECOND\n if (ms < SECOND || ms > MAX_WHEEL_MS || ms % SECOND !== 0) {\n keyMap.set(key, [setTimeout(handleCallback.bind(null, [key, cb]), ms)]); // Store timeout ID instead of slot\n\n return;\n }\n\n // No need for Math.ceil here since ms is guaranteed by modulo above\n const seconds = ms / SECOND;\n const slot = (position + seconds) % WHEEL_SIZE;\n\n wheel[slot].push([key, cb]);\n keyMap.set(key, slot);\n\n if (!timer) {\n timer = setInterval(() => {\n position = (position + 1) % WHEEL_SIZE;\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 const idx = slotArr.findIndex(([k]) => k === key);\n\n if (idx !== -1) {\n slotArr.splice(idx, 1);\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\nfunction ensureListenerSet(key: string) {\n let set = listeners.get(key);\n\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n\n return set;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function addListener(key: string, fn: Listener): void {\n ensureListenerSet(key).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 return mergeConfigs({}, sanitized, defaultConfig);\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 if (!reqConfig) {\n return buildFetcherConfig(url, getDefaultConfig());\n }\n\n const sanitized = sanitizeObject(reqConfig);\n const merged = mergeConfigs(defaultConfig, sanitized);\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 requestConfig.url = baseURL + 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 !headers[CONTENT_TYPE]\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 if (overrideConfig[property]) {\n const base = baseConfig[property];\n const override = overrideConfig[property];\n\n // Handle Headers instances which don't expose entries as own enumerable properties\n if (\n property === 'headers' &&\n ((base as Headers | (HeadersObject & HeadersInit)) instanceof Headers ||\n (override as Headers | (HeadersObject & HeadersInit)) instanceof\n Headers)\n ) {\n const baseNormalized = processHeaders(base);\n const overrideNormalized = processHeaders(override);\n targetConfig[property] = {\n ...baseNormalized,\n ...overrideNormalized,\n } as RequestConfig[K];\n } else {\n targetConfig[property] = {\n ...base,\n ...override,\n };\n }\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, UNDEFINED } from './constants';\nimport { isObject, sanitizeObject, sortObject, timeNow } 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 CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\n : cacheStr;\n }\n\n let bodyString = '';\n if (body) {\n if (typeof body === STRING) {\n bodyString = body.length < MIN_LENGTH_TO_HASH ? body : hash(body); // hash only if large\n } else if (body instanceof FormData) {\n body.forEach((value, key) => {\n // Append key=value and '&' directly to the result\n bodyString += key + '=' + value + '&';\n });\n\n if (bodyString.length > MIN_LENGTH_TO_HASH) {\n bodyString = hash(bodyString);\n }\n } else if (\n (typeof Blob !== UNDEFINED && body instanceof Blob) ||\n (typeof File !== UNDEFINED && body instanceof File)\n ) {\n bodyString = 'BF' + body.size + body.type;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n bodyString = 'AB' + body.byteLength;\n } else {\n const o = 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 // Prevent cache poisoning by removal of control chars and unusual characters\n return CACHE_KEY_NEEDS_SANITIZE.test(cacheStr)\n ? cacheStr.replace(CACHE_KEY_SANITIZE_PATTERN, '')\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 // Return data whether fresh or stale (SWR: serve stale, revalidation is timer-driven)\n return entry.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\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 (\n mimeType.includes(APPLICATION_CONTENT_TYPE + 'octet-stream') &&\n typeof response.blob === FUNCTION\n ) {\n data = await response.blob(); // Parse as blob\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 return {\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: () => response.blob(),\n json: () => response.json(),\n text: () => response.text(),\n clone: () => response.clone(),\n arrayBuffer: () => response.arrayBuffer(),\n formData: () => response.formData(),\n bytes: () => response.bytes(),\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\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 if (retryAfterMs !== null) {\n waitTime = 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 let customDecision: boolean | null = null;\n\n // Get custom decision if shouldRetry is provided\n if (shouldRetry) {\n const result = await shouldRetry(output, attempt);\n customDecision = result;\n\n // Decision cascade:\n if (customDecision !== null) {\n return !customDecision;\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 { DefaultParams, DefaultUrlParams, DefaultPayload } from './types';\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) {\n logger(requestConfig, 'FETCH ERROR', error as ResponseError);\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\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\n/**\n * Logs messages or errors using the configured logger's `warn` method.\n *\n * @param {RequestConfig} reqConfig - Request config passed when making the request\n * @param {...(string | ResponseError)} args - Messages or errors to log.\n */\nfunction logger(\n reqConfig: RequestConfig,\n ...args: (string | ResponseError)[]\n): void {\n const logger = reqConfig.logger;\n\n if (logger && logger.warn) {\n logger.warn(...args);\n }\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 = false, 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 = 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} to ${url} failed! Status: ${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 = false) =>\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 { isAbsoluteUrl } 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 const endpointConfig = endpoints[endpointName];\n const _endpointConfig =\n endpointConfig ||\n ({ url: String(endpointName) } as RequestConfigUrlRequired);\n const url = _endpointConfig.url;\n\n // Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)\n if (url.startsWith('//')) {\n throw new Error('Protocol-relative URLs are 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 const mergedConfig = isAbsoluteUrl(url)\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) {\n if (prop in apiHandler) {\n return apiHandler[prop as unknown as keyof typeof apiHandler];\n }\n\n // Prevent handler from triggering non-existent endpoints\n if (endpoints[prop]) {\n return apiHandler.request.bind(null, prop);\n }\n\n return handleNonImplemented.bind(null, prop);\n },\n },\n );\n}\n\nexport { createApiFetcher };\n"]} \ No newline at end of file