import { UrlCheckResult } from '../types'; const CACHE_TTL_MS = 5 * 60 * 1000; const API_TIMEOUT_MS = 500; const MAX_CACHE_SIZE = 5000; export class UrlCache { private cache: Map = new Map(); async get(url: string): Promise { const normalized = this.normalizeUrl(url); const entry = this.cache.get(normalized); if (!entry) return null; if (Date.now() > entry.expiresAt) { this.cache.delete(normalized); return null; } return { ...entry.result, cached: true }; } async set(url: string, result: UrlCheckResult): Promise { const normalized = this.normalizeUrl(url); if (this.cache.size >= MAX_CACHE_SIZE) { const firstKey = this.cache.keys().next().value; if (firstKey) this.cache.delete(firstKey); } this.cache.set(normalized, { result, expiresAt: Date.now() + CACHE_TTL_MS, }); } async persistToStorage(): Promise { const entries: Record = {}; for (const [key, value] of this.cache.entries()) { entries[key] = value; } await chrome.storage.local.set({ urlCache: entries }); } async loadFromStorage(): Promise { const data = await chrome.storage.local.get('urlCache') as { urlCache: Record }; if (data.urlCache) { const now = Date.now(); for (const [key, entry] of Object.entries(data.urlCache)) { if (now <= entry.expiresAt) { this.cache.set(key, entry); } } } } getStats(): { size: number; max: number } { return { size: this.cache.size, max: MAX_CACHE_SIZE }; } clear(): void { this.cache.clear(); } private normalizeUrl(url: string): string { try { const u = new URL(url); u.hash = ''; u.search = ''; return u.toString(); } catch { return url.toLowerCase(); } } } export const urlCache = new UrlCache(); export const CACHE_TTL = CACHE_TTL_MS; export const API_TIMEOUT = API_TIMEOUT_MS;