import type { Cipher, Folder, Send } from './types'; export interface VaultCoreSnapshot { ciphers: Cipher[]; folders: Folder[]; sends: Send[]; } interface VaultCoreCacheRecord { cacheKey: string; revisionStamp: number; savedAt: number; snapshot: VaultCoreSnapshot; } const DB_NAME = 'nodewarden-web-cache'; const DB_VERSION = 1; const VAULT_CORE_STORE = 'vault-core'; let dbPromise: Promise | null = null; function supportsIndexedDb(): boolean { return typeof indexedDB !== 'undefined'; } function openDatabase(): Promise { if (!supportsIndexedDb()) return Promise.resolve(null); if (dbPromise) return dbPromise; dbPromise = new Promise((resolve) => { try { const request = indexedDB.open(DB_NAME, DB_VERSION); request.onupgradeneeded = () => { const db = request.result; if (!db.objectStoreNames.contains(VAULT_CORE_STORE)) { db.createObjectStore(VAULT_CORE_STORE, { keyPath: 'cacheKey' }); } }; request.onsuccess = () => resolve(request.result); request.onerror = () => resolve(null); request.onblocked = () => resolve(null); } catch { resolve(null); } }); return dbPromise; } function withStore( mode: IDBTransactionMode, run: (store: IDBObjectStore) => Promise ): Promise { return openDatabase().then((db) => { if (!db) return null; return new Promise((resolve) => { try { const tx = db.transaction(VAULT_CORE_STORE, mode); const store = tx.objectStore(VAULT_CORE_STORE); void run(store).then(resolve).catch(() => resolve(null)); tx.onerror = () => resolve(null); tx.onabort = () => resolve(null); } catch { resolve(null); } }); }); } export async function loadCachedVaultCoreSnapshot(cacheKey: string): Promise { const normalized = String(cacheKey || '').trim(); if (!normalized) return null; return withStore('readonly', (store) => new Promise((resolve) => { const request = store.get(normalized); request.onsuccess = () => { const record = request.result as VaultCoreCacheRecord | undefined; resolve(record || null); }; request.onerror = () => resolve(null); })); } export async function saveCachedVaultCoreSnapshot( cacheKey: string, revisionStamp: number, snapshot: VaultCoreSnapshot ): Promise { const normalized = String(cacheKey || '').trim(); if (!normalized) return; await withStore('readwrite', (store) => new Promise((resolve) => { const record: VaultCoreCacheRecord = { cacheKey: normalized, revisionStamp, savedAt: Date.now(), snapshot, }; const request = store.put(record); request.onsuccess = () => resolve(); request.onerror = () => resolve(); })); } export async function clearCachedVaultCoreSnapshot(cacheKey: string): Promise { const normalized = String(cacheKey || '').trim(); if (!normalized) return; await withStore('readwrite', (store) => new Promise((resolve) => { const request = store.delete(normalized); request.onsuccess = () => resolve(); request.onerror = () => resolve(); })); }