90 lines
2.7 KiB
JavaScript
90 lines
2.7 KiB
JavaScript
import { DB_VERSION_CURRENT } from './constants'
|
|
import { addKnownInstance, deleteKnownInstance } from './knownInstances'
|
|
import { migrations } from './migrations'
|
|
import { clearAllCaches } from './cache'
|
|
|
|
const openReqs = {}
|
|
const databaseCache = {}
|
|
|
|
function createDatabase (instanceName) {
|
|
return new Promise((resolve, reject) => {
|
|
let req = indexedDB.open(instanceName, DB_VERSION_CURRENT.version)
|
|
openReqs[instanceName] = req
|
|
req.onerror = reject
|
|
req.onblocked = () => {
|
|
console.error('idb blocked')
|
|
}
|
|
req.onupgradeneeded = (e) => {
|
|
let db = req.result
|
|
let tx = e.currentTarget.transaction
|
|
|
|
let migrationsToDo = migrations.filter(({ version }) => e.oldVersion < version)
|
|
|
|
function doNextMigration () {
|
|
if (!migrationsToDo.length) {
|
|
return
|
|
}
|
|
let { migration } = migrationsToDo.shift()
|
|
migration(db, tx, doNextMigration)
|
|
}
|
|
doNextMigration()
|
|
}
|
|
req.onsuccess = () => resolve(req.result)
|
|
})
|
|
}
|
|
|
|
export async function getDatabase (instanceName) {
|
|
if (!instanceName) {
|
|
throw new Error('instanceName is undefined in getDatabase()')
|
|
}
|
|
if (!databaseCache[instanceName]) {
|
|
databaseCache[instanceName] = await createDatabase(instanceName)
|
|
await addKnownInstance(instanceName)
|
|
}
|
|
return databaseCache[instanceName]
|
|
}
|
|
|
|
export async function dbPromise (db, storeName, readOnlyOrReadWrite, cb) {
|
|
return new Promise((resolve, reject) => {
|
|
const tx = db.transaction(storeName, readOnlyOrReadWrite)
|
|
let store = typeof storeName === 'string'
|
|
? tx.objectStore(storeName)
|
|
: storeName.map(name => tx.objectStore(name))
|
|
let res
|
|
cb(store, (result) => {
|
|
res = result
|
|
})
|
|
|
|
tx.oncomplete = () => resolve(res)
|
|
tx.onerror = () => reject(tx.error)
|
|
})
|
|
}
|
|
|
|
export function deleteDatabase (instanceName) {
|
|
return new Promise((resolve, reject) => {
|
|
// close any open requests
|
|
let openReq = openReqs[instanceName]
|
|
if (openReq && openReq.result) {
|
|
openReq.result.close()
|
|
}
|
|
delete openReqs[instanceName]
|
|
delete databaseCache[instanceName]
|
|
let req = indexedDB.deleteDatabase(instanceName)
|
|
req.onsuccess = () => resolve()
|
|
req.onerror = () => reject(req.error)
|
|
req.onblocked = () => console.error(`database ${instanceName} blocked`)
|
|
}).then(() => deleteKnownInstance(instanceName))
|
|
.then(() => clearAllCaches(instanceName))
|
|
}
|
|
|
|
// this should probably only be used in unit tests
|
|
export function closeDatabase (instanceName) {
|
|
// close any open requests
|
|
let openReq = openReqs[instanceName]
|
|
if (openReq && openReq.result) {
|
|
openReq.result.close()
|
|
}
|
|
delete openReqs[instanceName]
|
|
delete databaseCache[instanceName]
|
|
clearAllCaches(instanceName)
|
|
}
|