import localforage from 'localforage'; // Define the structure of the stored data interface StorageItem { value: T; expire: number | null; // Expiration timestamp, null means valid permanently } class Storage { constructor() { // Default configuration (optional) localforage.config({ name: 'RiskGuard_V1', storeName: 'key_value_pairs', }); } /** * Set cache (add/update) * @param key Key * @param value Value * @param ttl Expiration time (unit: seconds). If not passed, it will be valid permanently. */ async set(key: string, value: T, ttl?: number): Promise { const expire = ttl ? Date.now() + ttl * 1000 : null; const item: StorageItem = { value, expire, }; await localforage.setItem(key, item); return value; } /** * Get cache (query) * @param key Key * @returns Returns the original data if not expired or does not exist, otherwise returns null */ async get(key: string): Promise { const item = await localforage.getItem>(key); if (!item) return null; // Check if expired if (item.expire !== null && Date.now() > item.expire) { await this.remove(key); // Immediately clean up if expired return null; } return item.value; } /** * Remove cache (delete) * @param key Key */ async remove(key: string): Promise { await localforage.removeItem(key); } /** * Clear all caches */ async clear(): Promise { await localforage.clear(); } /** * Get all keys */ async keys(): Promise { return await localforage.keys(); } } // Export singleton export const storage = new Storage();