UNPKG

axios-cache-interceptor

Version:
90 lines (78 loc) 2.64 kB
import { buildStorage, canStale, isExpired } from './build.js'; import type { StorageValue } from './types.js'; /** * Creates a simple storage. You can persist his data by using `sessionStorage` or * `localStorage` with it. * * **ImplNote**: Without polyfill, this storage only works on browser environments. * * @example * * ```js * const fromLocalStorage = buildWebStorage(localStorage); * const fromSessionStorage = buildWebStorage(sessionStorage); * * const myStorage = new Storage(); * const fromMyStorage = buildWebStorage(myStorage); * ``` * * @param storage The type of web storage to use. localStorage or sessionStorage. * @param prefix The prefix to index the storage. Useful to prevent collision between * multiple places using the same storage. */ export function buildWebStorage(storage: Storage, prefix = 'axios-cache-') { return buildStorage({ clear: () => { for (const key in storage) { if (key.startsWith(prefix)) { storage.removeItem(key); } } }, find: (key) => { const json = storage.getItem(prefix + key); return json ? (JSON.parse(json) as StorageValue) : undefined; }, remove: (key) => { storage.removeItem(prefix + key); }, set: (key, value) => { const save = () => storage.setItem(prefix + key, JSON.stringify(value)); try { return save(); } catch (error) { const allValues: [string, StorageValue][] = Object.entries( storage as Record<string, string> ) .filter((item) => item[0].startsWith(prefix)) .map((item) => [item[0], JSON.parse(item[1]) as StorageValue]); // Remove all expired values for (const value of allValues) { if (value[1].state === 'cached' && isExpired(value[1]) && !canStale(value[1])) { storage.removeItem(value[0]); } } // Try save again after removing expired values try { return save(); } catch { // Storage still full, try removing the oldest value until it can be saved // Descending sort by createdAt const sortedItems = allValues.sort( (a, b) => (a[1].createdAt || 0) - (b[1].createdAt || 0) ); for (const item of sortedItems) { storage.removeItem(item[0]); try { return save(); } catch { // This key didn't free all the required space } } } // Clear the cache for the specified key storage.removeItem(prefix + key); } } }); }