UNPKG

onionskin

Version:

Multilayer Cache Manager for JavaScript

189 lines (171 loc) 5.32 kB
var Promise = require('bluebird'); var Utils = require('./utils'); module.exports = IndexedDB; function IndexedDB(namespace) { this.namespace = namespace || 'onionskin'; this.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; this.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction; this.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange; var that = this; this.db = function () { return new Promise(function (resolve, reject) { var request = that.indexedDB.open(that.namespace); request.onerror = function (event) { reject(event.target.error); }; request.onsuccess = function () { resolve(request.result); }; request.onupgradeneeded = function (event) { var db = event.target.result; var objectStore = db.createObjectStore('cache', { keyPath: 'key' }); objectStore.createIndex('key', 'key', { unique: true }); }; }).bind(this); }; } IndexedDB.available = (function () { return typeof window !== 'undefined' && ( 'indexedDB' in window || 'mozIndexedDB' in window || 'webkitIndexedDB' in window || 'msIndexedDB' in window ); })(); IndexedDB.prototype.put = function (key, value, expiration) { value = Utils.assemble(value, expiration, key, false); return this._key(key).then(function (k) { value.key = k; return this._put(value); }); }; IndexedDB.prototype._put = function (value) { return this.db().then(function (db) { return new Promise(function (resolve, reject) { var transaction = db.transaction('cache', 'readwrite'); var store = transaction.objectStore('cache'); transaction.onerror = function (err) { reject(err.target.error); }; transaction.oncomplete = resolve; store.put(value); }); }); }; IndexedDB.prototype.get = function (key) { return this._key(key).then(this._get).then(function (value) { if (value) { delete value.key; } return value; }); }; IndexedDB.prototype._get = function (key) { return this.db().then(function (db) { var store = db.transaction('cache').objectStore('cache'); var request = store.get(key); return new Promise(function (resolve, reject) { request.onerror = function (err) { reject(err.target.error); db.close(); }; request.onsuccess = function () { resolve(request.result || null); db.close(); }; }); }); }; IndexedDB.prototype.delete = function (key) { return this._key(key).then(function (k) { return this.db().then(function (db) { var transaction = db.transaction('cache', 'readwrite'); var store = transaction.objectStore('cache'); var index = store.index('key'); var keyRange = this.IDBKeyRange.lowerBound(k); return new Promise(function (resolve, reject) { var cursor = index.openKeyCursor(keyRange); var queue = []; cursor.onerror = function (event) { reject(event.target.error); }; cursor.onsuccess = function (event) { var cursor = event.target.result; if (cursor) { if (cursor.key.substr(0, k.length) === k) { queue.push(new Promise(function (resolve, reject) { var request = store.delete(cursor.key); })); } cursor.continue(); } }; transaction.onerror = function (event) { reject(event.target.error); db.close(); }; transaction.oncomplete = function () { resolve.apply(this, arguments); db.close(); }; }); }); }); }; IndexedDB.prototype._delete = function (key) { return this.db().then(function (db) { return new Promise(function (resolve, reject) { var transaction = db.transaction('cache', 'readwrite'); var store = transaction.objectStore('cache'); transaction.oncomplete = function () { resolve(); db.close(); }; transaction.onerror = function (err) { reject(err.target.error); db.close(); }; store.delete(key); }); }); }; IndexedDB.prototype.isLocked = function (key) { return this._key(key+'_lock').then(this._get).then(function (value) { return Boolean(value); }); }; IndexedDB.prototype.lock = function (key) { return this._key(key+'_lock').then(function (k) { return this._put({ key: k, value: 1 }); }); }; IndexedDB.prototype.unlock = function (key) { return this._key(key+'_lock').then(this._delete); }; IndexedDB.prototype.flush = function () { return this.db().then(function (db) { return new Promise(function (resolve, reject) { var store = db.transaction('cache', 'readwrite').objectStore('cache'); var request = store.clear(); request.onerror = function (err) { reject(err.target.error); db.close(); }; request.onsuccess = function () { resolve(request.result); db.close(); }; }); }); }; IndexedDB.prototype._key = function (key) { key = Utils.key(this.namespace, key); return Promise.cast(key).bind(this); };