import { domtools } from '@design.estate/dees-element'; interface CachedDocument { url: string; document: any; lastAccessed: number; refCount: number; } export class PdfManager { private static cache = new Map(); private static maxCacheSize = 10; private static pdfjsLib: any; private static initialized = false; public static async initialize() { if (this.initialized) return; // @ts-ignore this.pdfjsLib = await import('https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.379/+esm'); this.pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.379/build/pdf.worker.mjs'; this.initialized = true; } public static async loadDocument(url: string): Promise { await this.initialize(); // Check cache first const cached = this.cache.get(url); if (cached) { cached.lastAccessed = Date.now(); cached.refCount++; return cached.document; } // Load new document const loadingTask = this.pdfjsLib.getDocument(url); const document = await loadingTask.promise; // Add to cache with LRU eviction if needed if (this.cache.size >= this.maxCacheSize) { this.evictLeastRecentlyUsed(); } this.cache.set(url, { url, document, lastAccessed: Date.now(), refCount: 1, }); return document; } public static releaseDocument(url: string) { const cached = this.cache.get(url); if (cached) { cached.refCount--; if (cached.refCount <= 0) { // Don't immediately remove, keep for potential reuse cached.refCount = 0; } } } private static evictLeastRecentlyUsed() { let oldestTime = Infinity; let oldestKey: string | null = null; for (const [key, value] of this.cache.entries()) { // Only evict if not currently in use if (value.refCount === 0 && value.lastAccessed < oldestTime) { oldestTime = value.lastAccessed; oldestKey = key; } } if (oldestKey) { const cached = this.cache.get(oldestKey); if (cached?.document) { cached.document.destroy?.(); } this.cache.delete(oldestKey); } } public static clearCache() { for (const cached of this.cache.values()) { if (cached.document) { cached.document.destroy?.(); } } this.cache.clear(); } public static getCacheStats() { return { size: this.cache.size, maxSize: this.maxCacheSize, entries: Array.from(this.cache.entries()).map(([url, data]) => ({ url, refCount: data.refCount, lastAccessed: new Date(data.lastAccessed).toISOString(), })), }; } }