/** * Minimal IndexedDB queue for sync operations (optional extension). * Usage: queueSyncItem({ method, url, headers, body }); flushSyncQueue() when online. */ (function (global) { const DB_NAME = 'smoa_sync_queue'; const STORE = 'pending'; function openDb() { return new Promise(function (resolve, reject) { const r = indexedDB.open(DB_NAME, 1); r.onerror = function () { reject(r.error); }; r.onupgradeneeded = function () { r.result.createObjectStore(STORE, { keyPath: 'id', autoIncrement: true }); }; r.onsuccess = function () { resolve(r.result); }; }); } global.queueSyncItem = function (item) { return openDb().then(function (db) { return new Promise(function (resolve, reject) { const tx = db.transaction(STORE, 'readwrite'); tx.objectStore(STORE).add({ created: Date.now(), item: item }); tx.oncomplete = function () { resolve(); }; tx.onerror = function () { reject(tx.error); }; }); }); }; global.flushSyncQueue = function (fetchImpl) { var f = fetchImpl || fetch; return openDb().then(function (db) { return new Promise(function (resolve) { const tx = db.transaction(STORE, 'readonly'); const req = tx.objectStore(STORE).getAll(); req.onsuccess = function () { var rows = req.result || []; resolve(rows); }; }); }).then(function (rows) { return Promise.all( rows.map(function (row) { var it = row.item; return f(it.url, { method: it.method, headers: it.headers, body: it.body }); }) ); }); }; })(typeof window !== 'undefined' ? window : this);