UNPKG

@oxyhq/services

Version:

Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀

250 lines (228 loc) • 5.22 kB
"use strict"; /** * Centralized cache utility with TTL support * * This is a production-ready cache implementation used across the codebase * for consistent caching behavior and performance optimization. */ /** * Cache entry with expiration tracking */ /** * Cache statistics */ /** * TTL-based cache implementation * * Features: * - Automatic expiration based on TTL * - Manual cleanup of expired entries * - Statistics tracking (hits, misses, hit rate) * - Type-safe generic interface * * @example * ```typescript * const cache = new TTLCache<string>(5 * 60 * 1000); // 5 minutes * * // Set with default TTL * cache.set('key', 'value'); * * // Set with custom TTL * cache.set('key', 'value', 10 * 60 * 1000); // 10 minutes * * // Get value * const value = cache.get('key'); * * // Get statistics * const stats = cache.getStats(); * ``` */ export class TTLCache { cache = new Map(); hits = 0; misses = 0; /** * Create a new TTL cache * @param defaultTTL Default TTL in milliseconds (default: 5 minutes) */ constructor(defaultTTL = 5 * 60 * 1000) { this.defaultTTL = defaultTTL; } /** * Get a value from cache * @param key Cache key * @returns Cached value or null if not found or expired */ get(key) { const entry = this.cache.get(key); if (!entry) { this.misses++; return null; } const now = Date.now(); if (now > entry.expiresAt) { this.cache.delete(key); this.misses++; return null; } this.hits++; return entry.data; } /** * Set a value in cache * @param key Cache key * @param data Data to cache * @param ttl Optional TTL override (uses default if not provided) */ set(key, data, ttl) { const now = Date.now(); const expiresAt = now + (ttl || this.defaultTTL); this.cache.set(key, { data, timestamp: now, expiresAt }); } /** * Delete a specific cache entry * @param key Cache key * @returns true if entry was deleted, false if not found */ delete(key) { return this.cache.delete(key); } /** * Clear all cache entries */ clear() { this.cache.clear(); this.hits = 0; this.misses = 0; } /** * Check if a key exists and is not expired * @param key Cache key * @returns true if key exists and is valid */ has(key) { const entry = this.cache.get(key); if (!entry) return false; if (Date.now() > entry.expiresAt) { this.cache.delete(key); return false; } return true; } /** * Get all valid cache keys * @returns Array of valid cache keys */ keys() { const now = Date.now(); const validKeys = []; for (const [key, entry] of this.cache.entries()) { if (now <= entry.expiresAt) { validKeys.push(key); } else { this.cache.delete(key); } } return validKeys; } /** * Clean up expired entries * @returns Number of entries removed */ cleanup() { const now = Date.now(); let removed = 0; for (const [key, entry] of this.cache.entries()) { if (now > entry.expiresAt) { this.cache.delete(key); removed++; } } return removed; } /** * Get cache size (number of entries) */ size() { return this.cache.size; } /** * Get cache statistics */ getStats() { const total = this.hits + this.misses; return { size: this.cache.size, hits: this.hits, misses: this.misses, hitRate: total > 0 ? this.hits / total : 0 }; } /** * Reset statistics (keeps cache entries) */ resetStats() { this.hits = 0; this.misses = 0; } } /** * Create a TTL cache instance (convenience function) * * @example * ```typescript * const cache = createCache<string>(5 * 60 * 1000); * ``` */ export function createCache(ttl = 5 * 60 * 1000) { return new TTLCache(ttl); } /** * Global cache cleanup interval (runs every minute) * This helps prevent memory leaks from expired cache entries */ let cleanupInterval = null; const activeCaches = new Set(); /** * Register a cache for automatic cleanup * @param cache Cache instance to register */ export function registerCacheForCleanup(cache) { activeCaches.add(cache); // Start cleanup interval if not already running if (!cleanupInterval) { cleanupInterval = setInterval(() => { for (const cache of activeCaches) { cache.cleanup(); } }, 60000); // Every minute } } /** * Unregister a cache from automatic cleanup * @param cache Cache instance to unregister */ export function unregisterCacheFromCleanup(cache) { activeCaches.delete(cache); // Stop cleanup interval if no caches are registered if (activeCaches.size === 0 && cleanupInterval) { clearInterval(cleanupInterval); cleanupInterval = null; } } /** * Stop all cleanup intervals (useful for testing) * This will clear the interval and unregister all caches */ export function stopAllCleanupIntervals() { if (cleanupInterval) { clearInterval(cleanupInterval); cleanupInterval = null; } activeCaches.clear(); } //# sourceMappingURL=cache.js.map