UNPKG

sveltekit-sync

Version:
109 lines (108 loc) 3.55 kB
import { openDB } from 'idb'; import { browser } from '$app/environment'; export class IDBAdapter { db = null; dbName; version; constructor(dbName = 'sync-db', version = 1) { this.dbName = dbName; this.version = version; if (!this.db && browser) this.init(); } ensureInitialized() { if (!this.db) { throw new Error('Database not initialized. Call adapter.init() first.'); } } async init(schema) { if (this.db) return; // Already initialized this.db = await openDB(this.dbName, this.version, { upgrade(db) { // Create default stores if (!db.objectStoreNames.contains('sync_queue')) { db.createObjectStore('sync_queue', { keyPath: 'id' }); } if (!db.objectStoreNames.contains('sync_meta')) { db.createObjectStore('sync_meta', { keyPath: 'key' }); } // Create user-defined stores if (schema) { Object.keys(schema).forEach(table => { if (!db.objectStoreNames.contains(table)) { db.createObjectStore(table, { keyPath: 'id' }); } }); } }, }); } async insert(table, data) { if (!this.db) throw new Error('Database not initialized'); await this.db.add(table, data); return data; } async update(table, id, data) { if (!this.db) throw new Error('Database not initialized'); const updated = { ...data, id }; await this.db.put(table, updated); return updated; } async delete(table, id) { if (!this.db) throw new Error('Database not initialized'); await this.db.delete(table, id); } async find(table, query) { if (!this.db) throw new Error('Database not initialized'); return this.db.getAll(table); } async findOne(table, id) { if (!this.db) throw new Error('Database not initialized'); const result = await this.db.get(table, id); return result || null; } async addToQueue(op) { await this.insert('sync_queue', op); } async getQueue() { return this.find('sync_queue'); } async removeFromQueue(ids) { if (!this.db) throw new Error('Database not initialized'); const tx = this.db.transaction('sync_queue', 'readwrite'); await Promise.all(ids.map(id => tx.store.delete(id))); await tx.done; } async updateQueueStatus(id, status, error) { const op = await this.findOne('sync_queue', id); if (op) { await this.update('sync_queue', id, { ...op, status, error }); } } async getLastSync() { const meta = await this.findOne('sync_meta', 'lastSync'); return meta?.value || 0; } async setLastSync(timestamp) { await this.update('sync_meta', 'lastSync', { key: 'lastSync', value: timestamp, }); } async getClientId() { let meta = await this.findOne('sync_meta', 'clientId'); if (!meta) { const clientId = crypto.randomUUID(); await this.insert('sync_meta', { key: 'clientId', value: clientId }); return clientId; } return meta.value; } }