/** * Wrapper around window.localStorage for the Respellion platform. * Handles serialization/deserialization, namespaces, and quota limits. */ const STORAGE_PREFIX = 'respellion:'; export const storage = { /** * Get an item from storage * @param {string} key - e.g. 'kb:topics' * @returns {any} */ get(key, defaultValue = null) { try { const item = window.localStorage.getItem(STORAGE_PREFIX + key); return item ? JSON.parse(item) : defaultValue; } catch (e) { console.error(`Error reading ${key} from storage:`, e); return defaultValue; } }, /** * Set an item in storage * @param {string} key * @param {any} value */ set(key, value) { try { const serialized = JSON.stringify(value); window.localStorage.setItem(STORAGE_PREFIX + key, serialized); } catch (e) { if (e.name === 'QuotaExceededError' || e.code === 22) { console.error(`Storage quota exceeded when setting ${key}.`); } else { console.error(`Error saving ${key} to storage:`, e); } } }, /** * Remove an item from storage * @param {string} key */ remove(key) { try { window.localStorage.removeItem(STORAGE_PREFIX + key); } catch (e) { console.error(`Error removing ${key} from storage:`, e); } }, /** * Get all keys matching a specific prefix (e.g. 'kb:topics:') * @param {string} prefix * @returns {string[]} Array of matching keys (without the STORAGE_PREFIX) */ getKeysByPrefix(prefix) { const keys = []; const fullPrefix = STORAGE_PREFIX + prefix; for (let i = 0; i < window.localStorage.length; i++) { const key = window.localStorage.key(i); if (key && key.startsWith(fullPrefix)) { keys.push(key.substring(STORAGE_PREFIX.length)); } } return keys; } };