UNPKG

@oceans/indexdb

Version:

oceans indexdb

350 lines (278 loc) 7.97 kB
import { merge } from './utils' export const Router = { collections: {}, register (prefix, name, indexs) { if (!this.collections[prefix]) { this.collections[prefix] = {} } this.collections[prefix][name] = { name, indexs } }, getCollections (prefix) { return this.collections[prefix] } } export class Connect { constructor (params) { const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB if (!indexedDB) { throw new Error('Your browser is not support indexDB.') } this.settings = Object.assign({ dbName: '', version: 1, createObjectStoreOption: { keyPath: 'id', autoIncrement: true }, collections: {} }, params || {}) if (!this.settings.dbName) { throw new Error('db name is required') } this.indexedDB = indexedDB this.collections = this.settings.collections this.db = null this.events = {} } open () { return new Promise((resolve, reject) => { const dbInstance = this.indexedDB.open(this.settings.dbName, this.settings.version || 1) dbInstance.onsuccess = (e) => { this.db = dbInstance.result Connect.db[this.settings.dbName] = { db: this.db, connectInstance: this } resolve(this.db) } dbInstance.onerror = (e) => { const msg = e.currentTarget.error.message reject(msg) } dbInstance.onupgradeneeded = (e) => { const db = e.target.result const collections = this.collections Object.keys(collections).forEach((key) => { const collection = collections[key] if (!db.objectStoreNames.contains(collection.name)) { const store = db.createObjectStore( collection.name, this.settings.createObjectStoreOption || {} ) if (collection.indexs) { collection.indexs.forEach((item) => { store.createIndex(item.name, item.keyPath, item.options || {}) }) } if (this.events.onupgradeneeded) { this.events.onupgradeneeded(db) } console.log('current version : ', this.settings.version) } }) } }) } bind (name, cb) { this.events[name] = cb } } Connect.db = {} export class Base { constructor (struct, params) { this.settings = merge({ db: null, collectionName: '', connectInstance: null }, params || {}, true) if (!this.settings.db) { throw new Error('db is required') } if (!this.settings.collectionName) { throw new Error('collection name is required') } if (!this.settings.connectInstance) { throw new Error('connectInstance is required') } this.struct = struct this.db = this.settings.db this.events = {} this.connectInstance = this.settings.connectInstance } bind (name, cb) { this.events[name] = cb } getTransactionAndStore (isWrite) { const collectionName = this.settings.collectionName const transaction = this.db.transaction([collectionName], isWrite ? 'readwrite' : 'readonly') const store = transaction.objectStore(collectionName) return { transaction, store } } insert (docs) { return new Promise((resolve, reject) => { const db = this.db if (!db) { reject(new Error('db is not ready')) return false } if (!docs || docs.length === 0) { resolve(docs) return false } let data = [] if (docs.constructor === Array) { data = docs } else { data.push(docs) } const rs = this.getTransactionAndStore(true) rs.transaction.oncomplete = (e) => { resolve() } rs.transaction.onerror = (e) => { reject(e.target.error.message) } const struct = this.struct data.forEach((item) => { const doc = merge(struct, item, true) rs.store.add(doc) }) }) } get (key, value) { return new Promise((resolve, reject) => { if (!key) { reject(new Error('key is required')) return false } const rs = this.getTransactionAndStore() const request = rs.store.index(key).get(value) request.onsuccess = (e) => { resolve(e.target.result) } request.onerror = (e) => { reject(new Error(e.target.error.message)) } }) } list (key, value, option) { return new Promise((resolve, reject) => { const settings = Object.assign({ page: 0, pageSize: 20, sort: 'next' // next 正, prev 倒 }, option || {}) const docs = [] const IDBKeyRange = window.IDBKeyRange let isAdvancing = true let limit = settings.page === 0 ? -100 : settings.pageSize let val = null const rs = this.getTransactionAndStore() let request = null if (key) { if (value instanceof IDBKeyRange) { val = value } else { val = IDBKeyRange.only(value) } request = rs.store.index(key).openCursor(val, settings.sort) } else { request = rs.store.openCursor(null, settings.sort) } request.onsuccess = (e) => { const cursor = e.target.result if (cursor) { const count = settings.page * settings.pageSize if (isAdvancing && count > 0) { cursor.advance(count) isAdvancing = false } else { docs.push(cursor.value) if (limit !== 0) { limit-- cursor.continue() } } } else { let rs = docs if (settings.page > 0) { rs = Object.assign({ docs }, settings) } resolve(rs) } } request.onerror = (e) => { reject(e.target.error.message) } }) } delete (key, value) { return new Promise((resolve, reject) => { if (!key) { reject(new Error('key is required')) return false } if (typeof value === 'undefined') { reject(new Error('value is require')) return false } const rs = this.getTransactionAndStore(true) const findOneRequest = rs.store.index(key).get(value) findOneRequest.onsuccess = (e) => { const info = e.target.result if (!info) { resolve('ok') return false } const request = rs.store.delete(info[this.connectInstance.settings.keyPath]) request.onsuccess = () => { resolve() } request.onerror = (e) => { reject(e.target.error.message) } } findOneRequest.onerror = (e) => { reject(e.target.error.message) } }) } update (key, value, updateInfo) { return new Promise((resolve, reject) => { if (!key) { reject(new Error('key is required')) return false } if (!value) { reject(new Error('value is required')) return false } if (!updateInfo) { reject(new Error('updateInfo is required')) return false } const rs = this.getTransactionAndStore(true) const request = rs.store.index(key).get(value) request.onsuccess = (e) => { const doc = e.target.result Object.keys(updateInfo).forEach((k) => { if (typeof doc[k] !== 'undefined') { doc[k] = updateInfo[k] } }) const req = rs.store.put(doc) req.onsuccess = (e) => { resolve('ok') } req.onerror = (e) => { reject(e.target.error.message) } } request.onerror = (e) => { reject(e.target.error.message) } }) } }