/* eslint-disable no-shadow */ interface CacheEntry { version: string; value: T; } export class Store { readonly dbp: Promise; // eslint-disable-next-line default-param-last constructor(dbName = "tg-cache", readonly storeName = "keyval") { this.dbp = new Promise((resolve, reject) => { const openreq = indexedDB.open(dbName, 1); openreq.onerror = () => reject(openreq.error); openreq.onsuccess = () => resolve(openreq.result); // First time setup: create an empty object store openreq.onupgradeneeded = () => { openreq.result.createObjectStore(storeName); }; }); } withIDBStore( type: IDBTransactionMode, callback: (store: IDBObjectStore) => void ): Promise { return this.dbp.then( (db) => new Promise((resolve, reject) => { const transaction = db.transaction(this.storeName, type); transaction.oncomplete = () => resolve(); transaction.onabort = () => reject(transaction.error); transaction.onerror = () => reject(transaction.error); callback(transaction.objectStore(this.storeName)); }) ); } } let defaultStore: Store; function getDefaultStore() { if (!defaultStore) defaultStore = new Store(); return defaultStore; } export function get( key: IDBValidKey, store = getDefaultStore() ): Promise> { let req: IDBRequest; return store .withIDBStore("readonly", (idbstore) => { req = idbstore.get(key); }) .then(() => req.result); } export function set( key: IDBValidKey, value: Type, version: string, store = getDefaultStore() ): Promise { return store.withIDBStore("readwrite", (idbstore) => { idbstore.put({ version, value }, key); }); } export function del( key: IDBValidKey, store = getDefaultStore() ): Promise { return store.withIDBStore("readwrite", (idbstore) => { idbstore.delete(key); }); } export function clear(store = getDefaultStore()): Promise { return store.withIDBStore("readwrite", (idbstore) => { idbstore.clear(); }); } export function keys(store = getDefaultStore()): Promise { const dbkeys: IDBValidKey[] = []; return store .withIDBStore("readonly", (idbstore) => { // This would be store.getAllKeys(), but it isn't supported by Edge or Safari. // And openKeyCursor isn't supported by Safari. (idbstore.openKeyCursor || idbstore.openCursor).call(idbstore).onsuccess = function () { if (!this.result) return; dbkeys.push(this.result.key); this.result.continue(); }; }) .then(() => dbkeys); } export default { get, set, keys, del, clear, };