/** * Persistence.js * Handles asynchronous saving and loading using IndexedDB. * Manages both Active Runs and Persistent Roster data. */ const DB_NAME = "AetherShardsDB"; const RUN_STORE = "Runs"; const ROSTER_STORE = "Roster"; const VERSION = 2; // Bumped version to add Roster store export class Persistence { constructor() { this.db = null; } async init() { return new Promise((resolve, reject) => { const request = indexedDB.open(DB_NAME, VERSION); request.onerror = (e) => reject("DB Error: " + e.target.error); request.onupgradeneeded = (e) => { const db = e.target.result; // Create Runs Store if missing if (!db.objectStoreNames.contains(RUN_STORE)) { db.createObjectStore(RUN_STORE, { keyPath: "id" }); } // Create Roster Store if missing if (!db.objectStoreNames.contains(ROSTER_STORE)) { db.createObjectStore(ROSTER_STORE, { keyPath: "id" }); } }; request.onsuccess = (e) => { this.db = e.target.result; resolve(); }; }); } // --- RUN DATA --- async saveRun(runData) { if (!this.db) await this.init(); return this._put(RUN_STORE, { ...runData, id: "active_run" }); } async loadRun() { if (!this.db) await this.init(); return this._get(RUN_STORE, "active_run"); } async clearRun() { if (!this.db) await this.init(); return this._delete(RUN_STORE, "active_run"); } // --- ROSTER DATA --- async saveRoster(rosterData) { if (!this.db) await this.init(); // Wrap the raw data object in an ID for storage return this._put(ROSTER_STORE, { id: "player_roster", data: rosterData }); } async loadRoster() { if (!this.db) await this.init(); const result = await this._get(ROSTER_STORE, "player_roster"); return result ? result.data : null; } // --- INTERNAL HELPERS --- _put(storeName, item) { return new Promise((resolve, reject) => { const tx = this.db.transaction([storeName], "readwrite"); const store = tx.objectStore(storeName); const req = store.put(item); req.onsuccess = () => resolve(); req.onerror = () => reject(req.error); }); } _get(storeName, key) { return new Promise((resolve, reject) => { const tx = this.db.transaction([storeName], "readonly"); const store = tx.objectStore(storeName); const req = store.get(key); req.onsuccess = () => resolve(req.result); req.onerror = () => reject(req.error); }); } _delete(storeName, key) { return new Promise((resolve, reject) => { const tx = this.db.transaction([storeName], "readwrite"); const store = tx.objectStore(storeName); const req = store.delete(key); req.onsuccess = () => resolve(); req.onerror = () => reject(req.error); }); } }