soiz1's picture
Upload 225 files
7aec436 verified
// 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;