mirror of
https://github.com/arthurfiorette/axios-cache-interceptor.git
synced 2025-12-08 17:36:16 +00:00
fix: proper generic usage to type deep properties
This commit is contained in:
parent
8d5a90e2fd
commit
ce2f5976bc
33
src/cache/axios.ts
vendored
33
src/cache/axios.ts
vendored
@ -12,7 +12,7 @@ import type { CacheInstance, CacheProperties } from './cache';
|
||||
* @template D The type that the request body was
|
||||
*/
|
||||
export type CacheAxiosResponse<R = any, D = any> = AxiosResponse<R, D> & {
|
||||
config: CacheRequestConfig<D>;
|
||||
config: CacheRequestConfig<R, D>;
|
||||
|
||||
/** The id used for this request. if config specified an id, the id will be returned */
|
||||
id: string;
|
||||
@ -24,9 +24,10 @@ export type CacheAxiosResponse<R = any, D = any> = AxiosResponse<R, D> & {
|
||||
/**
|
||||
* Options that can be overridden per request
|
||||
*
|
||||
* @template R The type returned by this response
|
||||
* @template D The type for the request body
|
||||
*/
|
||||
export type CacheRequestConfig<D = any> = AxiosRequestConfig<D> & {
|
||||
export type CacheRequestConfig<R = any, D = any> = AxiosRequestConfig<D> & {
|
||||
/**
|
||||
* An id for this request, if this request is used in cache, only the last request made
|
||||
* with this id will be returned.
|
||||
@ -40,7 +41,7 @@ export type CacheRequestConfig<D = any> = AxiosRequestConfig<D> & {
|
||||
*
|
||||
* False means ignore everything about cache, for this request.
|
||||
*/
|
||||
cache?: false | Partial<CacheProperties>;
|
||||
cache?: false | Partial<CacheProperties<R, D>>;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -58,7 +59,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
* @template D The type that the request body use
|
||||
*/
|
||||
<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
config: CacheRequestConfig<D>
|
||||
config: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
/**
|
||||
* @template T The type returned by this response
|
||||
@ -67,7 +68,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
*/
|
||||
<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
url: string,
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
|
||||
defaults: AxiosDefaults<any> & {
|
||||
@ -75,12 +76,12 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
};
|
||||
|
||||
interceptors: {
|
||||
request: AxiosInterceptorManager<CacheRequestConfig<any>>;
|
||||
response: AxiosInterceptorManager<CacheAxiosResponse<never, any>>;
|
||||
request: AxiosInterceptorManager<CacheRequestConfig<any, any>>;
|
||||
response: AxiosInterceptorManager<CacheAxiosResponse<any, any>>;
|
||||
};
|
||||
|
||||
/** @template D The type that the request body use */
|
||||
getUri<D>(config?: CacheRequestConfig<D>): string;
|
||||
getUri<D>(config?: CacheRequestConfig<any, D>): string;
|
||||
|
||||
/**
|
||||
* @template T The type returned by this response
|
||||
@ -88,7 +89,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
* @template D The type that the request body use
|
||||
*/
|
||||
request<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
|
||||
/**
|
||||
@ -98,7 +99,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
*/
|
||||
get<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
url: string,
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
|
||||
/**
|
||||
@ -108,7 +109,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
*/
|
||||
delete<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
url: string,
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
|
||||
/**
|
||||
@ -118,7 +119,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
*/
|
||||
head<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
url: string,
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
|
||||
/**
|
||||
@ -128,7 +129,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
*/
|
||||
options<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
url: string,
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
|
||||
/**
|
||||
@ -139,7 +140,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
post<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
url: string,
|
||||
data?: D,
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
|
||||
/**
|
||||
@ -150,7 +151,7 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
put<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
url: string,
|
||||
data?: D,
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
|
||||
/**
|
||||
@ -161,6 +162,6 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {
|
||||
patch<T = any, D = any, R = CacheAxiosResponse<T, D>>(
|
||||
url: string,
|
||||
data?: D,
|
||||
config?: CacheRequestConfig<D>
|
||||
config?: CacheRequestConfig<T, D>
|
||||
): Promise<R>;
|
||||
}
|
||||
|
||||
23
src/cache/cache.ts
vendored
23
src/cache/cache.ts
vendored
@ -3,11 +3,14 @@ import type { Deferred } from 'fast-defer';
|
||||
import type { HeadersInterpreter } from '../header/types';
|
||||
import type { AxiosInterceptor } from '../interceptors/types';
|
||||
import type { AxiosStorage, CachedResponse } from '../storage/types';
|
||||
import type { CachePredicate, KeyGenerator } from '../util/types';
|
||||
import type { CacheUpdater } from '../util/update-cache';
|
||||
import type { CachePredicate, CacheUpdater, KeyGenerator } from '../util/types';
|
||||
import type { CacheAxiosResponse, CacheRequestConfig } from './axios';
|
||||
|
||||
export type CacheProperties = {
|
||||
/**
|
||||
* @template R The type returned by this response
|
||||
* @template D The type for the request body
|
||||
*/
|
||||
export type CacheProperties<R = any, D = any> = {
|
||||
/**
|
||||
* The time until the cached value is expired in milliseconds.
|
||||
*
|
||||
@ -18,7 +21,7 @@ export type CacheProperties = {
|
||||
*
|
||||
* @default 1000 * 60 * 5 // 5 Minutes
|
||||
*/
|
||||
ttl: number | (<R, D>(response: CacheAxiosResponse<R, D>) => number | Promise<number>);
|
||||
ttl: number | ((response: CacheAxiosResponse<R, D>) => number | Promise<number>);
|
||||
|
||||
/**
|
||||
* If this interceptor should configure the cache from the request cache header When
|
||||
@ -40,21 +43,21 @@ export type CacheProperties = {
|
||||
*
|
||||
* @default {statusCheck: [200, 399]}
|
||||
*/
|
||||
cachePredicate: CachePredicate;
|
||||
cachePredicate: CachePredicate<R, D>;
|
||||
|
||||
/**
|
||||
* 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 nothing, the entry is deleted
|
||||
*
|
||||
* This is independent if the request made was cached or not.
|
||||
*
|
||||
* If an provided id represents and loading cache, he will be ignored.
|
||||
*
|
||||
* The id used is the same as the id on `CacheRequestConfig['id']`, auto-generated or not.
|
||||
*
|
||||
* @default {{}}
|
||||
*/
|
||||
update: Record<string, CacheUpdater>;
|
||||
update: Record<string, CacheUpdater<R, D>>;
|
||||
|
||||
/**
|
||||
* If the request should handle ETag and If-None-Match support. Use a string to force a
|
||||
@ -104,8 +107,8 @@ export interface CacheInstance {
|
||||
headerInterpreter: HeadersInterpreter;
|
||||
|
||||
/** The request interceptor that will be used to handle the cache. */
|
||||
requestInterceptor: AxiosInterceptor<CacheRequestConfig<any>>;
|
||||
requestInterceptor: AxiosInterceptor<CacheRequestConfig<unknown, unknown>>;
|
||||
|
||||
/** The response interceptor that will be used to handle the cache. */
|
||||
responseInterceptor: AxiosInterceptor<CacheAxiosResponse<any, any>>;
|
||||
responseInterceptor: AxiosInterceptor<CacheAxiosResponse<unknown, unknown>>;
|
||||
}
|
||||
|
||||
2
src/cache/create.ts
vendored
2
src/cache/create.ts
vendored
@ -65,7 +65,7 @@ export function setupCache(
|
||||
axiosCache.storage = storage || buildMemoryStorage();
|
||||
|
||||
if (!isStorage(axiosCache.storage)) {
|
||||
throw new Error('create an storage with buildStorage()');
|
||||
throw new Error('Use buildStorage()');
|
||||
}
|
||||
|
||||
axiosCache.generateKey = generateKey || defaultKeyGenerator;
|
||||
|
||||
@ -17,8 +17,8 @@ import {
|
||||
setRevalidationHeaders
|
||||
} from './util';
|
||||
|
||||
export class CacheRequestInterceptor<D>
|
||||
implements AxiosInterceptor<CacheRequestConfig<D>>
|
||||
export class CacheRequestInterceptor
|
||||
implements AxiosInterceptor<CacheRequestConfig<unknown, unknown>>
|
||||
{
|
||||
constructor(readonly axios: AxiosCacheInstance) {}
|
||||
|
||||
@ -27,8 +27,8 @@ export class CacheRequestInterceptor<D>
|
||||
};
|
||||
|
||||
readonly onFulfilled = async (
|
||||
config: CacheRequestConfig<D>
|
||||
): Promise<CacheRequestConfig<D>> => {
|
||||
config: CacheRequestConfig<unknown>
|
||||
): Promise<CacheRequestConfig<unknown>> => {
|
||||
if (config.cache === false) {
|
||||
return config;
|
||||
}
|
||||
@ -77,7 +77,7 @@ export class CacheRequestInterceptor<D>
|
||||
});
|
||||
|
||||
if (cache.state === 'stale') {
|
||||
setRevalidationHeaders(cache, config as ConfigWithCache<D>);
|
||||
setRevalidationHeaders(cache, config as ConfigWithCache<unknown>);
|
||||
}
|
||||
|
||||
config.validateStatus = createValidateStatus(config.validateStatus);
|
||||
@ -112,8 +112,8 @@ export class CacheRequestInterceptor<D>
|
||||
* Even though the response interceptor receives this one from here, it has been
|
||||
* configured to ignore cached responses: true
|
||||
*/
|
||||
Promise.resolve<CacheAxiosResponse<any, D>>({
|
||||
config: config,
|
||||
Promise.resolve<CacheAxiosResponse<unknown, unknown>>({
|
||||
config,
|
||||
data: cachedResponse.data,
|
||||
headers: cachedResponse.headers,
|
||||
status: cachedResponse.status,
|
||||
|
||||
@ -8,8 +8,8 @@ import { updateCache } from '../util/update-cache';
|
||||
import type { AxiosInterceptor } from './types';
|
||||
import { setupCacheData } from './util';
|
||||
|
||||
export class CacheResponseInterceptor<R, D>
|
||||
implements AxiosInterceptor<CacheAxiosResponse<R, D>>
|
||||
export class CacheResponseInterceptor
|
||||
implements AxiosInterceptor<CacheAxiosResponse<unknown, unknown>>
|
||||
{
|
||||
constructor(readonly axios: AxiosCacheInstance) {}
|
||||
|
||||
@ -18,8 +18,8 @@ export class CacheResponseInterceptor<R, D>
|
||||
};
|
||||
|
||||
readonly onFulfilled = async (
|
||||
axiosResponse: AxiosResponse<R, D>
|
||||
): Promise<CacheAxiosResponse<R, D>> => {
|
||||
axiosResponse: AxiosResponse<unknown, unknown>
|
||||
): Promise<CacheAxiosResponse<unknown, unknown>> => {
|
||||
const response = this.cachedResponse(axiosResponse);
|
||||
|
||||
// Response is already cached
|
||||
@ -101,7 +101,7 @@ export class CacheResponseInterceptor<R, D>
|
||||
|
||||
// Update other entries before updating himself
|
||||
if (cacheConfig?.update) {
|
||||
updateCache(this.axios.storage, response.data, cacheConfig.update);
|
||||
updateCache(this.axios.storage, response, cacheConfig.update);
|
||||
}
|
||||
|
||||
const deferred = this.axios.waiting[response.id];
|
||||
@ -126,12 +126,14 @@ export class CacheResponseInterceptor<R, D>
|
||||
delete this.axios.waiting[key];
|
||||
};
|
||||
|
||||
readonly cachedResponse = (response: AxiosResponse<R, D>): CacheAxiosResponse<R, D> => {
|
||||
readonly cachedResponse = (
|
||||
response: AxiosResponse<unknown, unknown>
|
||||
): CacheAxiosResponse<unknown, unknown> => {
|
||||
return {
|
||||
id: this.axios.generateKey(response.config),
|
||||
// The request interceptor response.cache will return true or undefined. And true only when the response was cached.
|
||||
|
||||
cached: (response as CacheAxiosResponse<R, D>).cached || false,
|
||||
cached: (response as CacheAxiosResponse<unknown, unknown>).cached || false,
|
||||
...response
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type { Method } from 'axios';
|
||||
import type { CachedResponse, CacheProperties, StaleStorageValue } from '..';
|
||||
import type { CacheAxiosResponse, CacheRequestConfig } from '../cache/axios';
|
||||
import type { CacheProperties } from '../cache/cache';
|
||||
import type { CachedResponse, StaleStorageValue } from '../storage/types';
|
||||
import { Header } from '../util/headers';
|
||||
|
||||
/**
|
||||
@ -28,7 +29,7 @@ export function isMethodIn(requestMethod: Method, methodList: Method[] = []): bo
|
||||
return false;
|
||||
}
|
||||
|
||||
export type ConfigWithCache<D> = CacheRequestConfig<D> & {
|
||||
export type ConfigWithCache<D> = CacheRequestConfig<any, D> & {
|
||||
cache: Partial<CacheProperties>;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user