Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

incache

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

incache - npm Package Compare versions

Comparing version 2.0.0 to 3.0.0

webpack.config.js

11

CHANGELOG.md

@@ -7,2 +7,13 @@ # Change Log

## [3.0.0] - 2017-08-19
- Library loading was changed:
- **Now you need to instantiate the `new InCache` object**
- Added cache writing to disk
- Added `setConfig` method
- Added `addTo` method
- Added `prependTo` method
- Added `updateIn` method
- Added `removeFrom` method
- Added global record configuration
## [2.0.0] - 2017-08-13

@@ -9,0 +20,0 @@ - Changed `set` method: last argument now is an object, see documentation.

892

dist/incache.js

@@ -1,2 +0,2 @@

// [AIV] InCache Build version: 2.0.0
// [AIV] InCache Build version: 3.0.0
var incache =

@@ -65,3 +65,3 @@ /******/ (function(modules) { // webpackBootstrap

/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ return __webpack_require__(__webpack_require__.s = 1);
/******/ })

@@ -76,299 +76,2 @@ /************************************************************************/

module.exports = __webpack_require__(1);
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(process, global) {
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var helper = __webpack_require__(4);
/**
* @namespace incache
*/
var incache = {};
/**
* Global key
* @type {string}
* @ignore
*/
var GLOBAL_KEY = '___incache___storage___global___key___';
/**
* Default options
* @type {{silent: boolean, life: number}}
* @ignore
*/
var DEFAULT_OPTS = {
silent: false,
life: 0
};
/**
* Root object
* @ignore
*/
var root = (typeof process === 'undefined' ? 'undefined' : _typeof(process)) === 'object' && typeof process.pid !== 'undefined' ? global : window;
if (!root[GLOBAL_KEY]) root[GLOBAL_KEY] = {};
/**
* Short storage
* @ignore
*/
var storage = root[GLOBAL_KEY];
var _onRemoved = function _onRemoved() {};
var _onCreated = function _onCreated() {};
var _onUpdated = function _onUpdated() {};
/**
* Set/update record
* @param key {any}
* @param value {any}
* @param [opts] {Object} options object
* @param [opts.silent=false] {boolean} if true no event will be triggered
* @param [opts.life=0] {number} seconds of life. If 0 not expire.
* @returns {{isNew: boolean, createdOn: Date|null, updatedOn: Date|null, value: *}}
* @example
* incache.set('my key', 'my value');
* incache.set('my object', {a: 1, b: 2});
* incache.set('my boolean', true, {life: 2}); // Expires after 2 seconds
*/
incache.set = function (key, value) {
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var record = {
isNew: true,
createdOn: null,
updatedOn: null,
expiresOn: null,
value: value
};
opts = helper.defaults(opts, DEFAULT_OPTS);
if (opts.life && helper.is(opts.life, 'number')) {
record.expiresOn = helper.addSecondsToNow(opts.life);
}
if (incache.has(key)) {
record.isNew = false;
record.updatedOn = new Date();
if (!opts.silent) _onUpdated.call(undefined, key, record);
} else {
record.createdOn = new Date();
if (!opts.silent) _onCreated.call(undefined, key, record);
}
storage[key] = record;
return record;
};
/**
* Set/update multiple records. This method not trigger any event.
* @param records {array} array of object, e.g. [{key: foo1, value: bar1},{key: foo2, value: bar2}]
* @example
* incache.bulkSet([
* {key: 'my key 1', value: 'my value 1'},
* {key: 'my key 2', value: 'my value 2'},
* {key: 'my key 3', value: 'my value 3'},
* {key: 'my key 4', value: 'my value 4'}
* ]);
*/
incache.bulkSet = function (records) {
if (!helper.is(records, 'array')) throw new Error('records must be an array of object, e.g. {key: foo, value: bar}');
for (var i = 0; i < records.length; i++) {
if (helper.is(records[i].key, 'undefined') || helper.is(records[i].value, 'undefined')) throw new Error('key and value properties are required');
incache.set(records[i].key, records[i].value, { silent: true });
}
};
/**
* Get record by key
* @param key {any}
* @param [onlyValue=true] {boolean} if false get incache record
* @returns {any|null}
* @example
* incache.get('my key');
*/
incache.get = function (key) {
var onlyValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
if (incache.has(key)) {
if (incache.expired(key)) {
incache.remove(key, true);
return null;
}
return onlyValue ? storage[key].value : storage[key];
} else {
return null;
}
};
/**
* Delete a record
* @param key {any}
* @param [silent=false] {boolean} if true no event will be triggered
* @example
* incache.remove('my key');
*/
incache.remove = function (key) {
var silent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
delete storage[key];
if (!silent) _onRemoved.call(undefined, key);
};
/**
* Delete multiple records
* @param keys {array} an array of keys
* @example
* incache.bulkRemove(['key1', 'key2', 'key3']);
*/
incache.bulkRemove = function (keys) {
if (!helper.is(keys, 'array')) throw new Error('keys must be an array of keys');
for (var i = 0; i < keys.length; i++) {
incache.remove(keys[i], true);
}
};
/**
* Fetch all records
* @returns {Array}
*/
incache.all = function () {
var records = [];
for (var key in storage) {
if (storage.hasOwnProperty(key)) {
if (incache.expired(key)) {
incache.remove(key, true);
} else {
records.push({
key: key,
value: storage[key].value
});
}
}
}
return records;
};
/**
* Check if record is expired
* @param key {any}
* @returns {boolean}
*/
incache.expired = function (key) {
if (storage[key] && storage[key].expiresOn) {
var now = new Date();
var expiry = new Date(storage[key].expiresOn);
return now > expiry;
} else {
return false;
}
};
/**
* Remove all records
*/
incache.clear = function () {
/**
* Reset object
* @ignore
*/
storage = root[GLOBAL_KEY] = {};
};
/**
* Check if key exists
* @param key {any}
* @returns {boolean}
* @example
* incache.has('my key');
*/
incache.has = function (key) {
return storage.hasOwnProperty(key);
};
/**
* Triggered when a record has been deleted
* @param callback {incache.onRemoved~removedCallback} callback function
* @example
* incache.onRemoved((key)=>{
* console.log('removed', key);
* });
*/
incache.onRemoved = function (callback) {
_onRemoved = callback;
};
/**
* onRemoved callback
* @callback incache.onRemoved~removedCallback
* @param key {string} key of record removed
*/
/**
* Triggered when a record has been created
* @param callback {incache.onCreated~createdCallback} callback function
* @example
* incache.onCreated((key, record)=>{
* console.log('created', key, record);
* });
*/
incache.onCreated = function (callback) {
_onCreated = callback;
};
/**
* onCreated callback
* @callback incache.onCreated~createdCallback
* @param key {string} key of record created
* @param record {Object} record object
*/
/**
* Triggered when a record has been updated
* @param callback {incache.onUpdated~updatedCallback} callback function
* @example
* incache.onUpdated((key, record)=>{
* console.log('updated', key, record);
* });
*/
incache.onUpdated = function (callback) {
_onUpdated = callback;
};
/**
* onUpdated callback
* @callback incache.onUpdated~updatedCallback
* @param key {string} key of record updated
* @param record {Object} record object
*/
/**
* Expose module
*/
module.exports = incache;
module.exports._global_key = GLOBAL_KEY;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(3)))
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// shim for using process in browser

