import {CacheProvider} from './cacheProvider'; /** * In-memory Least Recently Used (LRU) cache. */ export class LruCache implements CacheProvider { private cache = new Map(); private readonly capacity: number; private constructor(capacity: number) { this.capacity = capacity; } /** * Initializes a new instance with the given capacity. * * @param {number} capacity The maximum number of entries in the cache. Must be a * positive safe integer. */ public static ofCapacity(capacity: number): LruCache { if (!Number.isSafeInteger(capacity) || capacity < 1) { throw new Error('LRU capacity must be a positive safe integer.'); } return new this(capacity); } public get(key: string, loader: (key: string) => Promise): Promise { if (!this.cache.has(key)) { return loader(key); } const value = this.cache.get(key)!; // Reposition the key as the most recently used value this.cache.delete(key); this.cache.set(key, value); return Promise.resolve(value); } public set(key: string, value: T): Promise { this.cache.set(key, value); this.prune(); return Promise.resolve(); } public delete(key: string): Promise { this.cache.delete(key); return Promise.resolve(); } private prune(): void { while (this.cache.size > this.capacity) { const leastRecentlyUsedKey = this.cache .keys() .next(); this.cache.delete(leastRecentlyUsedKey.value); } } }