123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- (function (global, factory) {
- if (typeof define === "function" && define.amd) {
- define('localStorageWrapper', ['module', 'exports', '../utils/isLocalStorageValid', '../utils/serializer', '../utils/promise', '../utils/executeCallback', '../utils/normalizeKey', '../utils/getCallback'], factory);
- } else if (typeof exports !== "undefined") {
- factory(module, exports, require('../utils/isLocalStorageValid'), require('../utils/serializer'), require('../utils/promise'), require('../utils/executeCallback'), require('../utils/normalizeKey'), require('../utils/getCallback'));
- } else {
- var mod = {
- exports: {}
- };
- factory(mod, mod.exports, global.isLocalStorageValid, global.serializer, global.promise, global.executeCallback, global.normalizeKey, global.getCallback);
- global.localStorageWrapper = mod.exports;
- }
- })(this, function (module, exports, _isLocalStorageValid, _serializer, _promise, _executeCallback, _normalizeKey, _getCallback) {
- 'use strict';
-
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
-
- var _isLocalStorageValid2 = _interopRequireDefault(_isLocalStorageValid);
-
- var _serializer2 = _interopRequireDefault(_serializer);
-
- var _promise2 = _interopRequireDefault(_promise);
-
- var _executeCallback2 = _interopRequireDefault(_executeCallback);
-
- var _normalizeKey2 = _interopRequireDefault(_normalizeKey);
-
- var _getCallback2 = _interopRequireDefault(_getCallback);
-
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
-
- // If IndexedDB isn't available, we'll fall back to localStorage.
- // Note that this will have considerable performance and storage
- // side-effects (all data will be serialized on save and only data that
- // can be converted to a string via `JSON.stringify()` will be saved).
-
- function _getKeyPrefix(options, defaultConfig) {
- var keyPrefix = options.name + '/';
-
- if (options.storeName !== defaultConfig.storeName) {
- keyPrefix += options.storeName + '/';
- }
- return keyPrefix;
- }
-
- // Check if localStorage throws when saving an item
- function checkIfLocalStorageThrows() {
- var localStorageTestKey = '_localforage_support_test';
-
- try {
- localStorage.setItem(localStorageTestKey, true);
- localStorage.removeItem(localStorageTestKey);
-
- return false;
- } catch (e) {
- return true;
- }
- }
-
- // Check if localStorage is usable and allows to save an item
- // This method checks if localStorage is usable in Safari Private Browsing
- // mode, or in any other case where the available quota for localStorage
- // is 0 and there wasn't any saved items yet.
- function _isLocalStorageUsable() {
- return !checkIfLocalStorageThrows() || localStorage.length > 0;
- }
-
- // Config the localStorage backend, using options set in the config.
- function _initStorage(options) {
- var self = this;
- var dbInfo = {};
- if (options) {
- for (var i in options) {
- dbInfo[i] = options[i];
- }
- }
-
- dbInfo.keyPrefix = _getKeyPrefix(options, self._defaultConfig);
-
- if (!_isLocalStorageUsable()) {
- return _promise2.default.reject();
- }
-
- self._dbInfo = dbInfo;
- dbInfo.serializer = _serializer2.default;
-
- return _promise2.default.resolve();
- }
-
- // Remove all keys from the datastore, effectively destroying all data in
- // the app's key/value store!
- function clear(callback) {
- var self = this;
- var promise = self.ready().then(function () {
- var keyPrefix = self._dbInfo.keyPrefix;
-
- for (var i = localStorage.length - 1; i >= 0; i--) {
- var key = localStorage.key(i);
-
- if (key.indexOf(keyPrefix) === 0) {
- localStorage.removeItem(key);
- }
- }
- });
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- // Retrieve an item from the store. Unlike the original async_storage
- // library in Gaia, we don't modify return values at all. If a key's value
- // is `undefined`, we pass that value to the callback function.
- function getItem(key, callback) {
- var self = this;
-
- key = (0, _normalizeKey2.default)(key);
-
- var promise = self.ready().then(function () {
- var dbInfo = self._dbInfo;
- var result = localStorage.getItem(dbInfo.keyPrefix + key);
-
- // If a result was found, parse it from the serialized
- // string into a JS object. If result isn't truthy, the key
- // is likely undefined and we'll pass it straight to the
- // callback.
- if (result) {
- result = dbInfo.serializer.deserialize(result);
- }
-
- return result;
- });
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- // Iterate over all items in the store.
- function iterate(iterator, callback) {
- var self = this;
-
- var promise = self.ready().then(function () {
- var dbInfo = self._dbInfo;
- var keyPrefix = dbInfo.keyPrefix;
- var keyPrefixLength = keyPrefix.length;
- var length = localStorage.length;
-
- // We use a dedicated iterator instead of the `i` variable below
- // so other keys we fetch in localStorage aren't counted in
- // the `iterationNumber` argument passed to the `iterate()`
- // callback.
- //
- // See: github.com/mozilla/localForage/pull/435#discussion_r38061530
- var iterationNumber = 1;
-
- for (var i = 0; i < length; i++) {
- var key = localStorage.key(i);
- if (key.indexOf(keyPrefix) !== 0) {
- continue;
- }
- var value = localStorage.getItem(key);
-
- // If a result was found, parse it from the serialized
- // string into a JS object. If result isn't truthy, the
- // key is likely undefined and we'll pass it straight
- // to the iterator.
- if (value) {
- value = dbInfo.serializer.deserialize(value);
- }
-
- value = iterator(value, key.substring(keyPrefixLength), iterationNumber++);
-
- if (value !== void 0) {
- return value;
- }
- }
- });
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- // Same as localStorage's key() method, except takes a callback.
- function key(n, callback) {
- var self = this;
- var promise = self.ready().then(function () {
- var dbInfo = self._dbInfo;
- var result;
- try {
- result = localStorage.key(n);
- } catch (error) {
- result = null;
- }
-
- // Remove the prefix from the key, if a key is found.
- if (result) {
- result = result.substring(dbInfo.keyPrefix.length);
- }
-
- return result;
- });
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- function keys(callback) {
- var self = this;
- var promise = self.ready().then(function () {
- var dbInfo = self._dbInfo;
- var length = localStorage.length;
- var keys = [];
-
- for (var i = 0; i < length; i++) {
- var itemKey = localStorage.key(i);
- if (itemKey.indexOf(dbInfo.keyPrefix) === 0) {
- keys.push(itemKey.substring(dbInfo.keyPrefix.length));
- }
- }
-
- return keys;
- });
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- // Supply the number of keys in the datastore to the callback function.
- function length(callback) {
- var self = this;
- var promise = self.keys().then(function (keys) {
- return keys.length;
- });
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- // Remove an item from the store, nice and simple.
- function removeItem(key, callback) {
- var self = this;
-
- key = (0, _normalizeKey2.default)(key);
-
- var promise = self.ready().then(function () {
- var dbInfo = self._dbInfo;
- localStorage.removeItem(dbInfo.keyPrefix + key);
- });
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- // Set a key's value and run an optional callback once the value is set.
- // Unlike Gaia's implementation, the callback function is passed the value,
- // in case you want to operate on that value only after you're sure it
- // saved, or something like that.
- function setItem(key, value, callback) {
- var self = this;
-
- key = (0, _normalizeKey2.default)(key);
-
- var promise = self.ready().then(function () {
- // Convert undefined values to null.
- // https://github.com/mozilla/localForage/pull/42
- if (value === undefined) {
- value = null;
- }
-
- // Save the original value to pass to the callback.
- var originalValue = value;
-
- return new _promise2.default(function (resolve, reject) {
- var dbInfo = self._dbInfo;
- dbInfo.serializer.serialize(value, function (value, error) {
- if (error) {
- reject(error);
- } else {
- try {
- localStorage.setItem(dbInfo.keyPrefix + key, value);
- resolve(originalValue);
- } catch (e) {
- // localStorage capacity exceeded.
- // TODO: Make this a specific error/event.
- if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
- reject(e);
- }
- reject(e);
- }
- }
- });
- });
- });
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- function dropInstance(options, callback) {
- callback = _getCallback2.default.apply(this, arguments);
-
- options = typeof options !== 'function' && options || {};
- if (!options.name) {
- var currentConfig = this.config();
- options.name = options.name || currentConfig.name;
- options.storeName = options.storeName || currentConfig.storeName;
- }
-
- var self = this;
- var promise;
- if (!options.name) {
- promise = _promise2.default.reject('Invalid arguments');
- } else {
- promise = new _promise2.default(function (resolve) {
- if (!options.storeName) {
- resolve(options.name + '/');
- } else {
- resolve(_getKeyPrefix(options, self._defaultConfig));
- }
- }).then(function (keyPrefix) {
- for (var i = localStorage.length - 1; i >= 0; i--) {
- var key = localStorage.key(i);
-
- if (key.indexOf(keyPrefix) === 0) {
- localStorage.removeItem(key);
- }
- }
- });
- }
-
- (0, _executeCallback2.default)(promise, callback);
- return promise;
- }
-
- var localStorageWrapper = {
- _driver: 'localStorageWrapper',
- _initStorage: _initStorage,
- _support: (0, _isLocalStorageValid2.default)(),
- iterate: iterate,
- getItem: getItem,
- setItem: setItem,
- removeItem: removeItem,
- clear: clear,
- length: length,
- key: key,
- keys: keys,
- dropInstance: dropInstance
- };
-
- exports.default = localStorageWrapper;
- module.exports = exports['default'];
- });
|