pinafore/routes/_database/databaseLifecycle.js

131 lines
3.7 KiB
JavaScript
Raw Normal View History

2018-01-23 18:03:31 +01:00
import {
META_STORE,
STATUS_TIMELINES_STORE,
2018-01-23 18:21:21 +01:00
STATUSES_STORE,
2018-01-28 21:51:48 +01:00
ACCOUNTS_STORE,
RELATIONSHIPS_STORE,
NOTIFICATIONS_STORE,
2018-02-11 19:35:25 +01:00
NOTIFICATION_TIMELINES_STORE,
2018-02-14 04:34:37 +01:00
PINNED_STATUSES_STORE,
2018-03-09 08:18:18 +01:00
TIMESTAMP,
REBLOG_ID,
2018-03-11 01:21:10 +01:00
THREADS_STORE,
2018-03-25 03:04:54 +02:00
STATUS_ID,
USERNAME_LOWERCASE
2018-01-23 18:03:31 +01:00
} from './constants'
import { addKnownInstance, deleteKnownInstance } from './knownInstances'
2018-01-23 18:03:31 +01:00
2018-02-09 07:29:29 +01:00
const openReqs = {}
const databaseCache = {}
2018-03-25 03:04:54 +02:00
const DB_VERSION_INITIAL = 9
const DB_VERSION_SEARCH_ACCOUNTS = 10
const DB_VERSION_CURRENT = 10
2018-02-14 04:34:37 +01:00
if (process.browser) {
require('indexeddb-getall-shim') // needed for Edge
}
2018-01-23 18:03:31 +01:00
function createDatabase (instanceName) {
return new Promise((resolve, reject) => {
2018-03-25 03:04:54 +02:00
let req = indexedDB.open(instanceName, DB_VERSION_CURRENT)
2018-01-23 18:03:31 +01:00
openReqs[instanceName] = req
req.onerror = reject
req.onblocked = () => {
console.log('idb blocked')
}
2018-01-28 21:51:48 +01:00
req.onupgradeneeded = (e) => {
2018-02-09 07:29:29 +01:00
let db = req.result
2018-03-25 03:04:54 +02:00
let tx = e.currentTarget.transaction
function createObjectStore (name, init, indexes) {
let store = init
? db.createObjectStore(name, init)
: db.createObjectStore(name)
if (indexes) {
Object.keys(indexes).forEach(indexKey => {
store.createIndex(indexKey, indexes[indexKey])
})
}
2018-03-09 03:31:59 +01:00
}
2018-03-25 03:04:54 +02:00
if (e.oldVersion < DB_VERSION_INITIAL) {
createObjectStore(STATUSES_STORE, { keyPath: 'id' }, {
[TIMESTAMP]: TIMESTAMP,
[REBLOG_ID]: REBLOG_ID
})
createObjectStore(STATUS_TIMELINES_STORE, null, {
'statusId': ''
})
createObjectStore(NOTIFICATIONS_STORE, { keyPath: 'id' }, {
[TIMESTAMP]: TIMESTAMP,
[STATUS_ID]: STATUS_ID
})
createObjectStore(NOTIFICATION_TIMELINES_STORE, null, {
'notificationId': ''
})
createObjectStore(ACCOUNTS_STORE, { keyPath: 'id' }, {
[TIMESTAMP]: TIMESTAMP
})
createObjectStore(RELATIONSHIPS_STORE, { keyPath: 'id' }, {
[TIMESTAMP]: TIMESTAMP
})
createObjectStore(THREADS_STORE, null, {
'statusId': ''
})
createObjectStore(PINNED_STATUSES_STORE, null, {
'statusId': ''
})
createObjectStore(META_STORE)
2018-03-11 01:21:10 +01:00
}
2018-03-25 03:04:54 +02:00
if (e.oldVersion < DB_VERSION_SEARCH_ACCOUNTS) {
tx.objectStore(ACCOUNTS_STORE)
.createIndex(USERNAME_LOWERCASE, USERNAME_LOWERCASE)
}
2018-01-23 18:03:31 +01:00
}
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)
}
2018-01-23 18:03:31 +01:00
return databaseCache[instanceName]
}
2018-02-09 07:29:29 +01:00
export async function dbPromise (db, storeName, readOnlyOrReadWrite, cb) {
return new Promise((resolve, reject) => {
2018-01-23 18:03:31 +01:00
const tx = db.transaction(storeName, readOnlyOrReadWrite)
2018-02-09 07:29:29 +01:00
let store = typeof storeName === 'string'
? tx.objectStore(storeName)
: storeName.map(name => tx.objectStore(name))
2018-01-23 18:03:31 +01:00
let res
cb(store, (result) => {
res = result
})
tx.oncomplete = () => resolve(res)
2018-02-09 07:29:29 +01:00
tx.onerror = () => reject(tx.error)
2018-01-23 18:03:31 +01:00
})
}
2018-02-09 07:29:29 +01:00
export function deleteDatabase (instanceName) {
2018-01-23 18:03:31 +01:00
return new Promise((resolve, reject) => {
// close any open requests
2018-02-09 07:29:29 +01:00
let openReq = openReqs[instanceName]
2018-01-23 18:03:31 +01:00
if (openReq && openReq.result) {
openReq.result.close()
}
delete openReqs[instanceName]
delete databaseCache[instanceName]
let req = indexedDB.deleteDatabase(instanceName)
req.onsuccess = () => resolve()
2018-02-09 07:29:29 +01:00
req.onerror = () => reject(req.error)
}).then(() => deleteKnownInstance(instanceName))
2018-02-09 07:29:29 +01:00
}