Skip to content

Commit

Permalink
refactor: externalized cache eviction predicate
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurfiorette committed Oct 25, 2021
1 parent 95de9fc commit f141b2e
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 12 deletions.
9 changes: 6 additions & 3 deletions src/interceptors/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ export class CacheResponseInterceptor<R, D>

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.

/**
* The request interceptor response.cache will return true or
* undefined. And true only when the response was cached.
*/
cached: (axiosResponse as CacheAxiosResponse<R, D>).cached || false,
...axiosResponse
};
Expand All @@ -60,7 +63,7 @@ export class CacheResponseInterceptor<R, D>
return { ...response, cached: false };
}

// Response was marked as cached
// Response is already cached
if (response.cached) {
return response;
}
Expand Down
3 changes: 2 additions & 1 deletion src/storage/memory.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { CacheStorage, StorageValue } from './types';
import { isCacheValid } from './util';

export class MemoryStorage implements CacheStorage {
private readonly storage: Map<string, StorageValue> = new Map();
Expand All @@ -10,7 +11,7 @@ export class MemoryStorage implements CacheStorage {
return { state: 'empty' };
}

if (value.state === 'cached' && value.createdAt + value.ttl < Date.now()) {
if (!isCacheValid(value)) {
this.remove(key);
return { state: 'empty' };
}
Expand Down
20 changes: 20 additions & 0 deletions src/storage/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { StorageValue } from './types';

/**
* Returns true if a storage value can still be used by checking his
* createdAt and ttl values.
*
* @param value The stored value
* @returns True if the cache can still be used
*/
export function isCacheValid(value: StorageValue): boolean {
if (!value) {
return false;
}

if (value.state !== 'cached') {
return false;
}

return value.createdAt + value.ttl > Date.now();
}
22 changes: 14 additions & 8 deletions src/storage/web.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import type { CacheStorage, StorageValue } from './types';
import { isCacheValid } from './util';

/**
* A storage that uses any {@link Storage} as his storage.
*/
export abstract class WindowStorageWrapper implements CacheStorage {
constructor(readonly storage: Storage, readonly prefix: string = 'axios-cache:') {}
constructor(readonly storage: Storage, readonly prefix: string = DEFAULT_KEY_PREFIX) {}

get = async (_key: string): Promise<StorageValue> => {
const key = this.prefix + _key;
const json = this.storage.getItem(key);
get = async (key: string): Promise<StorageValue> => {
const prefixedKey = this.prefixKey(key);
const json = this.storage.getItem(prefixedKey);

if (!json) {
return { state: 'empty' };
}

const parsed = JSON.parse(json);

if (parsed.state === 'cached' && parsed.createdAt + parsed.ttl < Date.now()) {
this.storage.removeItem(key);
if (!isCacheValid(parsed)) {
this.storage.removeItem(prefixedKey);
return { state: 'empty' };
}

Expand All @@ -25,12 +27,14 @@ export abstract class WindowStorageWrapper implements CacheStorage {

set = async (key: string, value: StorageValue): Promise<void> => {
const json = JSON.stringify(value);
this.storage.setItem(this.prefix + key, json);
this.storage.setItem(this.prefixKey(key), json);
};

remove = async (key: string): Promise<void> => {
this.storage.removeItem(this.prefix + key);
this.storage.removeItem(this.prefixKey(key));
};

private prefixKey = (key: string): string => `${this.prefix}:${key}`;
}

export class LocalCacheStorage extends WindowStorageWrapper {
Expand All @@ -44,3 +48,5 @@ export class SessionCacheStorage extends WindowStorageWrapper {
super(window.sessionStorage, prefix);
}
}

export const DEFAULT_KEY_PREFIX = 'axios-cache-interceptor';

0 comments on commit f141b2e

Please sign in to comment.