@@ -561,2 +264,575 @@ var process = module.exports = {};

/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = __webpack_require__(2);
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(global, process) {
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var helper = __webpack_require__(4);
var fs = __webpack_require__(5);
var InCache = function () {
/**
* Create instance
* @param [opts] {Object} configuration object
* @param [opts.save=true] {boolean} if true saves cache in disk. (server only)
* @param [opts.filePath=.incache] {string} cache file path
* @param [opts.storeName] {string} store name
* @param [opts.global] {Object} global record configuration
* @param [opts.global.silent=false] {boolean} if true no event will be triggered
* @param [opts.global.life=0] {number} max age. If 0 not expire
* @constructor
*/
function InCache() {
var _this = this;
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, InCache);
/**
* Global key
* @type {string}
* @ignore
*/
this.GLOBAL_KEY = '___InCache___storage___global___key___';
/**
* Root object
* @ignore
*/
this._root = helper.isServer() ? global : window;
/**
* InCache default configuration
* @type {{storeName: string, save: boolean, filePath: string, global: {silent: boolean, life: number}}}
* @ignore
*/
this.DEFAULT_CONFIG = {
storeName: '',
save: true,
filePath: '.incache',
global: {
silent: false,
life: 0
}
};
// Defines callback private
this._onRemoved = function () {};
this._onCreated = function () {};
this._onUpdated = function () {};
if (helper.isServer()) {
process.stdin.resume();
process.on('exit', function () {
_this._write();
});
process.on('SIGINT', function () {
_this._write();
});
}
this.setConfig(opts);
}
_createClass(InCache, [{
key: '_write',
value: function _write() {
var _memory = this._memory,
config = _memory.config,
data = _memory.data;
if (config.save) {
var content = JSON.stringify(data);
fs.writeFileSync(config.filePath, content);
}
}
}, {
key: '_read',
value: function _read() {
var config = this._memory.config;
if (config.save && fs.existsSync(config.filePath)) {
var content = fs.readFileSync(config.filePath);
try {
this._storage = this._memory.data = JSON.parse(content);
} catch (e) {
this._storage = this._memory.data = {};
}
}
}
/**
* Set configuration
* @param [opts] {Object} configuration object
* @param [opts.save=true] {boolean} if true saves cache in disk. (server only)
* @param [opts.filePath=.incache] {string} cache file path
* @param [opts.storeName] {string} store name
* @param [opts.global] {Object} global record configuration
* @param [opts.global.silent=false] {boolean} if true no event will be triggered
* @param [opts.global.life=0] {number} max age. If 0 not expire
*/
}, {
key: 'setConfig',
value: function setConfig() {
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
if (opts.storeName) this.GLOBAL_KEY += opts.storeName;
if (!this._root[this.GLOBAL_KEY]) {
this._root[this.GLOBAL_KEY] = {
metadata: {
lastSave: null
},
data: {},
config: this.DEFAULT_CONFIG
};
}
this._root[this.GLOBAL_KEY].config = helper.defaults(opts, this.DEFAULT_CONFIG);
this._memory = this._root[this.GLOBAL_KEY];
this._storage = this._memory.data;
if (helper.isServer()) this._read();
}
/**
* Get configuration
* @returns {*}
*/
}, {
key: 'getConfig',
value: function getConfig() {
return this._memory.config;
}
/**
* Set/update record
* @param key {any}
* @param value {any}
* @param [opts] {Object} options object
* @param [opts.silent=false] {boolean} if true no event will be triggered. (overwrites global configuration)
* @param [opts.life=0] {number} max age. If 0 not expire. (overwrites global configuration)
* @returns {{isNew: boolean, createdOn: Date|null, updatedOn: Date|null, value: *}}
* @example
* inCache.set('my key', 'my value');
* inCache.set('my object', {a: 1, b: 2});
* inCache.set('my boolean', true, {life: 2}); // Expires after 2 seconds
*/
}, {
key: 'set',
value: function set(key, value) {
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var record = {
isNew: true,
createdOn: null,
updatedOn: null,
expiresOn: null,
value: value
};
opts = helper.defaults(opts, this.DEFAULT_CONFIG.global);
if (opts.life && helper.is(opts.life, 'number')) {
record.expiresOn = helper.addSecondsToNow(opts.life);
}
if (this.has(key)) {
record.isNew = false;
record.updatedOn = new Date();
if (!opts.silent) this._onUpdated.call(this, key, record);
} else {
record.createdOn = new Date();
if (!opts.silent) this._onCreated.call(this, key, record);
}
this._storage[key] = record;
return record;
}
/**
* Set/update multiple records. This method not trigger any event.
* @param records {array} array of object, e.g. [{key: foo1, value: bar1},{key: foo2, value: bar2}]
* @example
* inCache.bulkSet([
* {key: 'my key 1', value: 'my value 1'},
* {key: 'my key 2', value: 'my value 2'},
* {key: 'my key 3', value: 'my value 3'},
* {key: 'my key 4', value: 'my value 4'}
* ]);
*/
}, {
key: 'bulkSet',
value: function bulkSet(records) {
if (!helper.is(records, 'array')) throw new Error('records must be an array of object, e.g. {key: foo, value: bar}');
for (var i = 0; i < records.length; i++) {
if (helper.is(records[i].key, 'undefined') || helper.is(records[i].value, 'undefined')) throw new Error('key and value properties are required');
this.set(records[i].key, records[i].value, { silent: true, fromBulk: true });
}
}
/**
* Get record by key
* @param key {any}
* @param [onlyValue=true] {boolean} if false get InCache record
* @returns {any|null}
* @example
* inCache.get('my key');
*/
}, {
key: 'get',
value: function get(key) {
var onlyValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
if (this.has(key)) {
if (this.expired(key)) {
this.remove(key, true);
return null;
}
return onlyValue ? this._storage[key].value : this._storage[key];
} else {
return null;
}
}
/**
* Delete a record
* @param key {any}
* @param [silent=false] {boolean} if true no event will be triggered
* @param [opts] {Object} optional arguments
* @example
* inCache.remove('my key');
*/
}, {
key: 'remove',
value: function remove(key) {
var silent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
delete this._storage[key];
if (!silent) this._onRemoved.call(this, key);
}
/**
* Given a key that has value like an array adds value to end of array
* @param key {any}
* @param value {any}
* @returns {*}
* @example
* inCache.set('myArray', ['hello', 'world']);
* inCache.addTo('myArray', 'ciao'); //-> ['hello', 'world', 'ciao'];
*/
}, {
key: 'addTo',
value: function addTo(key, value) {
if (!this.has(key)) return null;
var record = this.get(key);
if (!helper.is(record, 'array')) throw new Error('object must be an array');
record.push(value);
return this.set(key, record);
}
/**
* Given a key that has value like an array adds value to beginning of array
* @param key {any}
* @param value {any}
* @returns {*}
* @example
* inCache.set('myArray', ['hello', 'world']);
* inCache.prependTo('myArray', 'ciao'); //-> ['ciao', 'hello', 'world'];
*/
}, {
key: 'prependTo',
value: function prependTo(key, value) {
if (!this.has(key)) return null;
var record = this.get(key);
if (!helper.is(record, 'array')) throw new Error('object must be an array');
record.unshift(value);
return this.set(key, record);
}
/**
* Given a key that has value like an array updates key(s) if `where` is satisfied
* @param key {any}
* @param value {any}
* @param where {any}
* @example
* inCache.set('myArray', ['hello', 'world']);
* inCache.updateIn('myArray', 'ciao', 'hello'); //-> ['ciao', 'world'];
*
* inCache.set('myArray', [{a: 1, b: 2, c: 3], {b: 2, c: 3}, {b: 4, e: 5});
* inCache.updateIn('myArray', {z: 0, x: 0}, {b: 2, c: 3}); //-> [{z: 0, x: 0}, {z: 0, x: 0}, {b: 4, e: 5}];
*/
}, {
key: 'updateIn',
value: function updateIn(key, value, where) {
if (!this.has(key)) return null;
if (helper.is(value, 'undefined')) throw new Error('value cannot be undefined');
if (helper.is(where, 'undefined')) throw new Error('where cannot be undefined');
var recordValue = this.get(key);
if (!helper.is(recordValue, 'array')) throw new Error('value must be an array');
var updated = false;
for (var i in recordValue) {
if (recordValue.hasOwnProperty(i)) {
var result = [];
for (var prop in where) {
if (where.hasOwnProperty(prop)) if (helper.is(where, 'object')) result.push(typeof recordValue[i][prop] !== 'undefined' && recordValue[i][prop] === where[prop]);else result.push(recordValue[i] === where);
}
if (result.length && result.indexOf(false) === -1) {
updated = true;
recordValue[i] = value;
}
}
}
if (updated) {
this.set(key, recordValue);
}
}
/**
* Given a key that has value like an array removes key(s) if `where` is satisfied
* @param key {any}
* @param where {any}
* @example
* inCache.set('myArray', ['hello', 'world']);
* inCache.removeFrom('myArray', 'hello'); //-> ['world'];
*/
}, {
key: 'removeFrom',
value: function removeFrom(key, where) {
if (!this.has(key)) return null;
if (helper.is(where, 'undefined')) throw new Error('where cannot be undefined');
var recordValue = this.get(key);
if (!helper.is(recordValue, 'array')) throw new Error('value must be an array');
var recordLengthBefore = recordValue.length;
for (var i in recordValue) {
if (recordValue.hasOwnProperty(i)) {
var result = [];
for (var prop in where) {
if (where.hasOwnProperty(prop)) if (helper.is(where, 'object')) result.push(typeof recordValue[i][prop] !== 'undefined' && recordValue[i][prop] === where[prop]);else result.push(recordValue[i] === where);
}
if (result.length && result.indexOf(false) === -1) recordValue.splice(i, 1);
}
}
if (recordLengthBefore !== recordValue.length) {
this.set(key, recordValue);
}
}
/**
* Delete multiple records
* @param keys {array} an array of keys
* @example
* inCache.bulkRemove(['key1', 'key2', 'key3']);
*/
}, {
key: 'bulkRemove',
value: function bulkRemove(keys) {
if (!helper.is(keys, 'array')) throw new Error('keys must be an array of keys');
for (var i = 0; i < keys.length; i++) {
this.remove(keys[i], true, { fromBulk: true });
}
}
/**
* Fetch all records
* @returns {Array}
*/
}, {
key: 'all',
value: function all() {
var records = [];
for (var key in this._storage) {
if (this._storage.hasOwnProperty(key)) {
if (this.expired(key)) {
this.remove(key, true);
} else {
records.push({
key: key,
value: this._storage[key].value
});
}
}
}
return records;
}
/**
* Check if record is expired
* @param key {any}
* @returns {boolean}
*/
}, {
key: 'expired',
value: function expired(key) {
if (this._storage[key] && this._storage[key].expiresOn) {
var now = new Date();
var expiry = new Date(this._storage[key].expiresOn);
return now > expiry;
} else {
return false;
}
}
/**
* Remove all records
*/
}, {
key: 'clear',
value: function clear() {
/**
* Reset object
* @ignore
*/
this._storage = this._memory.data = {};
}
/**
* Check if key exists
* @param key {any}
* @returns {boolean}
* @example
* inCache.has('my key');
*/
}, {
key: 'has',
value: function has(key) {
return this._storage.hasOwnProperty(key);
}
/**
* Triggered when a record has been deleted
* @param callback {InCache~removedCallback} callback function
* @example
* inCache.onRemoved((key)=>{
* console.log('removed', key);
* });
*/
}, {
key: 'onRemoved',
value: function onRemoved(callback) {
this._onRemoved = callback;
}
/**
* onRemoved callback
* @callback InCache~removedCallback
* @param key {string} key of record removed
*/
/**
* Triggered when a record has been created
* @param callback {InCache~createdCallback} callback function
* @example
* inCache.onCreated((key, record)=>{
* console.log('created', key, record);
* });
*/
}, {
key: 'onCreated',
value: function onCreated(callback) {
this._onCreated = callback;
}
/**
* onCreated callback
* @callback InCache~createdCallback
* @param key {string} key of record created
* @param record {Object} record object
*/
/**
* Triggered when a record has been updated
* @param callback {InCache~updatedCallback} callback function
* @example
* inCache.onUpdated((key, record)=>{
* console.log('updated', key, record);
* });
*/
}, {
key: 'onUpdated',
value: function onUpdated(callback) {
this._onUpdated = callback;
}
/**
* onUpdated callback
* @callback InCache~updatedCallback
* @param key {string} key of record updated
* @param record {Object} record object
*/
}]);
return InCache;
}();
/**
* Expose module
*/
module.exports = InCache;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(3), __webpack_require__(0)))
/***/ }),
/* 3 */

