Source: lib/core/utils/LruCache.js

/**
 * A standard Least Recently Used (LRU) Cache implementation.
 * Uses JavaScript Map's insertion order preservation to maintain recency.
 */
export class LruCache {
  /**
   * @param {number} limit - Maximum number of items allowed in the cache.
   * @param {function(string, *): void} [onEvict] - Optional callback triggered when an item is evicted.
   */
  constructor(limit, onEvict = null) {
    if (typeof limit !== 'number' || limit <= 0) {
      throw new Error('LRU Cache limit must be a positive number');
    }
    this.limit = limit;
    this.onEvict = onEvict;
    this.cache = new Map();
  }

  /**
   * Retrieves an item from the cache and updates its recency.
   * @param {string} key
   * @returns {*} The cached value, or undefined if not found.
   */
  get(key) {
    if (!this.cache.has(key)) {
      return undefined;
    }
    const value = this.cache.get(key);
    // Refresh recency by re-inserting
    this.cache.delete(key);
    this.cache.set(key, value);
    return value;
  }

  /**
   * Inserts or updates an item in the cache. Evicts the least recently used item if limit is exceeded.
   * @param {string} key
   * @param {*} value
   */
  set(key, value) {
    if (this.cache.has(key)) {
      this.cache.delete(key);
    } else if (this.cache.size >= this.limit) {
      // Evict least recently used (first key in map iterator)
      const lruKey = this.cache.keys().next().value;
      const lruValue = this.cache.get(lruKey);
      this.cache.delete(lruKey);
      if (typeof this.onEvict === 'function') {
        try {
          this.onEvict(lruKey, lruValue);
        } catch (err) {
          // Prevent errors in user-defined callback from breaking set()
          console.error('Error in LRU Cache onEvict callback:', err);
        }
      }
    }
    this.cache.set(key, value);
  }

  /**
   * Checks if a key exists in the cache without updating its recency.
   * @param {string} key
   * @returns {boolean}
   */
  has(key) {
    return this.cache.has(key);
  }

  /**
   * Deletes an item from the cache.
   * @param {string} key
   * @returns {boolean} True if the item existed and was removed.
   */
  delete(key) {
    return this.cache.delete(key);
  }

  /**
   * Clears all items from the cache.
   */
  clear() {
    this.cache.clear();
  }

  /**
   * Returns the current number of items in the cache.
   * @returns {number}
   */
  get size() {
    return this.cache.size;
  }
}