/* * node-cache 4.1.1 ( 2018-01-31 ) * https://github.com/mpneuried/nodecache * * Released under the MIT license * https://github.com/mpneuried/nodecache/blob/master/LICENSE * * Maintained by ( ) */ (function() { var EventEmitter, NodeCache, _assignIn, _isArray, _isFunction, _isNumber, _isObject, _isString, _size, _template, clone, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty, slice = [].slice, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; _assignIn = require("lodash/assignIn"); _isArray = require("lodash/isArray"); _isString = require("lodash/isString"); _isFunction = require("lodash/isFunction"); _isNumber = require("lodash/isNumber"); _isObject = require("lodash/isObject"); _size = require("lodash/size"); _template = require("lodash/template"); clone = require("clone"); EventEmitter = require('events').EventEmitter; module.exports = NodeCache = (function(superClass) { extend(NodeCache, superClass); function NodeCache(options) { this.options = options != null ? options : {}; this._initErrors = bind(this._initErrors, this); this._error = bind(this._error, this); this._getValLength = bind(this._getValLength, this); this._wrap = bind(this._wrap, this); this._isInvalidKey = bind(this._isInvalidKey, this); this._check = bind(this._check, this); this._checkData = bind(this._checkData, this); this.close = bind(this.close, this); this.flushAll = bind(this.flushAll, this); this.getStats = bind(this.getStats, this); this.keys = bind(this.keys, this); this.getTtl = bind(this.getTtl, this); this.ttl = bind(this.ttl, this); this.del = bind(this.del, this); this.set = bind(this.set, this); this.mget = bind(this.mget, this); this.get = bind(this.get, this); this._initErrors(); this.data = {}; this.options = _assignIn({ forceString: false, objectValueSize: 80, arrayValueSize: 40, stdTTL: 0, checkperiod: 600, useClones: true, errorOnMissing: false, deleteOnExpire: true }, this.options); this.stats = { hits: 0, misses: 0, keys: 0, ksize: 0, vsize: 0 }; this.validKeyTypes = ["string", "number"]; this._checkData(); return; } NodeCache.prototype.get = function(key, cb, errorOnMissing) { var _err, _ret, err; if (typeof cb === "boolean" && arguments.length === 2) { errorOnMissing = cb; cb = void 0; } if ((err = this._isInvalidKey(key)) != null) { if (cb != null) { cb(err); return; } else { throw err; } } if ((this.data[key] != null) && this._check(key, this.data[key])) { this.stats.hits++; _ret = this._unwrap(this.data[key]); if (cb != null) { cb(null, _ret); } return _ret; } else { this.stats.misses++; if (this.options.errorOnMissing || errorOnMissing) { _err = this._error("ENOTFOUND", { key: key }, cb); if (_err != null) { throw _err; } return; } else { if (cb != null) { cb(null, void 0); } } return void 0; } }; NodeCache.prototype.mget = function(keys, cb) { var _err, err, i, key, len, oRet; if (!_isArray(keys)) { _err = this._error("EKEYSTYPE"); if (cb != null) { cb(_err); } return _err; } oRet = {}; for (i = 0, len = keys.length; i < len; i++) { key = keys[i]; if ((err = this._isInvalidKey(key)) != null) { if (cb != null) { cb(err); return; } else { throw err; } } if ((this.data[key] != null) && this._check(key, this.data[key])) { this.stats.hits++; oRet[key] = this._unwrap(this.data[key]); } else { this.stats.misses++; } } if (cb != null) { cb(null, oRet); } return oRet; }; NodeCache.prototype.set = function(key, value, ttl, cb) { var err, existent; if (this.options.forceString && !_isString(value)) { value = JSON.stringify(value); } if (arguments.length === 3 && _isFunction(ttl)) { cb = ttl; ttl = this.options.stdTTL; } if ((err = this._isInvalidKey(key)) != null) { if (cb != null) { cb(err); return; } else { throw err; } } existent = false; if (this.data[key]) { existent = true; this.stats.vsize -= this._getValLength(this._unwrap(this.data[key], false)); } this.data[key] = this._wrap(value, ttl); this.stats.vsize += this._getValLength(value); if (!existent) { this.stats.ksize += this._getKeyLength(key); this.stats.keys++; } this.emit("set", key, value); if (cb != null) { cb(null, true); } return true; }; NodeCache.prototype.del = function(keys, cb) { var delCount, err, i, key, len, oldVal; if (!_isArray(keys)) { keys = [keys]; } delCount = 0; for (i = 0, len = keys.length; i < len; i++) { key = keys[i]; if ((err = this._isInvalidKey(key)) != null) { if (cb != null) { cb(err); return; } else { throw err; } } if (this.data[key] != null) { this.stats.vsize -= this._getValLength(this._unwrap(this.data[key], false)); this.stats.ksize -= this._getKeyLength(key); this.stats.keys--; delCount++; oldVal = this.data[key]; delete this.data[key]; this.emit("del", key, oldVal.v); } else { this.stats.misses++; } } if (cb != null) { cb(null, delCount); } return delCount; }; NodeCache.prototype.ttl = function() { var arg, args, cb, err, i, key, len, ttl; key = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; for (i = 0, len = args.length; i < len; i++) { arg = args[i]; switch (typeof arg) { case "number": ttl = arg; break; case "function": cb = arg; } } ttl || (ttl = this.options.stdTTL); if (!key) { if (cb != null) { cb(null, false); } return false; } if ((err = this._isInvalidKey(key)) != null) { if (cb != null) { cb(err); return; } else { throw err; } } if ((this.data[key] != null) && this._check(key, this.data[key])) { if (ttl >= 0) { this.data[key] = this._wrap(this.data[key].v, ttl, false); } else { this.del(key); } if (cb != null) { cb(null, true); } return true; } else { if (cb != null) { cb(null, false); } return false; } }; NodeCache.prototype.getTtl = function(key, cb) { var _ttl, err; if (!key) { if (cb != null) { cb(null, void 0); } return void 0; } if ((err = this._isInvalidKey(key)) != null) { if (cb != null) { cb(err); return; } else { throw err; } } if ((this.data[key] != null) && this._check(key, this.data[key])) { _ttl = this.data[key].t; if (cb != null) { cb(null, _ttl); } return _ttl; } else { if (cb != null) { cb(null, void 0); } return void 0; } }; NodeCache.prototype.keys = function(cb) { var _keys; _keys = Object.keys(this.data); if (cb != null) { cb(null, _keys); } return _keys; }; NodeCache.prototype.getStats = function() { return this.stats; }; NodeCache.prototype.flushAll = function(_startPeriod) { if (_startPeriod == null) { _startPeriod = true; } this.data = {}; this.stats = { hits: 0, misses: 0, keys: 0, ksize: 0, vsize: 0 }; this._killCheckPeriod(); this._checkData(_startPeriod); this.emit("flush"); }; NodeCache.prototype.close = function() { this._killCheckPeriod(); }; NodeCache.prototype._checkData = function(startPeriod) { var key, ref, value; if (startPeriod == null) { startPeriod = true; } ref = this.data; for (key in ref) { value = ref[key]; this._check(key, value); } if (startPeriod && this.options.checkperiod > 0) { this.checkTimeout = setTimeout(this._checkData, this.options.checkperiod * 1000, startPeriod); if (this.checkTimeout.unref != null) { this.checkTimeout.unref(); } } }; NodeCache.prototype._killCheckPeriod = function() { if (this.checkTimeout != null) { return clearTimeout(this.checkTimeout); } }; NodeCache.prototype._check = function(key, data) { var _retval; _retval = true; if (data.t !== 0 && data.t < Date.now()) { if (this.options.deleteOnExpire) { _retval = false; this.del(key); } this.emit("expired", key, this._unwrap(data)); } return _retval; }; NodeCache.prototype._isInvalidKey = function(key) { var ref; if (ref = typeof key, indexOf.call(this.validKeyTypes, ref) < 0) { return this._error("EKEYTYPE", { type: typeof key }); } }; NodeCache.prototype._wrap = function(value, ttl, asClone) { var livetime, now, oReturn, ttlMultiplicator; if (asClone == null) { asClone = true; } if (!this.options.useClones) { asClone = false; } now = Date.now(); livetime = 0; ttlMultiplicator = 1000; if (ttl === 0) { livetime = 0; } else if (ttl) { livetime = now + (ttl * ttlMultiplicator); } else { if (this.options.stdTTL === 0) { livetime = this.options.stdTTL; } else { livetime = now + (this.options.stdTTL * ttlMultiplicator); } } return oReturn = { t: livetime, v: asClone ? clone(value) : value }; }; NodeCache.prototype._unwrap = function(value, asClone) { if (asClone == null) { asClone = true; } if (!this.options.useClones) { asClone = false; } if (value.v != null) { if (asClone) { return clone(value.v); } else { return value.v; } } return null; }; NodeCache.prototype._getKeyLength = function(key) { return key.length; }; NodeCache.prototype._getValLength = function(value) { if (_isString(value)) { return value.length; } else if (this.options.forceString) { return JSON.stringify(value).length; } else if (_isArray(value)) { return this.options.arrayValueSize * value.length; } else if (_isNumber(value)) { return 8; } else if (_isObject(value)) { return this.options.objectValueSize * _size(value); } else { return 0; } }; NodeCache.prototype._error = function(type, data, cb) { var error; if (data == null) { data = {}; } error = new Error(); error.name = type; error.errorcode = type; error.message = this.ERRORS[type] != null ? this.ERRORS[type](data) : "-"; error.data = data; if (cb && _isFunction(cb)) { cb(error, null); } else { return error; } }; NodeCache.prototype._initErrors = function() { var _errMsg, _errT, ref; this.ERRORS = {}; ref = this._ERRORS; for (_errT in ref) { _errMsg = ref[_errT]; this.ERRORS[_errT] = _template(_errMsg); } }; NodeCache.prototype._ERRORS = { "ENOTFOUND": "Key `<%= key %>` not found", "EKEYTYPE": "The key argument has to be of type `string` or `number`. Found: `<%= type %>`", "EKEYSTYPE": "The keys argument has to be an array." }; return NodeCache; })(EventEmitter); }).call(this);