localforage-indexes
Version:
plugin for localforage to work with indexes in indexedDb
301 lines (254 loc) • 11.8 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('localforage')) :
typeof define === 'function' && define.amd ? define(['exports', 'localforage'], factory) :
(factory((global.localforagePluginBoilerplate = global.localforagePluginBoilerplate || {}),global.localforage));
}(this, function (exports,localforage) { 'use strict';
localforage = 'default' in localforage ? localforage['default'] : localforage;
/*
* Resolves a store created in versionchange transaction
* @param {localforage} localforageInstance
* @param {callback function} action - action to perform on store
* HACK: callback is used instead of Promise because Firefox & Safari destroy
* transactions that are passed through promise
* @param {callback function} finished - called after action is preformed
* @return {Promise} {
* store - store's indexes can be modified
* request - version update connection
* dbInfo - container with indexedDb config
* newVersion - current version of indexedDb
* oldVersion - previous version of indexedDb
* }
*/
function _upgradeStore(localforageInstance, action, finished) {
return localforageInstance.ready().then(function () {
var dbInfo = localforageInstance._dbInfo;
if (!(dbInfo.db instanceof IDBDatabase)) {
return finished(new Error('Driver ' + localforageInstance.driver() + ' does not support indexing'));
}
dbInfo.db.close();
var request = getIDB().open(dbInfo.name, dbInfo.db.version + 1);
request.onupgradeneeded = function (_ref) {
var newVersion = _ref.newVersion,
oldVersion = _ref.oldVersion;
dbInfo.db = request.result;
var store = request.transaction.objectStore(dbInfo.storeName);
action({ store: store, dbInfo: dbInfo, newVersion: newVersion, oldVersion: oldVersion });
};
request.onerror = function (e) {
e.preventDefault();
finished(request.error);
};
request.onsuccess = function () {
return finished();
};
});
}
function _getIndex(localforageInstance, indexName) {
var dbInfo = localforageInstance._dbInfo;
var storeName = dbInfo.storeName;
return dbInfo.db.transaction(storeName, 'readonly').objectStore(storeName).index(indexName);
}
function _executePromiseOrCallback(promise, callback) {
if (typeof callback === 'function') {
var resolve = function resolve(result) {
return callback(null, result);
};
var reject = function reject(error) {
return callback(error);
};
return promise(resolve, reject);
}
return new Promise(promise);
}
function _resolveParams(options, callback) {
if (typeof options === 'function') {
callback = options;
options = undefined;
}
return { options: options, callback: callback };
}
function getIDB() {
/* global indexedDB,webkitIndexedDB,mozIndexedDB,OIndexedDB,msIndexedDB */
try {
if (typeof indexedDB !== 'undefined') {
return indexedDB;
}
if (typeof webkitIndexedDB !== 'undefined') {
return webkitIndexedDB;
}
if (typeof mozIndexedDB !== 'undefined') {
return mozIndexedDB;
}
if (typeof OIndexedDB !== 'undefined') {
return OIndexedDB;
}
if (typeof msIndexedDB !== 'undefined') {
return msIndexedDB;
}
throw new Error("indexedDb not supported by browser");
} catch (e) {
throw e;
}
}
function handleMethodCall(localforageInstance, methodName, args) {
return localforageInstance.ready().then(function () {
var promise = localforageInstance._baseMethods[methodName].apply(localforageInstance, args);
return promise;
});
}
// wraps the localForage methods of the WrappedLibraryMethods array and
// allows you to execute code before & after their invocation
function wireUpMethods(localforageInstance) {
var WrappedLibraryMethods = ['clear', 'getItem', 'iterate', 'key', 'keys', 'length', 'removeItem', 'setItem'];
function wireUpMethod(localforageInstance, methodName) {
localforageInstance._baseMethods = localforageInstance._baseMethods || {};
localforageInstance._baseMethods[methodName] = localforageInstance[methodName];
localforageInstance[methodName] = function () {
return handleMethodCall(this, methodName, arguments);
};
}
for (var i = 0, len = WrappedLibraryMethods.length; i < len; i++) {
var methodName = WrappedLibraryMethods[i];
wireUpMethod(localforageInstance, methodName);
}
}
// place your plugin initialization logic here
// useful in case that you need to preserve a state
function setup(localforageInstance) {
if (!localforageInstance._pluginPrivateVariables) {
localforageInstance._pluginPrivateVariables = {
listOfImportantThings: [],
callCount: 0
};
// in case you need to observe the invocation of some methods
wireUpMethods(localforageInstance);
}
}
/*
* Creates index
* @param {String} indexName
* @param {String} keyPath, indexDb key path, keys separated with dot
* @param {Object} options, indexDb index creation options
* @param {Function<err | index>} callback
* @return {Promise<index>} resolves with new index, rejects if index is present
*/
function createIndex(indexName, keyPath, options, callback) {
var _resolveParams2 = _resolveParams(options, callback);
options = _resolveParams2.options;
callback = _resolveParams2.callback;
var localforageInstance = this;
setup(localforageInstance);
return _executePromiseOrCallback(function (resolve, reject) {
_upgradeStore(localforageInstance, function (_ref) {
var store = _ref.store,
dbInfo = _ref.dbInfo,
newVersion = _ref.newVersion,
oldVersion = _ref.oldVersion;
if (store.indexNames.contains(indexName)) {
return reject(new Error('The database "' + dbInfo.name + '" has been upgraded from version ' + oldVersion + ' to version ' + newVersion + ', but the index "' + indexName + '" in the storage "' + dbInfo.storeName + '" already exists.'));
}
store.createIndex(indexName, keyPath, options || {});
}, function (err) {
if (err) return reject(err);
resolve(_getIndex(localforageInstance, indexName));
}).catch(function (err) {
reject(err);
});
}, callback);
}
/*
* Gets index
* @param {String} indexName
* @param {Function<err | index>} callback
* @return {Promise<index>} resolves with an index, rejects if index is not found
*/
function getIndex(indexName, callback) {
var localforageInstance = this;
setup(localforageInstance);
return _executePromiseOrCallback(function (resolve, reject) {
localforageInstance.ready().then(function () {
return resolve(_getIndex(localforageInstance, indexName));
}).catch(reject);
}, callback);
}
/*
* Deletes then recreates index
* Use to change index keyPath or options
* @param {String} indexName
* @param {String} keyPath, indexDb key path, keys separated with dot
* @param {Object} options, indexDb index creation options
* @param {Function<err | index>} callback
* @return {Promise<index>} resolves with updated index, rejects if index is present
*/
function updateIndex(indexName, keyPath, options, callback) {
var _resolveParams3 = _resolveParams(options, callback);
options = _resolveParams3.options;
callback = _resolveParams3.callback;
var localforageInstance = this;
setup(localforageInstance);
return _executePromiseOrCallback(function (resolve, reject) {
_upgradeStore(localforageInstance, function (_ref2) {
var store = _ref2.store,
dbInfo = _ref2.dbInfo,
newVersion = _ref2.newVersion,
oldVersion = _ref2.oldVersion;
if (!store.indexNames.contains(indexName)) {
return reject(new Error('The database "' + dbInfo.name + '" has been upgraded from version ' + oldVersion + ' to version ' + newVersion + ', but the index "' + indexName + '" in the storage "' + dbInfo.storeName + '" does not exists.'));
}
store.deleteIndex(indexName);
store.createIndex(indexName, keyPath, options);
}, function (err) {
if (err) return reject(err);
resolve(_getIndex(localforageInstance, indexName));
}).catch(function (err) {
reject(err);
});
}, callback);
}
/*
* Deletes index
* @param {String} indexName
* @param {Function<err>} callback
* @return {Promise} resolves when index is delted, rejects if index isn't present
*/
function deleteIndex(indexName, callback) {
var localforageInstance = this;
setup(localforageInstance);
return _executePromiseOrCallback(function (resolve, reject) {
_upgradeStore(localforageInstance, function (_ref3) {
var store = _ref3.store,
dbInfo = _ref3.dbInfo,
newVersion = _ref3.newVersion,
oldVersion = _ref3.oldVersion;
if (!store.indexNames.contains(indexName)) {
return reject(new Error('The database "' + dbInfo.name + '" has been upgraded from version ' + oldVersion + ' to version ' + newVersion + ', but the index "' + indexName + '" in the storage "' + dbInfo.storeName + '" does not exists.'));
}
store.deleteIndex(indexName);
}, function (err) {
if (err) return reject(err);
resolve();
}).catch(function (err) {
reject(err);
});
}, callback);
}
// add your plugin method to every localForage instance
function extendPrototype(localforage) {
var localforagePrototype = Object.getPrototypeOf(localforage);
if (localforagePrototype) {
localforagePrototype.createIndex = createIndex;
localforagePrototype.getIndex = getIndex;
localforagePrototype.updateIndex = updateIndex;
localforagePrototype.deleteIndex = deleteIndex;
}
return localforage;
}
var extendPrototypeResult = extendPrototype(localforage);
exports.createIndex = createIndex;
exports.getIndex = getIndex;
exports.updateIndex = updateIndex;
exports.deleteIndex = deleteIndex;
exports.extendPrototype = extendPrototype;
exports.extendPrototypeResult = extendPrototypeResult;
Object.defineProperty(exports, '__esModule', { value: true });
}));