@@ -596,4 +872,4 @@ /***/ (function(module, exports, __webpack_require__) {

"use strict";
/* WEBPACK VAR INJECTION */(function(process) {
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

@@ -643,5 +919,21 @@

/**
* Check if is Node environment
* @returns {boolean}
*/
helper.isServer = function () {
return (typeof process === 'undefined' ? 'undefined' : _typeof(process)) === 'object' && typeof process.pid !== 'undefined';
};
module.exports = helper;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/***/ })
/******/ ]);

@@ -1,2 +0,2 @@

// [AIV] InCache Build version: 2.0.0
var incache=function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,n){"use strict";e.exports=n(1)},function(e,t,n){"use strict";(function(t,r){var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=n(4),u={},c="___incache___storage___global___key___",a={silent:!1,life:0},l="object"===(void 0===t?"undefined":o(t))&&void 0!==t.pid?r:window;l[c]||(l[c]={});var f=l[c],s=function(){},p=function(){},y=function(){};u.set=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r={isNew:!0,createdOn:null,updatedOn:null,expiresOn:null,value:t};return n=i.defaults(n,a),n.life&&i.is(n.life,"number")&&(r.expiresOn=i.addSecondsToNow(n.life)),u.has(e)?(r.isNew=!1,r.updatedOn=new Date,n.silent||y.call(void 0,e,r)):(r.createdOn=new Date,n.silent||p.call(void 0,e,r)),f[e]=r,r},u.bulkSet=function(e){if(!i.is(e,"array"))throw new Error("records must be an array of object, e.g. {key: foo, value: bar}");for(var t=0;t<e.length;t++){if(i.is(e[t].key,"undefined")||i.is(e[t].value,"undefined"))throw new Error("key and value properties are required");u.set(e[t].key,e[t].value,{silent:!0})}},u.get=function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return u.has(e)?u.expired(e)?(u.remove(e,!0),null):t?f[e].value:f[e]:null},u.remove=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];delete f[e],t||s.call(void 0,e)},u.bulkRemove=function(e){if(!i.is(e,"array"))throw new Error("keys must be an array of keys");for(var t=0;t<e.length;t++)u.remove(e[t],!0)},u.all=function(){var e=[];for(var t in f)f.hasOwnProperty(t)&&(u.expired(t)?u.remove(t,!0):e.push({key:t,value:f[t].value}));return e},u.expired=function(e){if(f[e]&&f[e].expiresOn){return new Date>new Date(f[e].expiresOn)}return!1},u.clear=function(){f=l[c]={}},u.has=function(e){return f.hasOwnProperty(e)},u.onRemoved=function(e){s=e},u.onCreated=function(e){p=e},u.onUpdated=function(e){y=e},e.exports=u,e.exports._global_key=c}).call(t,n(2),n(3))},function(e,t,n){"use strict";function r(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function i(e){if(s===setTimeout)return setTimeout(e,0);if((s===r||!s)&&setTimeout)return s=setTimeout,setTimeout(e,0);try{return s(e,0)}catch(t){try{return s.call(null,e,0)}catch(t){return s.call(this,e,0)}}}function u(e){if(p===clearTimeout)return clearTimeout(e);if((p===o||!p)&&clearTimeout)return p=clearTimeout,clearTimeout(e);try{return p(e)}catch(t){try{return p.call(null,e)}catch(t){return p.call(this,e)}}}function c(){m&&d&&(m=!1,d.length?h=d.concat(h):v=-1,h.length&&a())}function a(){if(!m){var e=i(c);m=!0;for(var t=h.length;t;){for(d=h,h=[];++v<t;)d&&d[v].run();v=-1,t=h.length}d=null,m=!1,u(e)}}function l(e,t){this.fun=e,this.array=t}function f(){}var s,p,y=e.exports={};!function(){try{s="function"==typeof setTimeout?setTimeout:r}catch(e){s=r}try{p="function"==typeof clearTimeout?clearTimeout:o}catch(e){p=o}}();var d,h=[],m=!1,v=-1;y.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];h.push(new l(e,t)),1!==h.length||m||i(a)},l.prototype.run=function(){this.fun.apply(null,this.array)},y.title="browser",y.browser=!0,y.env={},y.argv=[],y.version="",y.versions={},y.on=f,y.addListener=f,y.once=f,y.off=f,y.removeListener=f,y.removeAllListeners=f,y.emit=f,y.prependListener=f,y.prependOnceListener=f,y.listeners=function(e){return[]},y.binding=function(e){throw new Error("process.binding is not supported")},y.cwd=function(){return"/"},y.chdir=function(e){throw new Error("process.chdir is not supported")},y.umask=function(){return 0}},function(e,t,n){"use strict";var r,o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};r=function(){return this}();try{r=r||Function("return this")()||(0,eval)("this")}catch(e){"object"===("undefined"==typeof window?"undefined":o(window))&&(r=window)}e.exports=r},function(e,t,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o={};o.is=function(e,t){return Object.prototype.toString.call(e).toLowerCase()==="[object "+t+"]".toLowerCase()},o.defaults=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e.hasOwnProperty(n)?"object"===r(e[n])&&o.defaults(e[n],t[n]):e[n]=t[n]);return e},o.addSecondsToNow=function(e){var t=new Date;return new Date(t.setSeconds(t.getSeconds()+e))},e.exports=o}]);
// [AIV] InCache Build version: 3.0.0
var incache=function(e){function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var r={};return t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=1)}([function(e,t,r){"use strict";function n(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function i(e){if(c===setTimeout)return setTimeout(e,0);if((c===n||!c)&&setTimeout)return c=setTimeout,setTimeout(e,0);try{return c(e,0)}catch(t){try{return c.call(null,e,0)}catch(t){return c.call(this,e,0)}}}function a(e){if(h===clearTimeout)return clearTimeout(e);if((h===o||!h)&&clearTimeout)return h=clearTimeout,clearTimeout(e);try{return h(e)}catch(t){try{return h.call(null,e)}catch(t){return h.call(this,e)}}}function s(){p&&y&&(p=!1,y.length?v=y.concat(v):m=-1,v.length&&u())}function u(){if(!p){var e=i(s);p=!0;for(var t=v.length;t;){for(y=v,v=[];++m<t;)y&&y[m].run();m=-1,t=v.length}y=null,p=!1,a(e)}}function f(e,t){this.fun=e,this.array=t}function l(){}var c,h,d=e.exports={};!function(){try{c="function"==typeof setTimeout?setTimeout:n}catch(e){c=n}try{h="function"==typeof clearTimeout?clearTimeout:o}catch(e){h=o}}();var y,v=[],p=!1,m=-1;d.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)t[r-1]=arguments[r];v.push(new f(e,t)),1!==v.length||p||i(u)},f.prototype.run=function(){this.fun.apply(null,this.array)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.versions={},d.on=l,d.addListener=l,d.once=l,d.off=l,d.removeListener=l,d.removeAllListeners=l,d.emit=l,d.prependListener=l,d.prependOnceListener=l,d.listeners=function(e){return[]},d.binding=function(e){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(e){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}},function(e,t,r){"use strict";e.exports=r(2)},function(e,t,r){"use strict";(function(t,n){function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var i=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),a=r(4),s=r(5),u=function(){function e(){var r=this,i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};o(this,e),this.GLOBAL_KEY="___InCache___storage___global___key___",this._root=a.isServer()?t:window,this.DEFAULT_CONFIG={storeName:"",save:!0,filePath:".incache",global:{silent:!1,life:0}},this._onRemoved=function(){},this._onCreated=function(){},this._onUpdated=function(){},a.isServer()&&(n.stdin.resume(),n.on("exit",function(){r._write()}),n.on("SIGINT",function(){r._write()})),this.setConfig(i)}return i(e,[{key:"_write",value:function(){var e=this._memory,t=e.config,r=e.data;if(t.save){var n=JSON.stringify(r);s.writeFileSync(t.filePath,n)}}},{key:"_read",value:function(){var e=this._memory.config;if(e.save&&s.existsSync(e.filePath)){var t=s.readFileSync(e.filePath);try{this._storage=this._memory.data=JSON.parse(t)}catch(e){this._storage=this._memory.data={}}}}},{key:"setConfig",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};e.storeName&&(this.GLOBAL_KEY+=e.storeName),this._root[this.GLOBAL_KEY]||(this._root[this.GLOBAL_KEY]={metadata:{lastSave:null},data:{},config:this.DEFAULT_CONFIG}),this._root[this.GLOBAL_KEY].config=a.defaults(e,this.DEFAULT_CONFIG),this._memory=this._root[this.GLOBAL_KEY],this._storage=this._memory.data,a.isServer()&&this._read()}},{key:"getConfig",value:function(){return this._memory.config}},{key:"set",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n={isNew:!0,createdOn:null,updatedOn:null,expiresOn:null,value:t};return r=a.defaults(r,this.DEFAULT_CONFIG.global),r.life&&a.is(r.life,"number")&&(n.expiresOn=a.addSecondsToNow(r.life)),this.has(e)?(n.isNew=!1,n.updatedOn=new Date,r.silent||this._onUpdated.call(this,e,n)):(n.createdOn=new Date,r.silent||this._onCreated.call(this,e,n)),this._storage[e]=n,n}},{key:"bulkSet",value:function(e){if(!a.is(e,"array"))throw new Error("records must be an array of object, e.g. {key: foo, value: bar}");for(var t=0;t<e.length;t++){if(a.is(e[t].key,"undefined")||a.is(e[t].value,"undefined"))throw new Error("key and value properties are required");this.set(e[t].key,e[t].value,{silent:!0,fromBulk:!0})}}},{key:"get",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return this.has(e)?this.expired(e)?(this.remove(e,!0),null):t?this._storage[e].value:this._storage[e]:null}},{key:"remove",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];arguments.length>2&&void 0!==arguments[2]&&arguments[2];delete this._storage[e],t||this._onRemoved.call(this,e)}},{key:"addTo",value:function(e,t){if(!this.has(e))return null;var r=this.get(e);if(!a.is(r,"array"))throw new Error("object must be an array");return r.push(t),this.set(e,r)}},{key:"prependTo",value:function(e,t){if(!this.has(e))return null;var r=this.get(e);if(!a.is(r,"array"))throw new Error("object must be an array");return r.unshift(t),this.set(e,r)}},{key:"updateIn",value:function(e,t,r){if(!this.has(e))return null;if(a.is(t,"undefined"))throw new Error("value cannot be undefined");if(a.is(r,"undefined"))throw new Error("where cannot be undefined");var n=this.get(e);if(!a.is(n,"array"))throw new Error("value must be an array");var o=!1;for(var i in n)if(n.hasOwnProperty(i)){var s=[];for(var u in r)r.hasOwnProperty(u)&&(a.is(r,"object")?s.push(void 0!==n[i][u]&&n[i][u]===r[u]):s.push(n[i]===r));s.length&&-1===s.indexOf(!1)&&(o=!0,n[i]=t)}o&&this.set(e,n)}},{key:"removeFrom",value:function(e,t){if(!this.has(e))return null;if(a.is(t,"undefined"))throw new Error("where cannot be undefined");var r=this.get(e);if(!a.is(r,"array"))throw new Error("value must be an array");var n=r.length;for(var o in r)if(r.hasOwnProperty(o)){var i=[];for(var s in t)t.hasOwnProperty(s)&&(a.is(t,"object")?i.push(void 0!==r[o][s]&&r[o][s]===t[s]):i.push(r[o]===t));i.length&&-1===i.indexOf(!1)&&r.splice(o,1)}n!==r.length&&this.set(e,r)}},{key:"bulkRemove",value:function(e){if(!a.is(e,"array"))throw new Error("keys must be an array of keys");for(var t=0;t<e.length;t++)this.remove(e[t],!0,{fromBulk:!0})}},{key:"all",value:function(){var e=[];for(var t in this._storage)this._storage.hasOwnProperty(t)&&(this.expired(t)?this.remove(t,!0):e.push({key:t,value:this._storage[t].value}));return e}},{key:"expired",value:function(e){if(this._storage[e]&&this._storage[e].expiresOn){return new Date>new Date(this._storage[e].expiresOn)}return!1}},{key:"clear",value:function(){this._storage=this._memory.data={}}},{key:"has",value:function(e){return this._storage.hasOwnProperty(e)}},{key:"onRemoved",value:function(e){this._onRemoved=e}},{key:"onCreated",value:function(e){this._onCreated=e}},{key:"onUpdated",value:function(e){this._onUpdated=e}}]),e}();e.exports=u}).call(t,r(3),r(0))},function(e,t,r){"use strict";var n,o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"===("undefined"==typeof window?"undefined":o(window))&&(n=window)}e.exports=n},function(e,t,r){"use strict";(function(t){var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n={};n.is=function(e,t){return Object.prototype.toString.call(e).toLowerCase()==="[object "+t+"]".toLowerCase()},n.defaults=function(e,t){for(var o in t)t.hasOwnProperty(o)&&(e.hasOwnProperty(o)?"object"===r(e[o])&&n.defaults(e[o],t[o]):e[o]=t[o]);return e},n.addSecondsToNow=function(e){var t=new Date;return new Date(t.setSeconds(t.getSeconds()+e))},n.isServer=function(){return"object"===(void 0===t?"undefined":r(t))&&void 0!==t.pid},e.exports=n}).call(t,r(0))},function(e,t,r){"use strict"}]);
{
"name": "incache",
"version": "2.0.0",
"description": "Share singleton via global object, yes you can!",
"version": "3.0.0",
"description": "Simple key/value in-memory storage or on disk to persist some data",
"main": "index.js",

@@ -13,3 +13,6 @@ "scripts": {

"test": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage",
"doc": "jsdoc2md --no-gfm src/incache.js > api.md"
"doc": "jsdoc2md --no-gfm src/incache.js > api.md",
"benchmark:app": "node ./test/app/index.js",
"benchmark:koa": "node ./node_modules/artillery/bin/artillery quick -d 10 -r 1000 -k http://127.0.0.1:3188/benchmark/notCached",
"benchmark:cache": "node ./node_modules/artillery/bin/artillery quick -d 10 -r 1000 -k http://127.0.0.1:3188/benchmark/cached"
},

@@ -25,2 +28,7 @@ "repository": {

"storage",
"session",
"http",
"response",
"data",
"caching",
"share"

@@ -35,3 +43,4 @@ ],

"devDependencies": {
"babel-core": "^6.25.0",
"artillery": "^1.6.0-4",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.1",

@@ -43,8 +52,11 @@ "babel-preset-es2015": "^6.24.1",

"jsdoc-to-markdown": "^3.0.0",
"koa": "^2.3.0",
"koa-router": "^7.2.1",
"mocha": "^3.5.0",
"mocha-lcov-reporter": "^1.3.0",
"unminified-webpack-plugin": "^1.2.0",
"webpack": "^3.5.3",
"webpack": "^3.5.5",
"webpack-auto-inject-version": "^0.5.14"
}
},
"dependencies": {}
}

