axios-cache-interceptor
Version:
Cache interceptor for axios
1,204 lines (1,203 loc) • 52.6 kB
text/typescript
import { AxiosInstance, AxiosInterceptorManager, AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse, Method } from "axios";
import { Deferred } from "fast-defer";
//#region src/storage/types.d.ts
/**
* Metadata for cache entry (extensible for future enhancements).
* Replaces x-axios-cache-* custom headers with cleaner structure.
*/
interface CachedResponseMeta {
/**
* Subset of request headers that match the Vary header.
* Used to validate vary requirements on cache retrieval.
*
* @example
* // Response has Vary: Authorization
* // Request has headers: { authorization: 'Bearer X', 'other-header': 'value' }
* meta: {
* vary: { authorization: 'Bearer X' }
* }
*/
vary?: Record<string, string | undefined>;
/**
* Revalidation metadata for conditional requests (304 Not Modified).
* Enables stale cache revalidation via `ETag` or `Last-Modified` validators.
*
* @example
* // ETag-based revalidation
* meta: { revalidation: { etag: 'W/123' } }
*
* @example
* // Last-Modified revalidation with cache timestamp
* meta: { revalidation: { lastModified: true } }
*/
revalidation?: {
/**
* ETag value for `If-None-Match` header.
* Stored when `cache.etag` config provides a custom value.
*/
etag?: string;
/**
* Last-Modified value for `If-Modified-Since` header.
* Can be a UTC date string or `true` to use cache creation timestamp.
*/
lastModified?: string | true;
};
}
interface CachedResponse {
data?: unknown;
headers: CacheAxiosResponse['headers'];
status: number;
statusText: string;
meta?: CachedResponseMeta;
}
/** The value returned for a given key. */
type StorageValue = StaleStorageValue | CachedStorageValue | LoadingStorageValue | EmptyStorageValue | MustRevalidateStorageValue;
type NotEmptyStorageValue = Exclude<StorageValue, EmptyStorageValue>;
interface StaleStorageValue {
data: CachedResponse;
ttl?: number;
staleTtl?: undefined;
createdAt: number;
state: 'stale';
}
interface MustRevalidateStorageValue {
data: CachedResponse;
ttl?: number;
staleTtl?: undefined;
createdAt: number;
state: 'must-revalidate';
}
interface CachedStorageValue {
data: CachedResponse;
/**
* The number in milliseconds to wait after createdAt before the value is considered
* stale.
*/
ttl: number;
staleTtl?: number;
createdAt: number;
state: 'cached';
}
type LoadingStorageValue = LoadingEmptiedStorageValue | LoadingStaledStorageValue | LoadingRevalidateStorageValue;
interface LoadingEmptiedStorageValue {
data?: undefined;
ttl?: undefined;
staleTtl?: undefined;
createdAt?: undefined;
state: 'loading';
previous: 'empty';
}
interface LoadingStaledStorageValue {
state: 'loading';
data: CachedResponse;
ttl?: undefined;
staleTtl?: undefined;
createdAt: number;
previous: 'stale';
}
interface LoadingRevalidateStorageValue {
state: 'loading';
data: CachedResponse;
ttl?: undefined;
staleTtl?: undefined;
createdAt: number;
previous: 'must-revalidate';
}
interface EmptyStorageValue {
data?: undefined;
ttl?: undefined;
staleTtl?: undefined;
/** Defined when the state is cached */
createdAt?: undefined;
state: 'empty';
}
/**
* A storage interface is the entity responsible for saving, retrieving and serializing
* data received from network and requested when a axios call is made.
*
* @default buildMemoryStorage
* @see https://axios-cache-interceptor.js.org/guide/storages
*/
interface AxiosStorage {
/**
* Sets a new value for the given key
*
* Use {@link AxiosStorage.remove} to define a key with `'empty'` state.
*
* @param key The key to look for
* @param value The value to save.
* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
set: (key: string, value: NotEmptyStorageValue, currentRequest?: CacheRequestConfig) => MaybePromise<void>;
/**
* Removes the value for the given key
*
* @param key The key to look for
* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
remove: (key: string, currentRequest?: CacheRequestConfig) => MaybePromise<void>;
/**
* Returns the value for the given key. This method make checks for cache invalidation
* or etc.
*
* If the internal `find()` method returned null, this will map it to a `'empty'`
* storage value.
*
* @param key The key to look for
* @param currentRequest The current {@link CacheRequestConfig}, if any
* @returns The saved value for the given key.
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
get: (key: string, currentRequest?: CacheRequestConfig) => MaybePromise<StorageValue>;
/**
* Deletes all values from the storage, this method isn't used by the interceptor and is
* here just for convenience.
*
* **All native storages implement them, but it's not required.**
*
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
clear?: () => MaybePromise<void>;
}
//#endregion
//#region src/util/types.d.ts
type CachePredicate<R = unknown, D = unknown> = NonNullable<CachePredicateObject<R, D> | CachePredicateObject<R, D>['responseMatch']>;
/**
* A hint to the library about where the axios instance is being used.
*
* Used to take some decisions like handling or not `Cache-Control: private`.
*
* @default typeof window === 'undefined' ? 'server' : 'client'
* @see https://axios-cache-interceptor.js.org/config#location
*/
type InstanceLocation = 'client' | 'server';
interface CachePredicateObject<R = unknown, D = unknown> {
/** Matches if this function returned true. */
statusCheck?: (status: number) => MaybePromise<boolean>;
/**
* Matches if all keys in this object returned true.
*
* The response does not contain all headers specified here, the specified function will
* be called without argument.
*
* ### Remember, all axios headers are lowercase.
*/
containsHeaders?: Record<string, (header?: CacheAxiosResponse['headers'][string]) => MaybePromise<boolean>>;
/** Check if the response matches this predicate. */
responseMatch?: (res: CacheAxiosResponse<R, D>) => MaybePromise<boolean>;
/**
* Ignores the request if their url matches any provided urls and/or regexes.
*
* - It checks against the `request.url` property, `baseURL` is not considered.
* - When only `baseURL` is specified, this property is ignored.
*/
ignoreUrls?: (RegExp | string)[];
/**
* Ignores the request if their url does not match any provided urls and/or regexes.
*
* - It checks against the `request.url` property, `baseURL` is not considered.
* - When only `baseURL` is specified, this property is ignored.
* - If both `ignoreUrls` & `allowUrls` are matched, `ignoreUrls` take precedence.
*/
allowUrls?: (RegExp | string)[];
}
/**
* A simple function that receives a cache request config and optional metadata,
* and should return a string id for it.
*
* The meta parameter can include vary header values for generating vary-aware cache keys.
*/
type KeyGenerator<R = unknown, D = unknown> = (options: CacheRequestConfig<R, D>, meta?: CachedResponseMeta) => string;
/** @deprecated This type will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158 */
type MaybePromise<T> = T | Promise<T> | PromiseLike<T>;
/**
* You can use a `number` to ensure an max time (in seconds) that the cache can be reused.
*
* You can use `true` to use the cache until a new response is received.
*
* You can use a `function` predicate to determine if the cache can be reused (`boolean`)
* or how much time the cache can be used (`number`)
*/
type StaleIfErrorPredicate<R, D> = number | boolean | ((networkResponse: CacheAxiosResponse<R, D> | undefined, cache: LoadingStorageValue & {
previous: 'stale';
}, error: Record<string, unknown>) => MaybePromise<number | boolean>);
type CacheUpdaterFn<R, D> = (response: CacheAxiosResponse<R, D>) => MaybePromise<void>;
/**
* A record for a custom cache updater for each specified request id.
*
* `delete` -> Deletes the request cache `predicate()` -> Determines if the cache can be
* reused, deleted or modified.
*/
interface CacheUpdaterRecord<R, D> {
[requestId: string]: 'delete' | ((cached: Exclude<StorageValue, LoadingStorageValue>, response: CacheAxiosResponse<R, D>) => MaybePromise<CachedStorageValue | 'delete' | 'ignore'>);
}
/**
* Updates any specified request cache by applying the response for this network call.
*
* You can use a function to implement your own cache updater function.
*/
type CacheUpdater<R, D> = CacheUpdaterFn<R, D> | CacheUpdaterRecord<R, D>;
//#endregion
//#region src/header/types.d.ts
/**
* The possible values are:
*
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
* - `{ cache: number, stale: number }: used as the TTL value and stale TTL value`
*
* @deprecated This interface will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
type InterpreterResult = 'dont cache' | 'not enough headers' | number | {
cache: number;
stale?: number;
};
/**
* - If activated, when the response is received, the `ttl` property will be inferred from
* the requests headers. As described in the MDN docs and HTML specification.
*
* The possible returns are:
*
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
* - `{ cache: number, stale: number }: used as the TTL value and stale TTL value`
*
* @param header The header object to interpret.
* @param location The instance location, either `'client'` or `'server'`.
* @returns `false` if cache should not be used. `undefined` when provided headers was not
* enough to determine a valid value. Or a `number` containing the number of
* **milliseconds** to cache the response.
* @see https://axios-cache-interceptor.js.org/config#headerinterpreter
*
* @deprecated This interface will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
type HeaderInterpreter = (headers: CacheAxiosResponse['headers'], location: InstanceLocation) => InterpreterResult;
//#endregion
//#region src/interceptors/build.d.ts
/**
* See {@link AxiosInterceptorManager}
*
* @deprecated This interface will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
interface AxiosInterceptor<T> {
onFulfilled(value: T): T | Promise<T>;
/** Returns a successful response or re-throws the error */
onRejected?(error: Record<string, unknown>): T | Promise<T>;
}
/**
* @deprecated This interface will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
type RequestInterceptor = AxiosInterceptor<InternalCacheRequestConfig<unknown, unknown>>;
/**
* @deprecated This interface will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
type ResponseInterceptor = AxiosInterceptor<CacheAxiosResponse<unknown, unknown>>;
//#endregion
//#region src/cache/cache.d.ts
/**
* @template R The type returned by this response
* @template D The type for the request body
*/
interface CacheProperties<R = unknown, D = unknown> {
/**
* Whether the cache is enabled for this request.
*
* When set to `false`, the cache will be completely disabled for this request,
* similar to setting `cache: false` in the request config.
*
* This is useful for opt-in cache scenarios where you want to disable cache globally
* but enable it for specific requests by setting `cache: { enabled: true }`.
*
* @default true
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-enabled
*/
enabled: boolean;
/**
* The time until the cached value is expired in milliseconds.
*
* If a function is used, it will receive the complete response and waits to return a
* TTL value
*
* When using `interpretHeader: true`, this value will only be used if the interpreter
* can't determine their TTL value to override this
*
* @default 1000 * 60 * 5 // 5 Minutes
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-ttl
*/
ttl: number | ((response: CacheAxiosResponse<R, D>) => number | Promise<number>);
/**
* If activated, when the response is received, the `ttl` property will be inferred from
* the requests headers. As described in the MDN docs and HTML specification.
*
* See the actual implementation of the
* [`interpretHeader`](https://github.com/arthurfiorette/axios-cache-interceptor/blob/main/src/header/interpreter.ts)
* method for more information.
*
* @default true
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-interpretheader
*/
interpretHeader: boolean;
/**
* As most of our cache strategies depends on well known defined HTTP headers, most
* browsers also use those headers to define their own cache strategies and storages.
*
* When your requested routes includes `Cache-Control` in their responses, you may end
* up with we and your browser caching the response, resulting in a **double layer of
* cache**.
*
* This option solves this by including some predefined headers in the request, that
* should tell any client / adapter to not cache the response, thus only we will cache
* it.
*
* _These are headers used in our specific request, it won't affect any other request or
* response that the server may handle._*
*
* Headers included:
*
* - `Cache-Control: no-cache, no-store, must-revalidate, max-age=0`
* - `Pragma: no-cache`
* - `Expires: 0`
*
* Learn more at
* [#437](https://github.com/arthurfiorette/axios-cache-interceptor/issues/437#issuecomment-1361262194)
* and in this [StackOverflow](https://stackoverflow.com/a/62781874/14681561) answer.
*
* @default true
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachetakeover
*/
cacheTakeover: boolean;
/**
* Specifies which methods we should handle and cache. This is where you can enable
* caching to `POST`, `PUT`, `DELETE` and other methods, as the default is only `GET`.
*
* We use `methods` in a per-request configuration setup because sometimes you have
* exceptions to the method rule.
*
* @default ['get', 'head']
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-methods
*/
methods: Lowercase<Method>[];
/**
* An object or function that will be tested against the response to indicate if it can
* be cached.
*
* @default { statusCheck: (status) => [200, 203, 300, 301, 302, 404, 405, 410, 414, 501].includes(status) }
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachepredicate
*/
cachePredicate: CachePredicate<R, D>;
/**
* Once the request is resolved, this specifies what other responses should change their
* cache. Can be used to update the request or delete other caches. It is a simple
* `Record` with the request id.
*
* Here's an example with some basic login:
*
* Using a function instead of an object is supported but not recommended, as it's
* better to just consume the response normally and write your own code after it. But
* it`s here in case you need it.
*
* @default {{}}
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-update
*/
update: CacheUpdater<R, D>;
/**
* If the request should handle
* [`ETag`](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/ETag) and
* [`If-None-Match
* support`](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/If-None-Match).
* Use a string to force a custom static value or true to use the previous response
* ETag.
*
* To use `true` (automatic ETag handling), `interpretHeader` option must be set to
* `true`.
*
* @default true
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-etag
*/
etag: string | boolean;
/**
* Use
* [`If-Modified-Since`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since)
* header in this request. Use a date to force a custom static value or true to use the
* last cached timestamp.
*
* If never cached before, the header is not set.
*
* If `interpretHeader` is set and a
* [`Last-Modified`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)
* header is sent to us, then value from that header is used, otherwise cache creation
* timestamp will be sent in
* [`If-Modified-Since`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since).
*
* @default false // The opposite of the resulting `etag` option.
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-modifiedsince
*/
modifiedSince: Date | boolean;
/**
* Enables cache to be returned if the response comes with an error, either by invalid
* status code, network errors and etc. You can filter the type of error that should be
* stale by using a predicate function.
*
* **If the response is treated as error because of invalid status code _(like when
* using
* [statusCheck](https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachepredicate))_,
* and this ends up `true`, the cache will be preserved over the "invalid" request.**
*
* Types:
*
* - `number` -> the max time (in seconds) that the cache can be reused.
* - `boolean` -> `false` disables and `true` enables with infinite time if no value is
* present on `stale-if-error` in Cache-Control.
* - `function` -> a predicate that can return `number` or `boolean` as described above.
*
* @default true
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error
*/
staleIfError: StaleIfErrorPredicate<R, D>;
/**
* This option bypasses the current cache and always make a new http request. This will
* not delete the current cache, it will just replace the cache when the response
* arrives.
*
* Unlike as `cache: false`, this will not disable the cache, it will just ignore the
* pre-request cache checks before making the request. This way, all post-request
* options are still available and will work as expected.
*
* @default false
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-override
*/
override: boolean;
/**
* Asynchronously called when a network request is needed to resolve the data, but an
* older one **and probably expired** cache exists. Its with the current data **BEFORE**
* the network travel starts, so you can use it to temporarily update your UI with
* expired data before the network returns.
*
* Hydrating your components with old data before the network resolves with the newer
* one is better than _flickering_ your entire UI. This is even better when dealing with
* slower networks and persisted cache, like for mobile apps.
*
* If the request can return cached data, as no extensive network travel is needed, the
* hydrate **IS NOT CALLED**, as the axios promise will be resolved instantly.
*
* @default undefined
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-hydrate
*/
hydrate: undefined | ((cache: (LoadingStorageValue & {
previous: 'stale' | 'must-revalidate';
}) | CachedStorageValue | StaleStorageValue) => void | Promise<void>);
/**
* Configure HTTP Vary header handling.
*
* - `true`: Enable automatic vary handling (default - recommended for security)
* - `false`: Disable vary checking (WARNING: can cause cache poisoning!)
* - `string[]`: Use specific request headers in cache key
*
* @default true
* @example ['authorization', 'accept-language']
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-vary
*/
vary: string[] | boolean;
}
/**
* These are properties that are used and shared by the entire application.
*
* ```ts
* const axios = setupCache(axios, OPTIONS);
* ```
*
* The `setupCache` function receives global options and all [request
* specifics](https://axios-cache-interceptor.js.org/config/request-specifics) ones too.
* This way, you can customize the defaults for all requests.
*
* @see https://axios-cache-interceptor.js.org/config/request-specifics
*/
interface CacheInstance {
/**
* A hint to the library about where the axios instance is being used.
*
* Used to take some decisions like handling or not `Cache-Control: private`.
*
* @deprecated This property will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
* @default typeof window === 'undefined' ? 'server' : 'client'
* @see https://axios-cache-interceptor.js.org/config#location
*/
location: InstanceLocation;
/**
* A storage interface is the entity responsible for saving, retrieving and serializing
* data received from network and requested when a axios call is made.
*
* See the [Storages](https://axios-cache-interceptor.js.org/guide/storages) page for
* more information.
*
* @default buildMemoryStorage
* @see https://axios-cache-interceptor.js.org/config#storage
*/
storage: AxiosStorage;
/**
* The function used to create different keys for each request. Defaults to a function
* that priorizes the id, and if not specified, a string is generated using the
* `method`, `baseURL`, `params`, `data` and `url`.
*
* You can learn on how to use them on the [Request
* ID](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator) page.
*
* @default defaultKeyGenerator
* @see https://axios-cache-interceptor.js.org/config#generatekey
*/
generateKey: KeyGenerator;
/**
* A simple object that will hold a promise for each pending request. Used to handle
* concurrent requests.
*
* You'd normally not need to change this, but it is exposed in case you need to use it
* as some sort of listener of know when a request is waiting for other to finish.
*
* @deprecated This property will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
* @default new Map()
* @see https://axios-cache-interceptor.js.org/config#waiting
*/
waiting: Map<string, Deferred<void>>;
/**
* The function used to interpret all headers from a request and determine a time to
* live (`ttl`) number.
*
* **Many REST backends returns some variation of `Cache-Control: no-cache` or
* `Cache-Control: no-store` headers, which tell us to ignore caching at all. You shall
* disable `headerInterpreter` for those requests.**
*
* **If the debug mode prints `Cache header interpreted as 'dont cache'` this is
* probably the reason.**
*
* The possible returns are:
*
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
*
* @deprecated This property will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
* @default defaultHeaderInterpreter
* @see https://axios-cache-interceptor.js.org/config#headerinterpreter
*/
headerInterpreter: HeaderInterpreter;
/**
* The function that will be used to intercept the request before it is sent to the
* axios adapter.
*
* It is the main function of this library, as it is the bridge between the axios
* request and the cache.
*
* _It wasn't meant to be changed, but if you need to, you can do it by passing a new
* function to this property._*
*
* See its code for more information
* [here](https://github.com/arthurfiorette/axios-cache-interceptor/tree/main/src/interceptors).
*
* @deprecated This property will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
* @default defaultRequestInterceptor
* @see https://axios-cache-interceptor.js.org/config#requestinterceptor
*/
requestInterceptor: AxiosInterceptor<InternalCacheRequestConfig<unknown, unknown>>;
/**
* The function that will be used to intercept the request after it is returned by the
* axios adapter.
*
* It is the second most important function of this library, as it is the bridge between
* the axios response and the cache.
*
* _It wasn't meant to be changed, but if you need to, you can do it by passing a new
* function to this property._*
*
* See its code for more information
* [here](https://github.com/arthurfiorette/axios-cache-interceptor/tree/main/src/interceptors).
*
* @deprecated This property will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
* @default defaultResponseInterceptor
* @see https://axios-cache-interceptor.js.org/config#responseinterceptor
*/
responseInterceptor: AxiosInterceptor<Partial<CacheAxiosResponse<unknown, unknown>> & AxiosResponse<unknown, unknown>>;
/**
* The debug option will print debug information in the console. It is good if you need
* to trace any undesired behavior or issue. You can enable it by setting `debug` to a
* function that receives an string and returns nothing.
*
* Read the [Debugging](https://axios-cache-interceptor.js.org/guide/debugging) page for
* the complete guide.
*
* @default noop function
* @see https://axios-cache-interceptor.js.org/guide/debugging
*/
debug: (this: void, msg: DebugObject) => void;
}
/**
* An object with any possible type that can be used to log and debug information in
* `development` mode _(a.k.a `__ACI_DEV__ === true`)_
*
* @see https://axios-cache-interceptor.js.org/#/pages/development-mode
*/
interface DebugObject {
id?: string;
msg?: string;
data?: unknown;
}
//#endregion
//#region src/cache/axios.d.ts
/**
* A slightly changed than the original axios response. Containing information about the
* cache and other needed properties.
*
* @template R The type returned by this response
* @template D The type that the request body was
* @see https://axios-cache-interceptor.js.org/config/response-object
*/
interface CacheAxiosResponse<R = any, D = any> extends AxiosResponse<R, D> {
config: InternalCacheRequestConfig<R, D>;
/**
* The [Request ID](https://axios-cache-interceptor.js.org/guide/request-id) used in
* this request.
*
* It may have been generated by the [Key
* Generator](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator)
* or a custom one provided by
* [`config.id`](https://axios-cache-interceptor.js.org/config/request-specifics#id)
*
* @see https://axios-cache-interceptor.js.org/config/response-object#id
*/
id: string;
/**
* A simple boolean indicating if the request returned data from the cache or from the
* network call.
*
* This does not indicated if the request was capable of being cached or not, as options
* like
* [`cache.override`](https://axios-cache-interceptor.js.org/config/request-specifics#cache-override)
* may have been enabled.
*
* @see https://axios-cache-interceptor.js.org/config/response-object#cached
*/
cached: boolean;
/**
* A simple boolean indicating if the request returned data is from valid or stale
* cache.
*
* @see https://axios-cache-interceptor.js.org/config/response-object#stale
*/
stale?: boolean;
}
/**
* Options that can be overridden per request
*
* @template R The type returned by this response
* @template D The type for the request body
*/
interface CacheRequestConfig<R = any, D = any> extends AxiosRequestConfig<D> {
/**
* The [Request ID](https://axios-cache-interceptor.js.org/guide/request-id) used in
* this request.
*
* It may have been generated by the [Key
* Generator](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator)
* or a custom one provided by
* [`config.id`](https://axios-cache-interceptor.js.org/config/request-specifics#id)
*
* @default 'auto generated by the current key generator'
* @see https://axios-cache-interceptor.js.org/config/response-object#id
*/
id?: string;
/**
* The cache option available through the request config is where all the cache
* customization happens.
*
* You can pass an object with cache properties to customize cache behavior.
*
* **Note:** Setting `cache: false` is still supported for backward compatibility, but
* will be removed in the next major release. Use `cache: { enabled: false }` instead.
*
* This does not mean that the current cache will be excluded from the storage.
*
* @default 'inherits from global configuration'
* @see https://axios-cache-interceptor.js.org/config/response-object#cache
*/
cache?: Partial<CacheProperties<R, D>> | false;
}
/**
* Cached version of type {@link InternalAxiosRequestConfig}
*
* @deprecated This interface will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
interface InternalCacheRequestConfig<R = any, D = any> extends CacheRequestConfig<R, D> {
headers: AxiosRequestHeaders;
}
/**
* Same as the AxiosInstance but with CacheRequestConfig as a config type and
* CacheAxiosResponse as response type.
*
* @see https://axios-cache-interceptor.js.org/guide/getting-started
*/
interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
/**
* @template T1 The type returned by this response
* @template R1 The custom response type that the request can return
* @template D1 The type that the request body use
*/
<T1 = any, D1 = any, R1 = CacheAxiosResponse<T1, D1>>(config: CacheRequestConfig<T1, D1>): Promise<R1>;
/**
* @template T2 The type returned by this response
* @template R2 The custom response type that the request can return
* @template D2 The type that the request body use
*/
<T2 = any, D2 = any, R2 = CacheAxiosResponse<T2, D2>>(url: string, config?: CacheRequestConfig<T2, D2>): Promise<R2>;
defaults: AxiosInstance['defaults'] & {
cache: CacheProperties;
};
interceptors: {
request: AxiosInterceptorManager<InternalCacheRequestConfig<unknown, unknown>>;
response: AxiosInterceptorManager<Partial<CacheAxiosResponse<unknown, unknown>> & AxiosResponse<unknown, unknown>>;
};
/** @template D The type that the request body use */
getUri<D>(config?: CacheRequestConfig<any, D>): string;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
request<T = any, D = any, R = CacheAxiosResponse<T, D>>(config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
get<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
delete<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
head<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
options<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
post<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, data?: D, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
postForm<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, data?: D, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
put<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, data?: D, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
putForm<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, data?: D, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
patch<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, data?: D, config?: CacheRequestConfig<T, D>): Promise<R>;
/**
* @template T The type returned by this response
* @template R The custom response type that the request can return
* @template D The type that the request body use
*/
patchForm<T = any, D = any, R = CacheAxiosResponse<T, D>>(url: string, data?: D, config?: CacheRequestConfig<T, D>): Promise<R>;
}
//#endregion
//#region src/cache/create.d.ts
interface CacheOptions extends Partial<CacheInstance>, Partial<CacheProperties> {
/**
* Whether cache interceptors should be registered during setup.
*
* - `true`: register both request and response interceptors (default).
* - `false`: do not register cache interceptors automatically.
*
* Set to `false` when you need full control over interceptor registration order.
*
* @default true
*/
register?: boolean;
}
/**
* Apply the caching interceptors for a already created axios instance.
*
* ```ts
* const axios = setupCache(axios, OPTIONS);
* ```
*
* The `setupCache` function receives global options and all [request
* specifics](https://axios-cache-interceptor.js.org/config/request-specifics) ones too.
* This way, you can customize the defaults for all requests.
*
* @param axios The already created axios instance
* @param config The config for the caching interceptors
* @returns The same instance with extended typescript types.
* @see https://axios-cache-interceptor.js.org/config
*/
declare function setupCache(axios: AxiosInstance, options?: CacheOptions): AxiosCacheInstance;
//#endregion
//#region src/header/headers.d.ts
/**
* @deprecated This constant will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare const Header: {
/**
* ```txt
* If-Modified-Since: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since
*/
readonly IfModifiedSince: "if-modified-since";
/**
* ```txt
* Last-Modified: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified
*/
readonly LastModified: "last-modified";
/**
* ```txt
* If-None-Match: "<etag_value>"
* If-None-Match: "<etag_value>", "<etag_value>", …
* If-None-Match: *
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match
*/
readonly IfNoneMatch: "if-none-match";
/**
* ```txt
* Cache-Control: max-age=604800
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
*/
readonly CacheControl: "cache-control";
/**
* ```txt
* Pragma: no - cache;
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Pragma
*/
readonly Pragma: "pragma";
/**
* ```txt
* ETag: W / '<etag_value>';
* ETag: '<etag_value>';
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
*/
readonly ETag: "etag";
/**
* ```txt
* Expires: <http-date>
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires
*/
readonly Expires: "expires";
/**
* ```txt
* Age: <delta-seconds>
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Age
*/
readonly Age: "age";
/**
* Used internally as metadata to mark the cache item as revalidatable and enabling
* stale cache state Contains a string of ASCII characters that can be used as ETag for
* `If-Match` header Provided by user using `cache.etag` value.
*
* ```txt
* X-Axios-Cache-Etag: "<etag_value>"
* ```
*/
readonly XAxiosCacheEtag: "x-axios-cache-etag";
/**
* Used internally as metadata to mark the cache item as revalidatable and enabling
* stale cache state may contain `'use-cache-timestamp'` if `cache.modifiedSince` is
* `true`, otherwise will contain a date from `cache.modifiedSince`. If a date is
* provided, it can be used for `If-Modified-Since` header, otherwise the cache
* timestamp can be used for `If-Modified-Since` header.
*
* ```txt
* X-Axios-Cache-Last-Modified: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
* X-Axios-Cache-Last-Modified: use-cache-timestamp
* ```
*/
readonly XAxiosCacheLastModified: "x-axios-cache-last-modified";
/**
* Used internally as metadata to mark the cache item able to be used if the server
* returns an error. The stale-if-error response directive indicates that the cache can
* reuse a stale response when any error occurs.
*
* ```txt
* XAxiosCacheStaleIfError: <seconds>
* ```
*/
readonly XAxiosCacheStaleIfError: "x-axios-cache-stale-if-error";
/**
* Indicates which request headers affect the response content.
* Used to prevent cache poisoning when responses differ based on request headers.
*
* ```txt
* Vary: Authorization
* Vary: Authorization, Accept-Language
* Vary: *
* ```
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary
*/
readonly Vary: "vary";
};
//#endregion
//#region src/header/interpreter.d.ts
/**
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare const defaultHeaderInterpreter: HeaderInterpreter;
//#endregion
//#region src/interceptors/request.d.ts
/**
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare function defaultRequestInterceptor(axios: AxiosCacheInstance): RequestInterceptor;
//#endregion
//#region src/interceptors/response.d.ts
/**
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare function defaultResponseInterceptor(axios: AxiosCacheInstance): ResponseInterceptor;
//#endregion
//#region src/interceptors/util.d.ts
/**
* Creates a new validateStatus function that will use the one already used and also
* accept status code 304.
*
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare function createValidateStatus(oldValidate?: CacheRequestConfig['validateStatus']): (status: number) => boolean;
/**
* Checks if the given method is in the methods array
*
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare function isMethodIn(requestMethod?: Method | string, methodList?: Method[]): boolean;
/**
* @deprecated This interface will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
interface ConfigWithCache<D> extends InternalCacheRequestConfig<unknown, D> {
cache: Partial<CacheProperties<unknown, D>>;
}
/**
* This function updates the cache when the request is stale. So, the next request to the
* server will be made with proper header / settings.
*
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare function updateStaleRequest<D>(cache: StaleStorageValue | MustRevalidateStorageValue, config: ConfigWithCache<D>): void;
/**
* Creates the new date to the cache by the provided response. Also handles possible 304
* Not Modified by updating response properties.
*
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare function createCacheResponse<R, D>(response: CacheAxiosResponse<R, D>, previousCache?: CachedResponse): CachedResponse;
//#endregion
//#region src/storage/build.d.ts
/**
* Returns true if the provided object was created from {@link buildStorage} function.
*
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare const isStorage: (obj: unknown) => obj is AxiosStorage;
/** Returns true if value must be revalidated */
declare function mustRevalidate(value: CachedStorageValue | StaleStorageValue): boolean;
/** Returns true if this has sufficient properties to stale instead of expire. */
declare function canStale(value: CachedStorageValue): boolean;
/**
* Checks if the provided cache is expired. You should also check if the cache
* {@link canStale} and {@link mayUseStale}
*/
declare function isExpired(value: CachedStorageValue | StaleStorageValue): boolean;
/**
* Is a comparator function that sorts storage entries by their eviction priority
* and, in the same group, by older first.
*/
declare function storageEntriesSorter([, a]: [string, StorageValue], [, b]: [string, StorageValue]): number;
/**
* Returns true if the storage entry can be removed according to its state and the
* provided maxStaleAge.
*/
declare function canRemoveStorageEntry(value: StorageValue, maxStaleAge: number): boolean;
interface BuildStorage extends Omit<AxiosStorage, 'get'> {
/**
* Returns the value for the given key. This method does not have to make checks for
* cache invalidation or anything. It just returns what was previous saved, if present.
*
* @param key The key to look for
* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
find: (key: string, currentRequest?: CacheRequestConfig) => MaybePromise<StorageValue | undefined>;
}
/**
* All integrated storages are wrappers around the `buildStorage` function. External
* libraries use it and if you want to build your own, `buildStorage` is the way to go!
*
* The exported `buildStorage` function abstracts the storage interface and requires a
* super simple object to build the storage.
*
* **Note**: You can only create custom storages with this function.
*
* @example
*
* ```js
* const myStorage = buildStorage({
* find: () => {...},
* set: () => {...},
* remove: () => {...},
* clear: () => {...}
* });
*
* const axios = setupCache(axios, { storage: myStorage });
* ```
*
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
declare function buildStorage({
set,
find,
remove,
clear
}: BuildStorage): AxiosStorage;
//#endregion
//#region src/storage/memory.d.ts
/**
* Creates a simple in-memory storage. This means that if you need to persist data between
* page or server reloads, this will not help.
*
* This is the storage used by default.
*
* If you need to modify it's data, you can do by the `data` property.
*
* @example
*
* ```js
* const memoryStorage = buildMemoryStorage();
*
* setupCache(axios, { storage: memoryStorage });
*
* // Simple example to force delete the request cache
*
* const { id } = axios.get('url');
*
* delete memoryStorage.data[id];
* ```
*
* @param {boolean | 'double'} cloneData Use `true` if the data returned by `find()`
* should be cloned to avoid mutating the original data outside the `set()` method. Use
* `'double'` to also clone before saving value in storage using `set()`. Disabled is
* default
* @param {number | false} cleanupInterval The interval in milliseconds to run a
* setInterval job of cleaning old entries. If false, the job will not be created.
* 5 minutes (300_000) is default
* @param {number | false} maxEntries The maximum number of entries to keep in the
* storage. Its hard to determine the size of the entries, so a smart FIFO order is used
* to determine eviction. If false, no check will be done and you may grow up memory
* usage. 1024 is default
* @param {number} maxStaleAge The maximum age in milliseconds a stale entry can stay
* in the storage before being removed. Otherwise, stale-able entries would stay
* indefinitely causing a memory leak eventually. 1 hour (3_600_000) is default
*/
declare function buildMemoryStorage(cloneData?: boolean | 'double', cleanupInterval?: number | false, maxEntries?: number | false, maxStaleAge?: number): MemoryStorage;
interface MemoryStorage extends AxiosStorage {
data: Map<string, StorageValue>;
/** The job responsible to cleaning old entries */
cleaner: ReturnType<typeof setInterval>;
/** Tries to remove any invalid entry from the memory */
cleanup: () => void;
}
//#endregion
//#region src/storage/web-api.d.ts
/**
* Creates a simple storage. You can persist his data by using `sessionStorage` or
* `localStorage` with it.
*
* **ImplNote**: Without polyfill, this storage only works on browser environments.
*
* @example
*
* ```js
* const fromLocalStorage = buildWebStorage(localStorage);
* const fromSessionStorage = buildWebStorage(sessionStorage);
*
* const myStorage = new Storage();
* const fromMyStorage = buildWebStorage(myStorage);
* ```
*
* @param storage The type of web storage to use. localStorage or sessionStorage.
* @param prefix The prefix to index the storage. Useful to prevent collision between
* multiple places using the same storage.
* @param {number} maxStaleAge The maximum age in milliseconds a stale entry can stay
* in the storage before being removed. Otherwise, stale-able entries would stay
* indefinitely causing a memory leak eventually. 1 hour (3_600_000) is default
*/
declare function buildWebStorage(storage: Storage, prefix?: string, maxStaleAge?: number): AxiosStorage;
//#endregion
//#region src/util/cache-predicate.d.ts
/**
* Tests an response against a {@link CachePredicateObject}.
*
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare function testCachePredicate<R = unknown, D = unknown>(response: CacheAxiosResponse<R, D>, predicate: CachePredicate<R, D>): Promise<boolean>;
/**
* Determines whether a given URL matches a specified pattern, which can be either a
* string or a regular expression.
*
* @param matchPattern - The pattern to match against
*
* - If it's a regular expression, it will be reset to ensure consistent behavior for
* stateful regular expressions.
* - If it's a string, the function checks if the URL contains the string.
*
* @param configUrl - The URL to test against the provided pattern; normally `config.url`.
* @returns `true` if the `configUrl` matches the `matchPattern`
*
* @deprecated This function will be hidden in future versions. Please tell us why you need it at https://github.com/arthurfiorette/axios-cache-interceptor/issues/1158
*/
declare function regexOrStringMatch(matchPattern: string | RegExp, configUrl: string): boolean;
//#endregion
//#region src/util/key-generator.d.ts
/**
* Builds an generator that receives a {@link CacheRequestConfig} and optio