You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
3.2 KiB
95 lines
3.2 KiB
2 years ago
|
'use strict';
|
||
|
|
||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||
|
|
||
|
var wrapIdbValue = require('./wrap-idb-value.js');
|
||
|
|
||
|
/**
|
||
|
* Open a database.
|
||
|
*
|
||
|
* @param name Name of the database.
|
||
|
* @param version Schema version.
|
||
|
* @param callbacks Additional callbacks.
|
||
|
*/
|
||
|
function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
|
||
|
const request = indexedDB.open(name, version);
|
||
|
const openPromise = wrapIdbValue.wrap(request);
|
||
|
if (upgrade) {
|
||
|
request.addEventListener('upgradeneeded', (event) => {
|
||
|
upgrade(wrapIdbValue.wrap(request.result), event.oldVersion, event.newVersion, wrapIdbValue.wrap(request.transaction));
|
||
|
});
|
||
|
}
|
||
|
if (blocked)
|
||
|
request.addEventListener('blocked', () => blocked());
|
||
|
openPromise
|
||
|
.then((db) => {
|
||
|
if (terminated)
|
||
|
db.addEventListener('close', () => terminated());
|
||
|
if (blocking)
|
||
|
db.addEventListener('versionchange', () => blocking());
|
||
|
})
|
||
|
.catch(() => { });
|
||
|
return openPromise;
|
||
|
}
|
||
|
/**
|
||
|
* Delete a database.
|
||
|
*
|
||
|
* @param name Name of the database.
|
||
|
*/
|
||
|
function deleteDB(name, { blocked } = {}) {
|
||
|
const request = indexedDB.deleteDatabase(name);
|
||
|
if (blocked)
|
||
|
request.addEventListener('blocked', () => blocked());
|
||
|
return wrapIdbValue.wrap(request).then(() => undefined);
|
||
|
}
|
||
|
|
||
|
const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
|
||
|
const writeMethods = ['put', 'add', 'delete', 'clear'];
|
||
|
const cachedMethods = new Map();
|
||
|
function getMethod(target, prop) {
|
||
|
if (!(target instanceof IDBDatabase &&
|
||
|
!(prop in target) &&
|
||
|
typeof prop === 'string')) {
|
||
|
return;
|
||
|
}
|
||
|
if (cachedMethods.get(prop))
|
||
|
return cachedMethods.get(prop);
|
||
|
const targetFuncName = prop.replace(/FromIndex$/, '');
|
||
|
const useIndex = prop !== targetFuncName;
|
||
|
const isWrite = writeMethods.includes(targetFuncName);
|
||
|
if (
|
||
|
// Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
|
||
|
!(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
|
||
|
!(isWrite || readMethods.includes(targetFuncName))) {
|
||
|
return;
|
||
|
}
|
||
|
const method = async function (storeName, ...args) {
|
||
|
// isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
|
||
|
const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
|
||
|
let target = tx.store;
|
||
|
if (useIndex)
|
||
|
target = target.index(args.shift());
|
||
|
// Must reject if op rejects.
|
||
|
// If it's a write operation, must reject if tx.done rejects.
|
||
|
// Must reject with op rejection first.
|
||
|
// Must resolve with op value.
|
||
|
// Must handle both promises (no unhandled rejections)
|
||
|
return (await Promise.all([
|
||
|
target[targetFuncName](...args),
|
||
|
isWrite && tx.done,
|
||
|
]))[0];
|
||
|
};
|
||
|
cachedMethods.set(prop, method);
|
||
|
return method;
|
||
|
}
|
||
|
wrapIdbValue.replaceTraps((oldTraps) => ({
|
||
|
...oldTraps,
|
||
|
get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
|
||
|
has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
|
||
|
}));
|
||
|
|
||
|
exports.unwrap = wrapIdbValue.unwrap;
|
||
|
exports.wrap = wrapIdbValue.wrap;
|
||
|
exports.deleteDB = deleteDB;
|
||
|
exports.openDB = openDB;
|