UNPKG

lib0

Version:

> Monorepo of isomorphic utility functions

1 lines 15.3 kB
{"version":3,"file":"indexeddbV2.cjs","sources":["../indexeddbV2.js"],"sourcesContent":["/* eslint-env browser */\n\n/**\n * Helpers to work with IndexedDB.\n * This is an experimental implementation using Pledge instead of Promise.\n *\n * @experimental\n *\n * @module indexeddbv2\n */\n\nimport * as pledge from './pledge.js'\n\n/* c8 ignore start */\n\n/**\n * IDB Request to Pledge transformer\n *\n * @param {pledge.PledgeInstance<any>} p\n * @param {IDBRequest} request\n */\nexport const bindPledge = (p, request) => {\n // @ts-ignore\n request.onerror = event => p.cancel(event.target.error)\n // @ts-ignore\n request.onsuccess = event => p.resolve(event.target.result)\n}\n\n/**\n * @param {string} name\n * @param {function(IDBDatabase):any} initDB Called when the database is first created\n * @return {pledge.PledgeInstance<IDBDatabase>}\n */\nexport const openDB = (name, initDB) => {\n /**\n * @type {pledge.PledgeInstance<IDBDatabase>}\n */\n const p = pledge.create()\n const request = indexedDB.open(name)\n /**\n * @param {any} event\n */\n request.onupgradeneeded = event => initDB(event.target.result)\n /**\n * @param {any} event\n */\n request.onerror = event => p.cancel(event.target.error)\n /**\n * @param {any} event\n */\n request.onsuccess = event => {\n /**\n * @type {IDBDatabase}\n */\n const db = event.target.result\n db.onversionchange = () => { db.close() }\n p.resolve(db)\n }\n return p\n}\n\n/**\n * @param {pledge.Pledge<string>} name\n * @return {pledge.PledgeInstance<void>}\n */\nexport const deleteDB = name => pledge.createWithDependencies((p, name) => bindPledge(p, indexedDB.deleteDatabase(name)), name)\n\n/**\n * @param {IDBDatabase} db\n * @param {Array<Array<string>|Array<string|IDBObjectStoreParameters|undefined>>} definitions\n */\nexport const createStores = (db, definitions) => definitions.forEach(d =>\n // @ts-ignore\n db.createObjectStore.apply(db, d)\n)\n\n/**\n * @param {pledge.Pledge<IDBDatabase>} db\n * @param {pledge.Pledge<Array<string>>} stores\n * @param {\"readwrite\"|\"readonly\"} [access]\n * @return {pledge.Pledge<Array<IDBObjectStore>>}\n */\nexport const transact = (db, stores, access = 'readwrite') => pledge.createWithDependencies((p, db, stores) => {\n const transaction = db.transaction(stores, access)\n p.resolve(stores.map(store => getStore(transaction, store)))\n}, db, stores)\n\n/**\n * @param {IDBObjectStore} store\n * @param {pledge.Pledge<IDBKeyRange|undefined>} [range]\n * @return {pledge.PledgeInstance<number>}\n */\nexport const count = (store, range) => pledge.createWithDependencies((p, store, range) => bindPledge(p, store.count(range)), store, range)\n\n/**\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {pledge.Pledge<String | number | ArrayBuffer | Date | Array<any>>} key\n * @return {pledge.PledgeInstance<String | number | ArrayBuffer | Date | Array<any>>}\n */\nexport const get = (store, key) => pledge.createWithDependencies((p, store, key) => bindPledge(p, store.get(key)), store, key)\n\n/**\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {String | number | ArrayBuffer | Date | IDBKeyRange | Array<any> } key\n */\nexport const del = (store, key) => pledge.createWithDependencies((p, store, key) => bindPledge(p, store.delete(key)), store, key)\n\n/**\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {String | number | ArrayBuffer | Date | boolean} item\n * @param {String | number | ArrayBuffer | Date | Array<any>} [key]\n */\nexport const put = (store, item, key) => pledge.createWithDependencies((p, store, item, key) => bindPledge(p, store.put(item, key)), store, item, key)\n\n/**\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {String | number | ArrayBuffer | Date | boolean} item\n * @param {String | number | ArrayBuffer | Date | Array<any>} key\n * @return {pledge.PledgeInstance<any>}\n */\nexport const add = (store, item, key) => pledge.createWithDependencies((p, store, item, key) => bindPledge(p, store.add(item, key)), store, item, key)\n\n/**\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {String | number | ArrayBuffer | Date} item\n * @return {pledge.PledgeInstance<number>} Returns the generated key\n */\nexport const addAutoKey = (store, item) => pledge.createWithDependencies((p, store, item) => bindPledge(p, store.add(item)), store, item)\n\n/**\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {IDBKeyRange} [range]\n * @param {number} [limit]\n * @return {pledge.PledgeInstance<Array<any>>}\n */\nexport const getAll = (store, range, limit) => pledge.createWithDependencies((p, store, range, limit) => bindPledge(p, store.getAll(range, limit)), store, range, limit)\n\n/**\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {IDBKeyRange} [range]\n * @param {number} [limit]\n * @return {pledge.PledgeInstance<Array<any>>}\n */\nexport const getAllKeys = (store, range, limit) => pledge.createWithDependencies((p, store, range, limit) => bindPledge(p, store.getAllKeys(range, limit)), store, range, limit)\n\n/**\n * @param {IDBObjectStore} store\n * @param {IDBKeyRange|null} query\n * @param {'next'|'prev'|'nextunique'|'prevunique'} direction\n * @return {pledge.PledgeInstance<any>}\n */\nexport const queryFirst = (store, query, direction) => {\n /**\n * @type {any}\n */\n let first = null\n return iterateKeys(store, query, key => {\n first = key\n return false\n }, direction).map(() => first)\n}\n\n/**\n * @param {IDBObjectStore} store\n * @param {IDBKeyRange?} [range]\n * @return {pledge.PledgeInstance<any>}\n */\nexport const getLastKey = (store, range = null) => queryFirst(store, range, 'prev')\n\n/**\n * @param {IDBObjectStore} store\n * @param {IDBKeyRange?} [range]\n * @return {pledge.PledgeInstance<any>}\n */\nexport const getFirstKey = (store, range = null) => queryFirst(store, range, 'next')\n\n/**\n * @typedef KeyValuePair\n * @type {Object}\n * @property {any} k key\n * @property {any} v Value\n */\n\n/**\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {pledge.Pledge<IDBKeyRange|undefined>} [range]\n * @param {pledge.Pledge<number|undefined>} [limit]\n * @return {pledge.PledgeInstance<Array<KeyValuePair>>}\n */\nexport const getAllKeysValues = (store, range, limit) => pledge.createWithDependencies((p, store, range, limit) => {\n pledge.all([getAllKeys(store, range, limit), getAll(store, range, limit)]).map(([ks, vs]) => ks.map((k, i) => ({ k, v: vs[i] }))).whenResolved(p.resolve.bind(p))\n}, store, range, limit)\n\n/**\n * @param {pledge.PledgeInstance<void>} p\n * @param {any} request\n * @param {function(IDBCursorWithValue):void|boolean|Promise<void|boolean>} f\n */\nconst iterateOnRequest = (p, request, f) => {\n request.onerror = p.cancel.bind(p)\n /**\n * @param {any} event\n */\n request.onsuccess = async event => {\n const cursor = event.target.result\n if (cursor === null || (await f(cursor)) === false) {\n p.resolve(undefined)\n return\n }\n cursor.continue()\n }\n}\n\n/**\n * Iterate on keys and values\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {pledge.Pledge<IDBKeyRange|null>} keyrange\n * @param {function(any,any):void|boolean|Promise<void|boolean>} f Callback that receives (value, key)\n * @param {'next'|'prev'|'nextunique'|'prevunique'} direction\n */\nexport const iterate = (store, keyrange, f, direction = 'next') => pledge.createWithDependencies((p, store, keyrange) => {\n iterateOnRequest(p, store.openCursor(keyrange, direction), cursor => f(cursor.value, cursor.key))\n}, store, keyrange)\n\n/**\n * Iterate on the keys (no values)\n *\n * @param {pledge.Pledge<IDBObjectStore>} store\n * @param {pledge.Pledge<IDBKeyRange|null>} keyrange\n * @param {function(any):void|boolean|Promise<void|boolean>} f callback that receives the key\n * @param {'next'|'prev'|'nextunique'|'prevunique'} direction\n */\nexport const iterateKeys = (store, keyrange, f, direction = 'next') => pledge.createWithDependencies((p, store, keyrange) => {\n iterateOnRequest(p, store.openKeyCursor(keyrange, direction), cursor => f(cursor.key))\n}, store, keyrange)\n\n/**\n * Open store from transaction\n * @param {IDBTransaction} t\n * @param {String} store\n * @returns {IDBObjectStore}\n */\nexport const getStore = (t, store) => t.objectStore(store)\n\n/**\n * @param {any} lower\n * @param {any} upper\n * @param {boolean} lowerOpen\n * @param {boolean} upperOpen\n */\nexport const createIDBKeyRangeBound = (lower, upper, lowerOpen, upperOpen) => IDBKeyRange.bound(lower, upper, lowerOpen, upperOpen)\n\n/**\n * @param {any} upper\n * @param {boolean} upperOpen\n */\nexport const createIDBKeyRangeUpperBound = (upper, upperOpen) => IDBKeyRange.upperBound(upper, upperOpen)\n\n/**\n * @param {any} lower\n * @param {boolean} lowerOpen\n */\nexport const createIDBKeyRangeLowerBound = (lower, lowerOpen) => IDBKeyRange.lowerBound(lower, lowerOpen)\n\n/* c8 ignore stop */\n"],"names":["pledge.create","pledge.createWithDependencies","pledge.all"],"mappings":"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"}