persistent-storage
Version:
Abstracts access to any storage object implementing the webstorage Storage interface, offering optional compression using lz-string and optional encryption using crypto
166 lines • 5.46 kB
JavaScript
"use strict";
var crypto = require("./crypto");
var Config = require("./Config");
var lzString = require("lz-string");
var _ = require("lodash");
/**
* Constructs a new PersistentStorage instead
* @param opts
* @param {boolean=false} opts.useCompression
* @param {string=} opts.keyPrefix
* @param opts.storageBackend
* @constructor
*/
var PersistentStorage = (function () {
function PersistentStorage(opts) {
if (!opts.storageBackend) {
throw new Error("Must provide a storageBackend to wrap");
}
this.config = new Config(opts);
this.store = opts.storageBackend;
this.cache = {};
}
PersistentStorage.generateSalt = function (lengthBytes) {
return crypto.generateSalt(lengthBytes);
};
PersistentStorage.generateIV = function (lengthBytes) {
return crypto.generateIV(lengthBytes);
};
Object.defineProperty(PersistentStorage.prototype, "length", {
get: function () {
return this.keys().length;
},
enumerable: true,
configurable: true
});
/**
* Sets a value in the persistent storage
* @param {string} key - Key to associate this value with
* @param {*} value - Value to store, if undefined will delete the given key
*/
PersistentStorage.prototype.setItem = function (key, value) {
key = this.config.keyPrefix + key;
if (_.isUndefined(value)) {
return this.removeItem(key);
}
if (this.config.useCache) {
this.cache[key] = _.cloneDeep(value);
}
if (this.config.encryptKeys) {
key = crypto.encryptUtf8(key, this.config.encryption);
}
this.store.setItem(key, convertValueForStorage(value, this.config));
};
/**
* Gets a value from the persistant storage, uses in memory cache if possible
* @param {string} key - Key to retrieve
* @returns {*}
*/
PersistentStorage.prototype.getItem = function (key) {
key = this.config.keyPrefix + key;
if (this.config.useCache && this.cache.hasOwnProperty(key)) {
return _.cloneDeep(this.cache[key]);
}
if (this.config.encryptKeys) {
key = crypto.encryptUtf8(key, this.config.encryption);
}
var value = this.store.getItem(key);
if (value) {
value = inflateValueFromStorage(value, this.config);
if (this.config.useCache) {
this.cache[key] = value;
}
return value;
}
};
/**
* Gets the nth key in the store, note that the order of keys is not guaranteed but
* will be consistent so long as the key set stays the same.
* @param {number} n
* @returns {string}
*/
PersistentStorage.prototype.key = function (n) {
return this.keys()[n];
};
/**
* Gets an array of the keys in the store
* @returns {string[]}
*/
PersistentStorage.prototype.keys = function () {
var _this = this;
var prefix = this.config.keyPrefix, keys = _.chain(_.keys(this.store));
if (this.config.encryptKeys) {
keys = keys.map(function (key) {
try {
return crypto.decryptUtf8(key, _this.config.encryption);
}
catch (err) {
return '';
}
});
keys = keys.compact();
}
if (prefix) {
keys = keys.filter(function (key) {
return _.startsWith(key, prefix);
})
.map(function (key) {
return key.substr(prefix.length);
});
}
return keys.value();
};
/**
* Removes an item from the store
* @param {string} key
*/
PersistentStorage.prototype.removeItem = function (key) {
key = this.config.keyPrefix + key;
delete this.cache[key];
if (this.config.encryptKeys) {
key = crypto.encryptUtf8(key, this.config.encryption);
}
this.store.removeItem(key);
};
/**
* Clears all items from the store
*/
PersistentStorage.prototype.clear = function () {
var _this = this;
this.purgeCache();
if (this.config.keyPrefix) {
_.forEach(this.keys(), function (key) { return _this.removeItem(key); });
}
else {
this.store.clear();
}
};
/**
* Clears all items from the cache
*/
PersistentStorage.prototype.purgeCache = function () {
this.cache = {};
};
return PersistentStorage;
}());
function convertValueForStorage(value, config) {
var str = JSON.stringify(value);
if (config.useCompression) {
str = lzString.compressToUTF16(str);
}
if (config.useEncryption) {
str = crypto.encryptUcs2(str, config.encryption);
}
return str;
}
function inflateValueFromStorage(str, config) {
if (config.useEncryption) {
str = crypto.decryptUcs2(str, config.encryption);
}
if (config.useCompression) {
str = lzString.decompressFromUTF16(str);
}
return JSON.parse(str);
}
module.exports = PersistentStorage;
//# sourceMappingURL=PersistentStorage.js.map