Simple Least Recently Used (LRU) cache implementation extending Map with memory management capabilities
npx @tessl/cli install tessl/npm-quick-lru@7.1.0Quick LRU is a high-performance Least Recently Used (LRU) cache implementation that extends JavaScript's native Map class with memory management capabilities. It supports advanced features including configurable maximum cache size with automatic eviction, optional time-based expiration with lazy cleanup, customizable eviction callbacks, and comprehensive cache management methods.
npm install quick-lruimport QuickLRU from 'quick-lru';For CommonJS:
const QuickLRU = require('quick-lru');import QuickLRU from 'quick-lru';
// Create a cache with maximum 1000 items
const cache = new QuickLRU({ maxSize: 1000 });
// Set values
cache.set('π¦', 'π');
cache.set('π', 'π');
// Get values
cache.get('π¦'); // 'π'
// Check existence
cache.has('π¦'); // true
// Get without affecting recency
cache.peek('π¦'); // 'π'
// Cache with expiration
const cacheWithTTL = new QuickLRU({
maxSize: 100,
maxAge: 60000, // 60 seconds
onEviction: (key, value) => console.log(`Evicted ${key}: ${value}`)
});
cacheWithTTL.set('temp', 'data', { maxAge: 30000 }); // 30 second overrideQuick LRU uses a dual-cache design for optimal performance:
Creates a new QuickLRU cache instance.
class QuickLRU<KeyType, ValueType> extends Map<KeyType, ValueType> {
constructor(options: Options<KeyType, ValueType>);
}
interface Options<KeyType, ValueType> {
/** Maximum number of items before evicting least recently used items */
readonly maxSize: number;
/** Maximum milliseconds an item should remain in cache (default: Infinity) */
readonly maxAge?: number;
/** Called right before an item is evicted from the cache */
onEviction?: (key: KeyType, value: ValueType) => void;
}Usage Example:
// Basic cache
const cache = new QuickLRU({ maxSize: 100 });
// Cache with TTL and eviction callback
const advancedCache = new QuickLRU({
maxSize: 50,
maxAge: 300000, // 5 minutes
onEviction: (key, value) => {
console.log(`Evicted ${key}`);
// Cleanup logic for URLs, file handles, etc.
}
});Sets an item in the cache with optional per-item expiration.
/**
* Set an item in the cache
* @param key - The key to store the value under
* @param value - The value to store
* @param options - Optional settings for this specific item
* @returns The cache instance for chaining
*/
set(key: KeyType, value: ValueType, options?: { maxAge?: number }): this;Usage Example:
cache.set('user:123', userData);
cache.set('session:abc', sessionData, { maxAge: 3600000 }); // 1 hour TTLRetrieves an item from the cache and marks it as recently used.
/**
* Get an item from the cache
* @param key - The key to retrieve
* @returns The stored value or undefined if not found or expired
*/
get(key: KeyType): ValueType | undefined;Checks if an item exists in the cache without affecting its recency.
/**
* Check if an item exists in the cache
* @param key - The key to check
* @returns True if the item exists and is not expired
*/
has(key: KeyType): boolean;Gets an item without marking it as recently used.
/**
* Get an item without marking it as recently used
* @param key - The key to peek at
* @returns The stored value or undefined if not found or expired
*/
peek(key: KeyType): ValueType | undefined;Removes an item from the cache.
/**
* Delete an item from the cache
* @param key - The key to delete
* @returns True if the item was removed, false if it didn't exist
*/
delete(key: KeyType): boolean;Removes all items from the cache.
/**
* Delete all items from the cache
*/
clear(): void;Gets the remaining time to live for an item.
/**
* Get remaining time to live for an item in milliseconds
* @param key - The key to check
* @returns Milliseconds until expiration, Infinity if no expiration, or undefined if item doesn't exist
*/
expiresIn(key: KeyType): number | undefined;Usage Example:
cache.set('temp', 'data', { maxAge: 60000 });
setTimeout(() => {
const ttl = cache.expiresIn('temp');
console.log(`Item expires in ${ttl}ms`);
}, 30000);Updates the maximum cache size, discarding items as necessary.
/**
* Update the maximum cache size
* @param maxSize - New maximum size (must be > 0)
* @throws TypeError if maxSize is not a number greater than 0
*/
resize(maxSize: number): void;Usage Example:
const cache = new QuickLRU({ maxSize: 100 });
// Later, dynamically adjust size based on memory constraints
cache.resize(50); // Evicts oldest items if neededGets the current number of items in the cache.
/**
* The current number of items stored in the cache
*/
get size(): number;Gets the maximum number of items the cache can hold.
/**
* The maximum number of items the cache can hold
*/
get maxSize(): number;Iterates over all keys in the cache.
/**
* Iterator for all keys in the cache
* @returns Iterator of keys in recency order (oldest first)
*/
keys(): IterableIterator<KeyType>;Iterates over all values in the cache.
/**
* Iterator for all values in the cache
* @returns Iterator of values in recency order (oldest first)
*/
values(): IterableIterator<ValueType>;Default iterator for the cache (same as entriesAscending).
/**
* Default iterator returning key-value pairs
* @returns Iterator of [key, value] pairs in recency order (oldest first)
*/
[Symbol.iterator](): IterableIterator<[KeyType, ValueType]>;Usage Example:
// Using for...of loop
for (const [key, value] of cache) {
console.log(`${key}: ${value}`);
}
// Using spread operator
const entries = [...cache];Iterates over entries from oldest to newest.
/**
* Iterator for entries in ascending recency order (oldest first)
* @returns Iterator of [key, value] pairs
*/
entriesAscending(): IterableIterator<[KeyType, ValueType]>;Iterates over entries from newest to oldest.
/**
* Iterator for entries in descending recency order (newest first)
* @returns Iterator of [key, value] pairs
*/
entriesDescending(): IterableIterator<[KeyType, ValueType]>;Map-compatible entries method (same as entriesAscending).
/**
* Iterator for entries (Map compatibility)
* @returns Iterator of [key, value] pairs in ascending recency order
*/
entries(): IterableIterator<[KeyType, ValueType]>;Executes a callback for each entry in the cache.
/**
* Execute a callback for each entry in the cache
* @param callbackFunction - Function called for each entry
* @param thisArgument - Value to use as 'this' when executing callback
*/
forEach(
callbackFunction: (value: ValueType, key: KeyType, cache: this) => void,
thisArgument?: any
): void;Usage Example:
cache.forEach((value, key) => {
console.log(`Processing ${key}: ${value}`);
});Returns a string representation of the cache.
/**
* Returns string representation of the cache
* @returns String in format "QuickLRU(currentSize/maxSize)"
*/
toString(): string;Provides the string tag for Object.prototype.toString.
/**
* String tag for Object.prototype.toString
*/
get [Symbol.toStringTag](): 'QuickLRU';Custom inspect method for Node.js util.inspect.
/**
* Custom inspect method for Node.js util.inspect
* @returns String representation of the cache
*/
[Symbol.for('nodejs.util.inspect.custom')](): string;Quick LRU throws TypeError in the following cases:
maxSize is not a number greater than 0maxAge is explicitly set to 0 (use undefined for no expiration)maxSize parameter is not a number greater than 0// These will throw TypeError
try {
new QuickLRU({ maxSize: 0 }); // maxSize must be > 0
new QuickLRU({ maxSize: 100, maxAge: 0 }); // maxAge cannot be 0
} catch (error) {
console.error(error.message);
}const cache = new QuickLRU({
maxSize: 1000,
maxAge: 300000, // 5 minutes
onEviction: (key, value) => {
// Cleanup resources
if (value && typeof value.cleanup === 'function') {
value.cleanup();
}
}
});// Monitor memory usage and adjust cache size
function adjustCacheSize(cache, memoryUsage) {
const targetSize = memoryUsage > 0.8 ? 50 : 200;
if (cache.maxSize !== targetSize) {
cache.resize(targetSize);
}
}// Different TTLs for different data types
cache.set('user:profile', userData, { maxAge: 3600000 }); // 1 hour
cache.set('user:session', sessionData, { maxAge: 1800000 }); // 30 minutes
cache.set('static:config', configData); // Uses default maxAge