import { openDB } from 'idb'; import { DATA_VERSION } from './version'; import { cacheableModels, cacheableModelNames } from './cacheableModels'; export class DataManager { constructor(accountId) { this.modelsToSync = cacheableModelNames; this.accountId = accountId; this.db = null; } async initDb() { if (this.db) return this.db; const dbName = `cw-store-${this.accountId}`; this.db = await openDB(dbName, DATA_VERSION, { upgrade(db, oldVersion, _newVersion, tx) { // Flush data carried over from a previous schema version so a // DATA_VERSION bump acts as a global cache reset. oldVersion === 0 on // first install, so fresh devices skip this. Clearing before creating // means we only ever clear stores that pre-existed this upgrade. if (oldVersion > 0) { for (let index = 0; index < db.objectStoreNames.length; index += 1) { tx.objectStore(db.objectStoreNames.item(index)).clear(); } } if (!db.objectStoreNames.contains('cache-keys')) { db.createObjectStore('cache-keys'); } cacheableModels.forEach(model => { if (!db.objectStoreNames.contains(model.name)) { db.createObjectStore(model.name, { keyPath: 'id' }); } }); }, }); // Store the database name in LocalStorage const dbNames = JSON.parse(localStorage.getItem('cw-idb-names') || '[]'); if (!dbNames.includes(dbName)) { dbNames.push(dbName); localStorage.setItem('cw-idb-names', JSON.stringify(dbNames)); } return this.db; } validateModel(name) { if (!name) throw new Error('Model name is not defined'); if (!this.modelsToSync.includes(name)) { throw new Error(`Model ${name} is not defined`); } return true; } async replace({ modelName, data }) { this.validateModel(modelName); await this.db.clear(modelName); return this.push({ modelName, data }); } async push({ modelName, data }) { this.validateModel(modelName); if (Array.isArray(data)) { const tx = this.db.transaction(modelName, 'readwrite'); data.forEach(item => { tx.store.add(item); }); await tx.done; } else { await this.db.add(modelName, data); } } async get({ modelName }) { this.validateModel(modelName); return this.db.getAll(modelName); } async setCacheKeys(cacheKeys) { await Promise.all( Object.entries(cacheKeys).map(([modelName, value]) => this.db.put('cache-keys', value, modelName) ) ); } async getCacheKey(modelName) { this.validateModel(modelName); return this.db.get('cache-keys', modelName); } }