Spaces:
Sleeping
Sleeping
File size: 3,289 Bytes
7aec436 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
// https://github.com/jakearchibald/safari-14-idb-fix/blob/582bbdc7230891113bfb5743391550cbf29d21f2/src/index.ts
const idbReady = () => {
const isSafari =
!navigator.userAgentData &&
/Safari\//.test(navigator.userAgent) &&
!/Chrom(e|ium)\//.test(navigator.userAgent);
// No point putting other browsers or older versions of Safari through this mess.
if (!isSafari || !indexedDB.databases) return Promise.resolve();
let intervalId;
return new Promise((resolve) => {
const tryIdb = () => indexedDB.databases().finally(resolve);
intervalId = setInterval(tryIdb, 100);
tryIdb();
}).finally(() => clearInterval(intervalId));
};
const allDatabases = [];
class Database {
constructor (name, version, storeName) {
this.name = name;
this.version = version;
this.storeName = storeName;
this.db = null;
this.dbPromise = null;
allDatabases.push(this);
}
open () {
if (this.db) {
return this.db;
}
if (this.dbPromise) {
return this.dbPromise;
}
if (typeof indexedDB === 'undefined') {
throw new Error('indexedDB is not supported');
}
this.dbPromise = idbReady()
.then(() => new Promise((resolve, reject) => {
const request = indexedDB.open(this.name, this.version);
request.onupgradeneeded = (e) => {
const db = e.target.result;
db.createObjectStore(this.storeName, {
keyPath: 'id'
});
};
request.onsuccess = (e) => {
const db = e.target.result;
resolve(db);
};
request.onerror = (e) => {
reject(new Error(`IDB Error ${e.target.error}`));
};
}))
.then((db) => {
this.dbPromise = null;
this.db = db;
return db;
})
.catch((err) => {
this.dbPromise = null;
throw err;
});
return this.dbPromise;
}
close () {
if (this.db) {
this.db.close();
this.db = null;
}
if (this.dbPromise) {
this.dbPromise.then((db) => {
db.close();
});
this.dbPromise = null;
}
}
async createTransaction (readwrite) {
const db = await this.open();
const transaction = db.transaction(this.storeName, readwrite);
const store = transaction.objectStore(this.storeName);
return {
db,
transaction,
store
};
}
async deleteEverything () {
const {transaction, store} = await this.createTransaction('readwrite');
return new Promise((resolve, reject) => {
Database.setTransactionErrorHandler(transaction, reject);
const request = store.clear();
request.onsuccess = () => {
resolve();
};
});
}
}
Database.setTransactionErrorHandler = (transaction, reject) => {
transaction.onerror = () => {
reject(new Error(`Transaction error: ${transaction.error}`))
};
};
const closeAllDatabases = () => {
for (const database of allDatabases) {
database.close();
}
};
// Closing databases makes us more likely to be put in the browser's back/forward cache
window.addEventListener('pagehide', closeAllDatabases);
export default Database;
|