🗄️🔥💨 Axios Cache Interceptor




Forks Issues Stars License Codecov Npm



### `axios-cache-interceptor` is a axios wrapper for caching and preventing unneeded requests
```ts import axios from 'axios'; import { useCache, SessionCacheStorage } from 'axios-cache-interceptor'; // An axios instance with modified types const api = useCache(axios.create(), { /* options */ }); // Make a simple request, with caching support, to the api const resp1 = await api.get('https://api.example.com/'); // resp1.cached = false const resp2 = await api.get('https://api.example.com/'); // resp2.cached = true ```

## Table of contents - [Table of contents](#table-of-contents) - [Installing](#installing) - [Support list](#support-list) - [Getting Started](#getting-started) - [What we support](#what-we-support) - [Basic Knowledge](#basic-knowledge) - [Request id](#request-id) - [Response object](#response-object) - [response.cached](#responsecached) - [response.id](#responseid) - [Global configuration](#global-configuration) - [config.storage](#configstorage) - [config.generateKey](#configgeneratekey) - [config.waiting](#configwaiting) - [config.headerInterpreter](#configheaderinterpreter) - [config.requestInterceptor and config.responseInterceptor](#configrequestinterceptor-and-configresponseinterceptor) - [Per-request configuration](#per-request-configuration) - [request.id](#requestid) - [request.cache.ttl](#requestcachettl) - [request.cache.interpretHeader](#requestcacheinterpretheader) - [request.cache.methods](#requestcachemethods) - [request.cache.cachePredicate](#requestcachecachepredicate) - [request.cache.update](#requestcacheupdate) - [License](#license) - [Contact](#contact)
## Installing > Axios is a peer dependency and must be installed separately. ```sh # Npm npm install --save axios axios-cache-interceptor # Yarn yarn add axios axios-cache-interceptor ```
## Support list Below you can check what version of this package is supported by your version of axios. But that does not mean that won't work with any version. Most of "breaking changes" made by axios was it's types. > **NOTE**: Below v0.3, axios was not configured as a peer dependency | [Version](https://github.com/ArthurFiorette/axios-cache-interceptor/releases) | [Axios](https://github.com/axios/axios/releases) | | ----------------------------------------------------------------------------- | ------------------------------------------------ | | `~v0.4` | `>= v0.32` | | `~v0.3` | `>= v0.22` | | `<= v0.2` | `v0.21` |
## Getting Started To you use this cache interceptor, you can apply to an existing instance or create a new one. ```js import { useCache } from 'axios-cache-interceptor'; // Your axios instance let axios; // Return the same axios instance, but with a modified Typescript type. axios = useCache(axios, { /* options here */ }); ``` or by creating a new one: ```js import { createCache } from 'axios-cache-interceptor'; const axios = createCache({ /* options here */ }); ``` After that, you can made your own requests normally.
## What we support - [x] Concurrent requests - [x] Typescript support - [x] Unit tests - [x] Header interpretation - [x] Infinity storage options - [x] Cache revalidation from responses - [ ] External storages, like redis ## Basic Knowledge ### Request id A good thing to know is that every request passed through this interceptor, has an id. **This does not mean that is a unique id**. The id is used in a number of ways, but the most important is to bind a request to its cache. The id generation is good enough to generate the same id for theoretically sames requests. The example of this is a request with `{ baseUrl: 'https://a.com/', url: '/b' }` results to the same id with `{ url: 'https://a.com/b/' }`. Also, a custom id can be used to treat two requests as the same. ```js axios.get('...', { id: 'my-custom-id', cache: { // other properties... } }); ``` The [default](src/util/key-generator.ts) id generation can clarify this idea. ### Response object Every response that came from our custom axios instance, will have some extras properties, that you can retrieve like that: ```js const result = await cache.get(/* ... */); const id = result['propertyName']; ``` #### response.cached A simple boolean to check whether this request was cached or not. **NOTE**: The first response of a request capable of being cached will return `cached: false`, as only your next requests will return `cached: true`. #### response.id The [request id](#request-id) resolved. This property represents the ID used throughout the internal code. Remember that, depending on the [config.keyGenerator](#configgeneratekey), it can be different as the provided on the [request.id](#requestid).
## Global configuration When applying the interceptor, you can customize some properties: ```js const axios = createCache({ // Properties here }); ``` ### config.storage The storage used to save the cache. Here will probably be the most changed property. Defaults to [MemoryStorage](src/storage/memory.ts). You can create your own implementation by implementing [CacheStorage](src/storage/types.ts). There are few built in storage implementations, you can use them by importing: ```js import /* ... */ 'axios-cache-interceptor/dist/storage/{name}'; ``` - [MemoryStorage](src/storage/memory.ts) `import 'axios-cache-interceptor/dist/storage/memory';` - [Session and Local Storage](src/storage/web.ts) `import 'axios-cache-interceptor/dist/storage/web';` - _Maybe your own?_ (PR's are welcome) ### config.generateKey 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, and url. ### config.waiting A simple object that will hold a promise for each pending request. Used to handle concurrent requests. Can also be used as type of _listener_ to know when a request is finished. ### config.headerInterpreter The function used to interpret all headers from a request and determine a time to live (`ttl`) number. Check out the [inline documentation](src/header/types.ts) to know how to modify your own. ### config.requestInterceptor and config.responseInterceptor The used request and response interceptor. Basically the core function of this library. Check out the used [request](src/interceptors/request.ts) and [response](src/interceptors/response.ts) to see the default used.
## Per-request configuration By using this axios client and using an ide with intellisense, you'll see a custom property called `cache`. The inline documentation is self explanatory, but here are some examples and information: ### request.id You can override the request id used by this property. ### request.cache.ttl The time that the request will remain in cache. Some custom storage implementations may not respect 100% the time. When using `interpretHeader`, this value is ignored. ### request.cache.interpretHeader If activated, when the response is received, the `ttl` property will be inferred from the requests headers. See the actual implementation of the [`interpretHeader`](src/header/interpreter.ts) method for more information. You can override the default behavior by setting the `headerInterpreter` when creating the cached axios client. ### request.cache.methods Specify what request methods should be cached. Defaults to only `GET` methods. ### request.cache.cachePredicate An object or function that will be tested against the response to test if it can be cached. See the [inline documentation](src/util/cache-predicate.ts) for more. An simple example with all values: ```js axios.get('url', { cache: { cachePredicate: { // Only cache if the response comes with a *good* status code statusCheck: [200, 399], // Tests against any header present in the response. containsHeader: { 'x-custom-header': true, 'x-custom-header-2': 'only if matches this string', 'x-custom-header-3': (value) => /* some calculation */ true }, // Check custom response body responseMatch: (response) => { // Sample that only caches if the response is authenticated return response.auth.status === 'authenticated': } } } }); ``` ### request.cache.update 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. Example: ```js // Retrieved together with their responses let otherResponseId; let userInfoResponseId; axios.get('url', { cache: { update: { // Evict the otherRequestId cache when this response arrives [otherResponseId]: 'delete', // An example that update the "user info response cache" when doing a login. // Imagine this request is a login one. [userInfoResponseId]: (cachedValue, thisResponse) => { return { ...cachedValue, user: thisResponse.user.info }; } } } }); ```
## License Licensed under the **MIT**. See [`LICENSE`](LICENSE) for more informations.
## Contact See my contact information on my [github profile](https://github.com/ArthurFiorette) or open a new issue.