Skip to content

Commit

Permalink
fix: generic spaghetti that axios brought
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurfiorette committed Oct 12, 2021
1 parent 1713bb0 commit 12a5032
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 66 deletions.
103 changes: 49 additions & 54 deletions src/axios/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {
AxiosInstance,
AxiosDefaults,
AxiosInterceptorManager,
AxiosPromise,
AxiosRequestConfig,
Expand All @@ -9,24 +9,9 @@ import type {
import type { Deferred } from 'typed-core/dist/promises/deferred';
import type { HeaderInterpreter } from '../header/types';
import type { AxiosInterceptor } from '../interceptors/types';
import type {
CachedResponse,
CachedStorageValue,
CacheStorage,
EmptyStorageValue
} from '../storage/types';
import type { CachedResponse, CacheStorage } from '../storage/types';
import type { CachePredicate, KeyGenerator } from '../util/types';

export type CacheUpdater =
| 'delete'
| ((
cached: EmptyStorageValue | CachedStorageValue,
newData: any
) => CachedStorageValue | void);

export type DefaultCacheRequestConfig = AxiosRequestConfig & {
cache: CacheProperties;
};
import type { CacheUpdater } from '../util/update-cache';

export type CacheProperties = {
/**
Expand Down Expand Up @@ -81,11 +66,11 @@ export type CacheProperties = {
};

/**
* @template T The data type that this responses use. Also the same
* generic type as it's request
* @template R The type returned by this response
* @template D The type that the request body was
*/
export type CacheAxiosResponse<T> = AxiosResponse<T> & {
config: CacheRequestConfig<T>;
export type CacheAxiosResponse<R, D> = AxiosResponse<R, D> & {
config: CacheRequestConfig<D>;

/**
* The id used for this request. if config specified an id, the id
Expand All @@ -102,9 +87,9 @@ export type CacheAxiosResponse<T> = AxiosResponse<T> & {
/**
* Options that can be overridden per request
*
* @template T The data that this request should return
* @template D The type for the request body
*/
export type CacheRequestConfig<T> = AxiosRequestConfig<T> & {
export type CacheRequestConfig<D> = 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.
Expand Down Expand Up @@ -159,61 +144,71 @@ export interface CacheInstance {
/**
* The response interceptor that will be used to handle the cache.
*/
responseInterceptor: AxiosInterceptor<CacheAxiosResponse<any>>;
responseInterceptor: AxiosInterceptor<CacheAxiosResponse<unknown, any>>;
}

/**
* Same as the AxiosInstance but with CacheRequestConfig as a config
* type and CacheAxiosResponse as response type.
*
* @see AxiosInstance
* @see Axios
* @see CacheRequestConfig
* @see CacheInstance
*/
export interface AxiosCacheInstance extends AxiosInstance, CacheInstance {
export interface AxiosCacheInstance extends CacheInstance {
<T>(config: CacheRequestConfig<T>): AxiosPromise;
<T>(url: string, config?: CacheRequestConfig<T>): AxiosPromise;

defaults: DefaultCacheRequestConfig;
defaults: AxiosDefaults<any> & {
cache: CacheProperties;
};

interceptors: {
request: AxiosInterceptorManager<CacheRequestConfig<any>>;
response: AxiosInterceptorManager<CacheAxiosResponse<never>>;
response: AxiosInterceptorManager<CacheAxiosResponse<never, any>>;
};

getUri<T>(config?: CacheRequestConfig<T>): string;

request<T = any, R = CacheAxiosResponse<T>>(config: CacheRequestConfig<T>): Promise<R>;
request<R = unknown, D = any>(
config: AxiosRequestConfig<D>
): Promise<CacheRequestConfig<R>>;

get<T = any, R = CacheAxiosResponse<T>>(
get<R = unknown, D = any>(
url: string,
config?: CacheRequestConfig<T>
): Promise<R>;
delete<T = any, R = CacheAxiosResponse<T>>(
config?: AxiosRequestConfig<D>
): Promise<CacheRequestConfig<R>>;

delete<R = unknown, D = any>(
url: string,
config?: CacheRequestConfig<T>
): Promise<R>;
head<T = any, R = CacheAxiosResponse<T>>(
config?: AxiosRequestConfig<D>
): Promise<CacheRequestConfig<R>>;

head<R = unknown, D = any>(
url: string,
config?: CacheRequestConfig<T>
): Promise<R>;
options<T = any, R = CacheAxiosResponse<T>>(
config?: AxiosRequestConfig<D>
): Promise<CacheRequestConfig<R>>;

options<R = unknown, D = any>(
url: string,
config?: CacheRequestConfig<T>
): Promise<R>;
post<T = any, R = CacheAxiosResponse<T>>(
config?: AxiosRequestConfig<D>
): Promise<CacheRequestConfig<R>>;

post<R = unknown, D = any>(
url: string,
data?: any,
config?: CacheRequestConfig<T>
): Promise<R>;
put<T = any, R = CacheAxiosResponse<T>>(
data?: D,
config?: AxiosRequestConfig<D>
): Promise<CacheRequestConfig<R>>;

put<R = unknown, D = any>(
url: string,
data?: any,
config?: CacheRequestConfig<T>
): Promise<R>;
patch<T = any, R = CacheAxiosResponse<T>>(
data?: D,
config?: AxiosRequestConfig<D>
): Promise<CacheRequestConfig<R>>;

patch<R = unknown, D = any>(
url: string,
data?: any,
config?: CacheRequestConfig<T>
): Promise<R>;
data?: D,
config?: AxiosRequestConfig<D>
): Promise<CacheRequestConfig<R>>;
}
8 changes: 4 additions & 4 deletions src/interceptors/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ import type {
} from '../storage/types';
import type { AxiosInterceptor } from './types';

export class CacheRequestInterceptor<R>
implements AxiosInterceptor<CacheRequestConfig<R>>
export class CacheRequestInterceptor<D>
implements AxiosInterceptor<CacheRequestConfig<D>>
{
constructor(readonly axios: AxiosCacheInstance) {}

use = (): void => {
this.axios.interceptors.request.use(this.onFulfilled);
};

onFulfilled = async (config: CacheRequestConfig<R>): Promise<CacheRequestConfig<R>> => {
onFulfilled = async (config: CacheRequestConfig<D>): Promise<CacheRequestConfig<D>> => {
// Skip cache
if (config.cache === false) {
return config;
Expand Down Expand Up @@ -100,7 +100,7 @@ export class CacheRequestInterceptor<R>
* Even though the response interceptor receives this one from
* here, it has been configured to ignore cached responses: true
*/
Promise.resolve<CacheAxiosResponse<R>>({
Promise.resolve<CacheAxiosResponse<unknown, D>>({
config: config,
data: cachedResponse.data,
headers: cachedResponse.headers,
Expand Down
12 changes: 6 additions & 6 deletions src/interceptors/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { checkPredicateObject } from '../util/cache-predicate';
import { updateCache } from '../util/update-cache';
import type { AxiosInterceptor } from './types';

export class CacheResponseInterceptor<R>
implements AxiosInterceptor<CacheAxiosResponse<R>>
export class CacheResponseInterceptor<R, D>
implements AxiosInterceptor<CacheAxiosResponse<R, D>>
{
constructor(readonly axios: AxiosCacheInstance) {}

Expand Down Expand Up @@ -46,15 +46,15 @@ export class CacheResponseInterceptor<R>
};

onFulfilled = async (
axiosResponse: AxiosResponse<R>
): Promise<CacheAxiosResponse<R>> => {
axiosResponse: AxiosResponse<R, D>
): Promise<CacheAxiosResponse<R, D>> => {
const key = this.axios.generateKey(axiosResponse.config);

const response: CacheAxiosResponse<R> = {
const response: CacheAxiosResponse<R, D> = {
id: key,
// When the request interceptor override the request adapter, it means
// that the response.cached will be true and therefore, the request was cached.
cached: (axiosResponse as CacheAxiosResponse<R>).cached || false,
cached: (axiosResponse as CacheAxiosResponse<R, D>).cached || false,
...axiosResponse
};

Expand Down
14 changes: 12 additions & 2 deletions src/util/update-cache.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import type { CacheUpdater } from '../axios/types';
import type { CacheStorage } from '../storage/types';
import type {
CachedStorageValue,
CacheStorage,
EmptyStorageValue
} from '../storage/types';

export type CacheUpdater =
| 'delete'
| ((
cached: EmptyStorageValue | CachedStorageValue,
newData: any
) => CachedStorageValue | void);

export async function updateCache<T = any>(
storage: CacheStorage,
Expand Down

0 comments on commit 12a5032

Please sign in to comment.