@@ -5,3 +5,3 @@ <div align="center">

<br/><br/>
Share singleton via global object, yes you can!
Simple key/value in-memory storage or on disk to persist some data
<br/><br/>

@@ -14,2 +14,6 @@ <a href="https://travis-ci.org/fabioricali/incache" target="_blank"><img src="https://travis-ci.org/fabioricali/incache.svg?branch=master" title="Build Status"/></a>

## Why?
InCache is a module that store any info in memory, it can be used for example for storing **server sessions**, **caching http response** or **sharing singleton object** in your apps.
It also give you the possibility to save data on disk so you can avoid the data loss when the process exit or restart.
## Installation

@@ -24,3 +28,4 @@

```javascript
const store = require('incache');
const InCache = require('incache');
const store = new InCache();

@@ -62,4 +67,4 @@ // Create a record with key 'my key'

### API Documentation
See <a href="https://github.com/fabioricali/incache/blob/master/api.md">here</a>
### API
See <a href="https://github.com/fabioricali/incache/blob/master/api.md">full documentation</a>

@@ -90,2 +95,5 @@ ### Browser

## Author
<a target="_blank" href="http://rica.li">Fabio Ricali</a>
<a target="_blank" href="http://rica.li">Fabio Ricali</a>
## Contributor
<a target="_blank" href="https://www.mdslab.org">Davide Polano</a>

@@ -44,2 +44,10 @@ const helper = {};

/**
* Check if is Node environment
* @returns {boolean}
*/
helper.isServer = () => {
return typeof process === 'object' && typeof process.pid !== 'undefined';
};
module.exports = helper;
const helper = require('./helper');
const fs = require('fs');
/**
* @namespace incache
*/
const incache = {};
class InCache {
/**
* Create instance
* @param [opts] {Object} configuration object
* @param [opts.save=true] {boolean} if true saves cache in disk. (server only)
* @param [opts.filePath=.incache] {string} cache file path
* @param [opts.storeName] {string} store name
* @param [opts.global] {Object} global record configuration
* @param [opts.global.silent=false] {boolean} if true no event will be triggered
* @param [opts.global.life=0] {number} max age. If 0 not expire
* @constructor
*/
constructor(opts = {}) {
/**
* Global key
* @type {string}
* @ignore
*/
const GLOBAL_KEY = '___incache___storage___global___key___';
/**
* Global key
* @type {string}
* @ignore
*/
/**
* Default options
* @type {{silent: boolean, life: number}}
* @ignore
*/
const DEFAULT_OPTS = {
silent: false,
life: 0
};
this.GLOBAL_KEY = '___InCache___storage___global___key___';
/**
* Root object
* @ignore
*/
const root = typeof process === 'object' && typeof process.pid !== 'undefined' ? global : window;
/**
* Root object
* @ignore
*/
this._root = helper.isServer() ? global : window;
if (!root[GLOBAL_KEY])
root[GLOBAL_KEY] = {};
/**
* InCache default configuration
* @type {{storeName: string, save: boolean, filePath: string, global: {silent: boolean, life: number}}}
* @ignore
*/
this.DEFAULT_CONFIG = {
storeName: '',
save: true,
filePath: '.incache',
global: {
silent: false,
life: 0
}
};
/**
* Short storage
* @ignore
*/
let storage = root[GLOBAL_KEY];
// Defines callback private
this._onRemoved = () => {};
this._onCreated = () => {};
this._onUpdated = () => {};
let _onRemoved = () => {
};
let _onCreated = () => {
};
let _onUpdated = () => {
};
if(helper.isServer()) {
process.stdin.resume();
process.on('exit', () => {
this._write()
});
process.on('SIGINT', () => {
this._write()
});
}
/**
* Set/update record
* @param key {any}
* @param value {any}
* @param [opts] {Object} options object
* @param [opts.silent=false] {boolean} if true no event will be triggered
* @param [opts.life=0] {number} seconds of life. If 0 not expire.
* @returns {{isNew: boolean, createdOn: Date|null, updatedOn: Date|null, value: *}}
* @example
* incache.set('my key', 'my value');
* incache.set('my object', {a: 1, b: 2});
* incache.set('my boolean', true, {life: 2}); // Expires after 2 seconds
*/
incache.set = (key, value, opts = {}) => {
let record = {
isNew: true,
createdOn: null,
updatedOn: null,
expiresOn: null,
value: value
};
this.setConfig(opts);
}
opts = helper.defaults(opts, DEFAULT_OPTS);
_write() {
let {config, data} = this._memory;
if (config.save) {
let content = JSON.stringify(data);
fs.writeFileSync(config.filePath, content);
}
}
if (opts.life && helper.is(opts.life, 'number')) {
record.expiresOn = helper.addSecondsToNow(opts.life);
_read() {
let config = this._memory.config;
if (config.save && fs.existsSync(config.filePath)) {
let content = fs.readFileSync(config.filePath);
try {
this._storage = this._memory.data = JSON.parse(content);
} catch (e) {
this._storage = this._memory.data = {};
}
}
}
if (incache.has(key)) {
record.isNew = false;
record.updatedOn = new Date();
if (!opts.silent)
_onUpdated.call(this, key, record);
} else {
record.createdOn = new Date();
if (!opts.silent)
_onCreated.call(this, key, record);
/**
* Set configuration
* @param [opts] {Object} configuration object
* @param [opts.save=true] {boolean} if true saves cache in disk. (server only)
* @param [opts.filePath=.incache] {string} cache file path
* @param [opts.storeName] {string} store name
* @param [opts.global] {Object} global record configuration
* @param [opts.global.silent=false] {boolean} if true no event will be triggered
* @param [opts.global.life=0] {number} max age. If 0 not expire
*/
setConfig(opts = {}) {
if (opts.storeName)
this.GLOBAL_KEY += opts.storeName;
if (!this._root[this.GLOBAL_KEY]) {
this._root[this.GLOBAL_KEY] = {
metadata: {
lastSave: null
},
data: {},
config: this.DEFAULT_CONFIG
};
}
this._root[this.GLOBAL_KEY].config = helper.defaults(opts, this.DEFAULT_CONFIG);
this._memory = this._root[this.GLOBAL_KEY];
this._storage = this._memory.data;
if (helper.isServer())
this._read();
}
storage[key] = record;
/**
* Get configuration
* @returns {*}
*/
getConfig() {
return this._memory.config;
}
return record;
};
/**
* Set/update record
* @param key {any}
* @param value {any}
* @param [opts] {Object} options object
* @param [opts.silent=false] {boolean} if true no event will be triggered. (overwrites global configuration)
* @param [opts.life=0] {number} max age. If 0 not expire. (overwrites global configuration)
* @returns {{isNew: boolean, createdOn: Date|null, updatedOn: Date|null, value: *}}
* @example
* inCache.set('my key', 'my value');
* inCache.set('my object', {a: 1, b: 2});
* inCache.set('my boolean', true, {life: 2}); // Expires after 2 seconds
*/
set(key, value, opts = {}) {
let record = {
isNew: true,
createdOn: null,
updatedOn: null,
expiresOn: null,
value: value
};
/**
* Set/update multiple records. This method not trigger any event.
* @param records {array} array of object, e.g. [{key: foo1, value: bar1},{key: foo2, value: bar2}]
* @example
* incache.bulkSet([
* {key: 'my key 1', value: 'my value 1'},
* {key: 'my key 2', value: 'my value 2'},
* {key: 'my key 3', value: 'my value 3'},
* {key: 'my key 4', value: 'my value 4'}
* ]);
*/
incache.bulkSet = (records) => {
if (!helper.is(records, 'array'))
throw new Error('records must be an array of object, e.g. {key: foo, value: bar}');
opts = helper.defaults(opts, this.DEFAULT_CONFIG.global);
for (let i = 0; i < records.length; i++) {
if (helper.is(records[i].key, 'undefined') || helper.is(records[i].value, 'undefined'))
throw new Error('key and value properties are required');
incache.set(records[i].key, records[i].value, {silent: true});
if (opts.life && helper.is(opts.life, 'number')) {
record.expiresOn = helper.addSecondsToNow(opts.life);
}
if (this.has(key)) {
record.isNew = false;
record.updatedOn = new Date();
if (!opts.silent)
this._onUpdated.call(this, key, record);
} else {
record.createdOn = new Date();
if (!opts.silent)
this._onCreated.call(this, key, record);
}
this._storage[key] = record;
return record;
}
};
/**
* Get record by key
* @param key {any}
* @param [onlyValue=true] {boolean} if false get incache record
* @returns {any|null}
* @example
* incache.get('my key');
*/
incache.get = (key, onlyValue = true) => {
if (incache.has(key)) {
if (incache.expired(key)) {
incache.remove(key, true);
/**
* Set/update multiple records. This method not trigger any event.
* @param records {array} array of object, e.g. [{key: foo1, value: bar1},{key: foo2, value: bar2}]
* @example
* inCache.bulkSet([
* {key: 'my key 1', value: 'my value 1'},
* {key: 'my key 2', value: 'my value 2'},
* {key: 'my key 3', value: 'my value 3'},
* {key: 'my key 4', value: 'my value 4'}
* ]);
*/
bulkSet(records) {
if (!helper.is(records, 'array'))
throw new Error('records must be an array of object, e.g. {key: foo, value: bar}');
for (let i = 0; i < records.length; i++) {
if (helper.is(records[i].key, 'undefined') || helper.is(records[i].value, 'undefined'))
throw new Error('key and value properties are required');
this.set(records[i].key, records[i].value, {silent: true, fromBulk: true});
}
}
/**
* Get record by key
* @param key {any}
* @param [onlyValue=true] {boolean} if false get InCache record
* @returns {any|null}
* @example
* inCache.get('my key');
*/
get(key, onlyValue = true) {
if (this.has(key)) {
if (this.expired(key)) {
this.remove(key, true);
return null;
}
return onlyValue ? this._storage[key].value : this._storage[key];
} else {
return null;
}
return onlyValue ? storage[key].value : storage[key];
} else {
return null;
}
};
/**
* Delete a record
* @param key {any}
* @param [silent=false] {boolean} if true no event will be triggered
* @example
* incache.remove('my key');
*/
incache.remove = (key, silent = false) => {
delete storage[key];
if (!silent)
_onRemoved.call(this, key);
};
/**
* Delete a record
* @param key {any}
* @param [silent=false] {boolean} if true no event will be triggered
* @param [opts] {Object} optional arguments
* @example
* inCache.remove('my key');
*/
remove(key, silent = false, opts = {}) {
delete this._storage[key];
if (!silent)
this._onRemoved.call(this, key);
}
/**
* Delete multiple records
* @param keys {array} an array of keys
* @example
* incache.bulkRemove(['key1', 'key2', 'key3']);
*/
incache.bulkRemove = (keys) => {
if (!helper.is(keys, 'array'))
throw new Error('keys must be an array of keys');
/**
* Given a key that has value like an array adds value to end of array
* @param key {any}
* @param value {any}
* @returns {*}
* @example
* inCache.set('myArray', ['hello', 'world']);
* inCache.addTo('myArray', 'ciao'); //-> ['hello', 'world', 'ciao'];
*/
addTo(key, value) {
if (!this.has(key)) return null;
let record = this.get(key);
for (let i = 0; i < keys.length; i++) {
incache.remove(keys[i], true);
if (!helper.is(record, 'array'))
throw new Error('object must be an array');
record.push(value);
return this.set(key, record);
}
};
/**
* Fetch all records
* @returns {Array}
*/
incache.all = () => {
let records = [];
/**
* Given a key that has value like an array adds value to beginning of array
* @param key {any}
* @param value {any}
* @returns {*}
* @example
* inCache.set('myArray', ['hello', 'world']);
* inCache.prependTo('myArray', 'ciao'); //-> ['ciao', 'hello', 'world'];
*/
prependTo(key, value) {
if (!this.has(key)) return null;
let record = this.get(key);
for (let key in storage) {
if (storage.hasOwnProperty(key)) {
if(incache.expired(key)) {
incache.remove(key, true);
} else {
records.push({
key: key,
value: storage[key].value
});
if (!helper.is(record, 'array'))
throw new Error('object must be an array');
record.unshift(value);
return this.set(key, record);
}
/**
* Given a key that has value like an array updates key(s) if `where` is satisfied
* @param key {any}
* @param value {any}
* @param where {any}
* @example
* inCache.set('myArray', ['hello', 'world']);
* inCache.updateIn('myArray', 'ciao', 'hello'); //-> ['ciao', 'world'];
*
* inCache.set('myArray', [{a: 1, b: 2, c: 3], {b: 2, c: 3}, {b: 4, e: 5});
* inCache.updateIn('myArray', {z: 0, x: 0}, {b: 2, c: 3}); //-> [{z: 0, x: 0}, {z: 0, x: 0}, {b: 4, e: 5}];
*/
updateIn(key, value, where) {
if (!this.has(key)) return null;
if (helper.is(value, 'undefined'))
throw new Error('value cannot be undefined');
if (helper.is(where, 'undefined'))
throw new Error('where cannot be undefined');
let recordValue = this.get(key);
if (!helper.is(recordValue, 'array'))
throw new Error('value must be an array');
let updated = false;
for (let i in recordValue) {
if (recordValue.hasOwnProperty(i)) {
let result = [];
for (let prop in where) {
if (where.hasOwnProperty(prop))
if (helper.is(where, 'object'))
result.push(typeof recordValue[i][prop] !== 'undefined' && recordValue[i][prop] === where[prop]);
else
result.push(recordValue[i] === where);
}
if (result.length && result.indexOf(false) === -1) {
updated = true;
recordValue[i] = value;
}
}
}
if (updated) {
this.set(key, recordValue);
}
}
return records;
};
/**
* Given a key that has value like an array removes key(s) if `where` is satisfied
* @param key {any}
* @param where {any}
* @example
* inCache.set('myArray', ['hello', 'world']);
* inCache.removeFrom('myArray', 'hello'); //-> ['world'];
*/
removeFrom(key, where) {
if (!this.has(key)) return null;
/**
* Check if record is expired
* @param key {any}
* @returns {boolean}
*/
incache.expired = (key) => {
if (storage[key] && storage[key].expiresOn) {
let now = new Date();
let expiry = new Date(storage[key].expiresOn);
return now > expiry;
} else {
return false;
if (helper.is(where, 'undefined'))
throw new Error('where cannot be undefined');
let recordValue = this.get(key);
if (!helper.is(recordValue, 'array'))
throw new Error('value must be an array');
let recordLengthBefore = recordValue.length;
for (let i in recordValue) {
if (recordValue.hasOwnProperty(i)) {
let result = [];
for (let prop in where) {
if (where.hasOwnProperty(prop))
if (helper.is(where, 'object'))
result.push(typeof recordValue[i][prop] !== 'undefined' && recordValue[i][prop] === where[prop]);
else
result.push(recordValue[i] === where);
}
if (result.length && result.indexOf(false) === -1)
recordValue.splice(i, 1);
}
}
if (recordLengthBefore !== recordValue.length) {
this.set(key, recordValue);
}
}
};
/**
* Remove all records
*/
incache.clear = () => {
/**
* Reset object
* @ignore
* Delete multiple records
* @param keys {array} an array of keys
* @example
* inCache.bulkRemove(['key1', 'key2', 'key3']);
*/
storage = root[GLOBAL_KEY] = {};
};
bulkRemove(keys) {
if (!helper.is(keys, 'array'))
throw new Error('keys must be an array of keys');
/**
* Check if key exists
* @param key {any}
* @returns {boolean}
* @example
* incache.has('my key');
*/
incache.has = (key) => {
return storage.hasOwnProperty(key);
};
for (let i = 0; i < keys.length; i++) {
this.remove(keys[i], true, {fromBulk: true});
}
}
/**
* Triggered when a record has been deleted
* @param callback {incache.onRemoved~removedCallback} callback function
* @example
* incache.onRemoved((key)=>{
* console.log('removed', key);
* });
*/
incache.onRemoved = (callback) => {
_onRemoved = callback;
};
/**
* Fetch all records
* @returns {Array}
*/
all() {
let records = [];
/**
* onRemoved callback
* @callback incache.onRemoved~removedCallback
* @param key {string} key of record removed
*/
for (let key in this._storage) {
if (this._storage.hasOwnProperty(key)) {
if (this.expired(key)) {
this.remove(key, true);
} else {
records.push({
key: key,
value: this._storage[key].value
});
}
}
}
/**
* Triggered when a record has been created
* @param callback {incache.onCreated~createdCallback} callback function
* @example
* incache.onCreated((key, record)=>{
* console.log('created', key, record);
* });
*/
incache.onCreated = (callback) => {
_onCreated = callback;
};
return records;
}
/**
* onCreated callback
* @callback incache.onCreated~createdCallback
* @param key {string} key of record created
* @param record {Object} record object
*/
/**
* Check if record is expired
* @param key {any}
* @returns {boolean}
*/
expired(key) {
if (this._storage[key] && this._storage[key].expiresOn) {
let now = new Date();
let expiry = new Date(this._storage[key].expiresOn);
return now > expiry;
} else {
return false;
}
}
/**
* Triggered when a record has been updated
* @param callback {incache.onUpdated~updatedCallback} callback function
* @example
* incache.onUpdated((key, record)=>{
* console.log('updated', key, record);
* });
*/
incache.onUpdated = (callback) => {
_onUpdated = callback;
};
/**
* Remove all records
*/
clear() {
/**
* Reset object
* @ignore
*/
this._storage = this._memory.data = {};
}
/**
* onUpdated callback
* @callback incache.onUpdated~updatedCallback
* @param key {string} key of record updated
* @param record {Object} record object
*/
/**
* Check if key exists
* @param key {any}
* @returns {boolean}
* @example
* inCache.has('my key');
*/
has(key) {
return this._storage.hasOwnProperty(key);
}
/**
* Triggered when a record has been deleted
* @param callback {InCache~removedCallback} callback function
* @example
* inCache.onRemoved((key)=>{
* console.log('removed', key);
* });
*/
onRemoved(callback) {
this._onRemoved = callback;
}
/**
* onRemoved callback
* @callback InCache~removedCallback
* @param key {string} key of record removed
*/
/**
* Triggered when a record has been created
* @param callback {InCache~createdCallback} callback function
* @example
* inCache.onCreated((key, record)=>{
* console.log('created', key, record);
* });
*/
onCreated(callback) {
this._onCreated = callback;
}
/**
* onCreated callback
* @callback InCache~createdCallback
* @param key {string} key of record created
* @param record {Object} record object
*/
/**
* Triggered when a record has been updated
* @param callback {InCache~updatedCallback} callback function
* @example
* inCache.onUpdated((key, record)=>{
* console.log('updated', key, record);
* });
*/
onUpdated(callback) {
this._onUpdated = callback;
}
/**
* onUpdated callback
* @callback InCache~updatedCallback
* @param key {string} key of record updated
* @param record {Object} record object
*/
}
/**
* Expose module
*/
module.exports = incache;
module.exports._global_key = GLOBAL_KEY;
module.exports = InCache;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc