diff --git a/src/axios/cache.ts b/src/axios/cache.ts index fe3050b..09b8745 100644 --- a/src/axios/cache.ts +++ b/src/axios/cache.ts @@ -3,15 +3,16 @@ import { applyRequestInterceptor } from '../interceptors/request'; import { applyResponseInterceptor } from '../interceptors/response'; import { MemoryStorage } from '../storage/memory'; import { defaultKeyGenerator } from '../utils/key-generator'; -import { AxiosCacheInstance, CacheInstance, CacheRequestConfig } from './types'; +import { AxiosCacheInstance, CacheInstance, CacheProperties } from './types'; -type Options = CacheRequestConfig['cache'] & Partial; - -export function createCache(axios: AxiosInstance, options: Options = {}): AxiosCacheInstance { +export function createCache( + axios: AxiosInstance, + options: Partial = {} +): AxiosCacheInstance { const axiosCache = axios as AxiosCacheInstance; axiosCache.storage = options.storage || new MemoryStorage(); - axiosCache.generateKey = defaultKeyGenerator; + axiosCache.generateKey = options.generateKey || defaultKeyGenerator; // CacheRequestConfig values axiosCache.defaults = { diff --git a/src/axios/index.ts b/src/axios/index.ts new file mode 100644 index 0000000..4f40e74 --- /dev/null +++ b/src/axios/index.ts @@ -0,0 +1,2 @@ +export * from './cache'; +export * from './types' \ No newline at end of file diff --git a/src/axios/types.ts b/src/axios/types.ts index 591fa83..ed23086 100644 --- a/src/axios/types.ts +++ b/src/axios/types.ts @@ -8,6 +8,57 @@ import type { } from 'axios'; import { CacheStorage } from '../storage/types'; +export type DefaultCacheRequestConfig = AxiosRequestConfig & { + cache: Required; +}; + +export type CacheProperties = { + /** + * The time until the cached value is expired in milliseconds. + * + * @default 1000 * 60 * 5 + */ + maxAge?: number; + + /** + * If this interceptor should configure the cache from the request cache header + * When used, the maxAge property is ignored + * + * @default false + */ + interpretHeader?: boolean; + + /** + * All methods that should be cached. + * + * @default ['get'] + */ + methods?: Lowercase[]; + + /** + * The function to check if the response code permit being cached. + * + * @default ({ status }) => status >= 200 && status < 300 + */ + shouldCache?: (response: AxiosResponse) => boolean; + + /** + * Once the request is resolved, this specifies what requests should we change the cache. + * Can be used to update the request or delete other caches. + * + * If the function returns void, the entry is deleted + * + * This is independent if the request made was cached or not. + * + * The id used is the same as the id on `CacheRequestConfig['id']`, auto-generated or not. + * + * @default {} + */ + update?: { + [id: string]: 'delete' | ((oldValue: any, atual: any) => any | void); + }; +}; + /** * Options that can be overridden per request */ @@ -23,52 +74,7 @@ export type CacheRequestConfig = AxiosRequestConfig & { /** * All cache options for the request */ - cache?: { - /** - * The time until the cached value is expired in milliseconds. - * - * @default 1000 * 60 * 5 - */ - maxAge?: number; - - /** - * If this interceptor should configure the cache from the request cache header - * When used, the maxAge property is ignored - * - * @default false - */ - interpretHeader?: boolean; - - /** - * All methods that should be cached. - * - * @default ['get'] - */ - methods?: Lowercase[]; - - /** - * The function to check if the response code permit being cached. - * - * @default ({ status }) => status >= 200 && status < 300 - */ - shouldCache?: (response: AxiosResponse) => boolean; - - /** - * Once the request is resolved, this specifies what requests should we change the cache. - * Can be used to update the request or delete other caches. - * - * If the function returns void, the entry is deleted - * - * This is independent if the request made was cached or not. - * - * The id used is the same as the id on `CacheRequestConfig['id']`, auto-generated or not. - * - * @default {} - */ - update?: { - [id: string]: 'delete' | ((oldValue: any, atual: any) => any | void); - }; - }; + cache?: CacheProperties; }; export interface CacheInstance { @@ -87,11 +93,19 @@ export interface CacheInstance { generateKey: (options: CacheRequestConfig) => string; } +/** + * Same as the AxiosInstance but with CacheRequestConfig as a config type. + * + * @see AxiosInstance + * @see CacheRequestConfig + * @see CacheInstance + */ export interface AxiosCacheInstance extends AxiosInstance, CacheInstance { (config: CacheRequestConfig): AxiosPromise; (url: string, config?: CacheRequestConfig): AxiosPromise; - defaults: CacheRequestConfig; + defaults: DefaultCacheRequestConfig; + interceptors: { request: AxiosInterceptorManager; response: AxiosInterceptorManager; diff --git a/src/index.ts b/src/index.ts index bf457ad..673a4ce 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ -export { createCache } from './axios/cache'; -export * from './constants'; +export * from './axios'; +export * as Constants from './constants'; export * from './storage'; diff --git a/src/interceptors/request.ts b/src/interceptors/request.ts index 3c4c482..b85d9a6 100644 --- a/src/interceptors/request.ts +++ b/src/interceptors/request.ts @@ -20,7 +20,7 @@ export function applyRequestInterceptor(axios: AxiosCacheInstance) { // The cache header will be set after the response has been read, until that time, the expiration will be -1 expiration: config.cache?.interpretHeader ? -1 - : config.cache?.maxAge || axios.defaults.cache!.maxAge! + : config.cache?.maxAge || axios.defaults.cache.maxAge }); return config; } diff --git a/src/interceptors/response.ts b/src/interceptors/response.ts index 7522f22..4a16f49 100644 --- a/src/interceptors/response.ts +++ b/src/interceptors/response.ts @@ -48,13 +48,13 @@ export function applyResponseInterceptor(axios: AxiosCacheInstance) { const expirationTime = maxAge ? // Header max age in seconds Date.now() + maxAge * 1000 - : response.config.cache?.maxAge || axios.defaults.cache!.maxAge!; + : response.config.cache?.maxAge || axios.defaults.cache.maxAge; cache.expiration = expirationTime; } else { // If the cache expiration has not been set, use the default expiration. cache.expiration = - cache.expiration || response.config.cache?.maxAge || axios.defaults.cache!.maxAge!; + cache.expiration || response.config.cache?.maxAge || axios.defaults.cache.maxAge!; } const data = { body: response.data, headers: response.headers }; diff --git a/src/storage/memory.ts b/src/storage/memory.ts index 663a6e2..efc8200 100644 --- a/src/storage/memory.ts +++ b/src/storage/memory.ts @@ -10,7 +10,6 @@ export class MemoryStorage implements CacheStorage { return value; } - // Fresh copy to prevent code duplication const empty = { data: null, expiration: -1, state: 'empty' } as const; this.storage.set(key, empty); return empty;