Comparing version 4.0.2 to 4.2.0
@@ -0,1 +1,13 @@ | ||
### 4.2.0 | ||
* True timeouts for cache calls - **[@jkrems](https://github.com/jkrems)** [#22](https://github.com/groupon/node-cached/pull/22) | ||
- [`0d9e48f`](https://github.com/groupon/node-cached/commit/0d9e48fc07b82723a481499084a9bf14f3bc1b0d) **feat:** True timeouts for cache calls | ||
### 4.1.1 | ||
* Switch to nlm - **[@jkrems](https://github.com/jkrems)** [#21](https://github.com/groupon/node-cached/pull/21) | ||
- [`bdac8c6`](https://github.com/groupon/node-cached/commit/bdac8c6f1f68e6296abf513c941736c88771149a) **chore:** Switch to nlm | ||
4.0.2 | ||
@@ -2,0 +14,0 @@ ----- |
@@ -1,63 +0,65 @@ | ||
// Generated by CoffeeScript 1.9.1 | ||
/* | ||
Copyright (c) 2014, Groupon, Inc. | ||
All rights reserved. | ||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions | ||
are met: | ||
Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
Neither the name of GROUPON nor the names of its contributors may be | ||
used to endorse or promote products derived from this software without | ||
specific prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
* Copyright (c) 2014, Groupon, Inc. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* | ||
* Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in the | ||
* documentation and/or other materials provided with the distribution. | ||
* | ||
* Neither the name of GROUPON nor the names of its contributors may be | ||
* used to endorse or promote products derived from this software without | ||
* specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
'use strict'; | ||
var typeMap; | ||
typeMap = Object.create(null); | ||
var typeMap = Object.create(null); | ||
exports.addType = function(type, klass) { | ||
return typeMap[type] = klass; | ||
}; | ||
function isBackend(object) { | ||
return typeof object.get === 'function' && typeof object.set === 'function'; | ||
} | ||
exports.create = function(options) { | ||
var klass, ref, type; | ||
if (options == null) { | ||
options = {}; | ||
} | ||
if ('function' === typeof options.get && 'function' === typeof options.set) { | ||
exports.create = function create(options) { | ||
options = options || {}; | ||
if (isBackend(options)) { | ||
return options; | ||
} | ||
type = (ref = options.type) != null ? ref : 'noop'; | ||
klass = typeMap[type]; | ||
if (klass == null) { | ||
throw new Error(type + " is not a supported cache backend type"); | ||
var type = options.type || 'noop'; | ||
var BackendClass = typeMap[type]; | ||
if (!BackendClass) { | ||
throw new Error(type + ' is not a supported cache backend type'); | ||
} | ||
return new klass(options); | ||
return new BackendClass(options); | ||
}; | ||
exports.addType('noop', require("./backends/noop")); | ||
function addType(type, BackendClass) { | ||
typeMap[type] = BackendClass; | ||
return BackendClass; | ||
} | ||
exports.addType = addType; | ||
exports.addType('memory', require("./backends/memory")); | ||
addType('noop', require('./backends/noop')); | ||
exports.addType('memcached', require("./backends/memcached")); | ||
addType('memory', require('./backends/memory')); | ||
addType('memcached', require('./backends/memcached')); |
@@ -1,90 +0,75 @@ | ||
// Generated by CoffeeScript 1.9.1 | ||
/* | ||
Copyright (c) 2014, Groupon, Inc. | ||
All rights reserved. | ||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions | ||
are met: | ||
Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
Neither the name of GROUPON nor the names of its contributors may be | ||
used to endorse or promote products derived from this software without | ||
specific prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
* Copyright (c) 2014, Groupon, Inc. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* | ||
* Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in the | ||
* documentation and/or other materials provided with the distribution. | ||
* | ||
* Neither the name of GROUPON nor the names of its contributors may be | ||
* used to endorse or promote products derived from this software without | ||
* specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
'use strict'; | ||
var Memcached, MemcachedBackend, promisify; | ||
Memcached = require('memcached'); | ||
var promisify = require('bluebird').promisify; | ||
var _ = require('lodash'); | ||
var Memcached = require('memcached'); | ||
promisify = require('bluebird').promisify; | ||
MemcachedBackend = (function() { | ||
var description; | ||
description = "Uses anything supporting the memcache protocol"; | ||
function MemcachedBackend(options) { | ||
var hosts, ref; | ||
this.type = 'memcached'; | ||
if (options.client != null) { | ||
this.client = options.client; | ||
} else { | ||
hosts = (ref = options.hosts) != null ? ref : '127.0.0.1:11211'; | ||
this.client = new Memcached(hosts, options); | ||
} | ||
this._clientGet = promisify(this.client.get, this.client); | ||
this._clientSet = promisify(this.client.set, this.client); | ||
this._clientDel = promisify(this.client.del, this.client); | ||
function createClient(options) { | ||
if (options.client) { | ||
return options.client; | ||
} | ||
var hosts = options.hosts || '127.0.0.1:11211'; | ||
return new Memcached(hosts, options); | ||
} | ||
MemcachedBackend.prototype.get = function(key) { | ||
return this._clientGet(key).then(function(answer) { | ||
if (answer === false) { | ||
return null; | ||
} else { | ||
return answer; | ||
} | ||
}); | ||
}; | ||
function normalizeValue(value) { | ||
return value === false ? null : value; | ||
} | ||
MemcachedBackend.prototype.set = function(key, value, options) { | ||
return this._clientSet(key, value, options.expire).then(function() { | ||
return value; | ||
}); | ||
}; | ||
/* Uses anything supporting the memcache protocol */ | ||
function MemcachedBackend(options) { | ||
this.type = 'memcached'; | ||
var client = this.client = createClient(options); | ||
this._clientGet = promisify(client.get, { context: client }); | ||
this._clientSet = promisify(client.set, { context: client }); | ||
this._clientDel = promisify(client.del, { context: client }); | ||
} | ||
module.exports = MemcachedBackend; | ||
MemcachedBackend.prototype.unset = function(key) { | ||
return this._clientDel(key).then(function() { | ||
return void 0; | ||
}); | ||
}; | ||
MemcachedBackend.prototype.get = function get(key) { | ||
return this._clientGet(key).then(normalizeValue); | ||
}; | ||
MemcachedBackend.prototype.end = function() { | ||
return this.client.end(); | ||
}; | ||
MemcachedBackend.prototype.set = function set(key, value, options) { | ||
return this._clientSet(key, value, options.expire) | ||
.then(_.constant(value)); | ||
}; | ||
return MemcachedBackend; | ||
MemcachedBackend.prototype.unset = function unset(key) { | ||
return this._clientDel(key).then(_.noop); | ||
}; | ||
})(); | ||
module.exports = MemcachedBackend; | ||
MemcachedBackend.prototype.end = function end() { | ||
return this.client.end(); | ||
}; |
@@ -1,92 +0,65 @@ | ||
// Generated by CoffeeScript 1.9.1 | ||
/* | ||
Copyright (c) 2014, Groupon, Inc. | ||
All rights reserved. | ||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions | ||
are met: | ||
Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
Neither the name of GROUPON nor the names of its contributors may be | ||
used to endorse or promote products derived from this software without | ||
specific prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
* Copyright (c) 2014, Groupon, Inc. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* | ||
* Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in the | ||
* documentation and/or other materials provided with the distribution. | ||
* | ||
* Neither the name of GROUPON nor the names of its contributors may be | ||
* used to endorse or promote products derived from this software without | ||
* specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
'use strict'; | ||
var MemoryBackend, Promise; | ||
Promise = require('bluebird'); | ||
var Bluebird = require('bluebird'); | ||
MemoryBackend = (function() { | ||
var description; | ||
var util = require('../util'); | ||
description = "Stores everything just in memory"; | ||
/* Stores everything just in memory */ | ||
function MemoryBackend() { | ||
this.cache = Object.create(null); | ||
this.type = 'memory'; | ||
} | ||
module.exports = MemoryBackend; | ||
function MemoryBackend() { | ||
this.cache = Object.create(null); | ||
this.type = 'memory'; | ||
MemoryBackend.prototype.get = function get(key) { | ||
var wrappedValue = this.cache[key] || null; | ||
if (util.isExpired(wrappedValue && wrappedValue.e)) { | ||
wrappedValue = null; | ||
delete this.cache[key]; | ||
} | ||
return Bluebird.resolve(wrappedValue ? wrappedValue.d : null); | ||
}; | ||
MemoryBackend.prototype.get = function(key) { | ||
var ref, ref1, ref2; | ||
if (this.isExpired((ref = this.cache[key]) != null ? ref.e : void 0)) { | ||
delete this.cache[key]; | ||
} | ||
return Promise.resolve((ref1 = (ref2 = this.cache[key]) != null ? ref2.d : void 0) != null ? ref1 : null); | ||
MemoryBackend.prototype.set = function set(key, value, options) { | ||
this.cache[key] = { | ||
d: value, | ||
e: util.expiresAt(options.expire), | ||
}; | ||
return Bluebird.resolve(value); | ||
}; | ||
MemoryBackend.prototype.expiresAt = function(seconds) { | ||
if (seconds === 0) { | ||
return 0; | ||
} else { | ||
return (new Date()).getTime() + (parseInt(seconds) * 1000); | ||
} | ||
}; | ||
MemoryBackend.prototype.isExpired = function(expires) { | ||
if (expires == null) { | ||
return false; | ||
} | ||
if (expires === 0) { | ||
return false; | ||
} | ||
return (new Date()).getTime() > (new Date(expires)).getTime(); | ||
}; | ||
MemoryBackend.prototype.set = function(key, value, options) { | ||
this.cache[key] = { | ||
d: value, | ||
e: this.expiresAt(options.expire) | ||
}; | ||
return Promise.resolve(value); | ||
}; | ||
MemoryBackend.prototype.unset = function(key) { | ||
delete this.cache[key]; | ||
return Promise.resolve(); | ||
}; | ||
return MemoryBackend; | ||
})(); | ||
module.exports = MemoryBackend; | ||
MemoryBackend.prototype.unset = function unset(key) { | ||
delete this.cache[key]; | ||
return Bluebird.resolve(); | ||
}; |
@@ -1,64 +0,52 @@ | ||
// Generated by CoffeeScript 1.9.1 | ||
/* | ||
Copyright (c) 2014, Groupon, Inc. | ||
All rights reserved. | ||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions | ||
are met: | ||
Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
Neither the name of GROUPON nor the names of its contributors may be | ||
used to endorse or promote products derived from this software without | ||
specific prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
* Copyright (c) 2014, Groupon, Inc. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* | ||
* Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in the | ||
* documentation and/or other materials provided with the distribution. | ||
* | ||
* Neither the name of GROUPON nor the names of its contributors may be | ||
* used to endorse or promote products derived from this software without | ||
* specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
'use strict'; | ||
var NoopBackend, Promise; | ||
Promise = require('bluebird'); | ||
var Bluebird = require('bluebird'); | ||
NoopBackend = (function() { | ||
var description; | ||
/* Simple backend doing nothing */ | ||
function NoopBackend() { | ||
this.type = 'noop'; | ||
} | ||
module.exports = NoopBackend; | ||
description = "Simple backend doing nothing"; | ||
NoopBackend.prototype.get = function get(/* key */) { | ||
return Bluebird.resolve(null); | ||
}; | ||
function NoopBackend() { | ||
this.type = 'noop'; | ||
} | ||
NoopBackend.prototype.set = function set(key, value) { | ||
return Bluebird.resolve(value); | ||
}; | ||
NoopBackend.prototype.get = function(key) { | ||
return Promise.resolve(null); | ||
}; | ||
NoopBackend.prototype.set = function(key, value) { | ||
return Promise.resolve(value); | ||
}; | ||
NoopBackend.prototype.unset = function(key) { | ||
return Promise.resolve(); | ||
}; | ||
return NoopBackend; | ||
})(); | ||
module.exports = NoopBackend; | ||
NoopBackend.prototype.unset = function unset(/* key */) { | ||
return Bluebird.resolve(); | ||
}; |
285
lib/cache.js
@@ -1,211 +0,130 @@ | ||
// Generated by CoffeeScript 1.9.1 | ||
/* | ||
Copyright (c) 2014, Groupon, Inc. | ||
All rights reserved. | ||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions | ||
are met: | ||
Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
Neither the name of GROUPON nor the names of its contributors may be | ||
used to endorse or promote products derived from this software without | ||
specific prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
* Copyright (c) 2014, Groupon, Inc. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* | ||
* Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in the | ||
* documentation and/or other materials provided with the distribution. | ||
* | ||
* Neither the name of GROUPON nor the names of its contributors may be | ||
* used to endorse or promote products derived from this software without | ||
* specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
'use strict'; | ||
var Backend, Cache, Promise, expiresAt, extend, isExpired, optionalOpts, toPromise; | ||
extend = require('lodash').extend; | ||
var _ = require('lodash'); | ||
Promise = require('bluebird'); | ||
var Backend = require('./backend'); | ||
var getOrElse = require('./get-or-else'); | ||
var util = require('./util'); | ||
Backend = require('./backend'); | ||
function Cache(options) { | ||
this.defaults = { | ||
freshFor: 0, | ||
expire: 0, | ||
}; | ||
this.name = options.name || 'default'; | ||
this.prefix = this.name + ':'; | ||
this.staleOrPending = {}; | ||
toPromise = function(val) { | ||
if ('function' === typeof val) { | ||
return Promise.resolve(val()); | ||
} else { | ||
return Promise.resolve(val); | ||
} | ||
this.setDefaults(options.defaults); | ||
this.setBackend(options.backend); | ||
} | ||
Cache.prototype.applyPrefix = function applyPrefix(key) { | ||
return [this.prefix, key].join(''); | ||
}; | ||
expiresAt = function(seconds) { | ||
if (seconds === 0) { | ||
return 0; | ||
} else { | ||
return Date.now() + parseInt(seconds, 10) * 1000; | ||
} | ||
Cache.prototype.setDefaults = function setDefaults(defaults) { | ||
this.defaults = this.prepareOptions(defaults); | ||
return this.defaults; | ||
}; | ||
isExpired = function(expires) { | ||
if (expires === 0) { | ||
return false; | ||
} | ||
return Date.now() > new Date(expires).getTime(); | ||
Cache.prototype.setBackend = function setBackend(backendOptions) { | ||
backendOptions = typeof backendOptions === 'string' ? { | ||
type: backendOptions, | ||
} : backendOptions || {}; | ||
this.end(); | ||
this.backend = Backend.create(backendOptions); | ||
return this.backend; | ||
}; | ||
optionalOpts = function(opts, cb) { | ||
if ((cb == null) && 'function' === typeof opts) { | ||
return { | ||
cb: opts, | ||
opts: null | ||
}; | ||
} else { | ||
return { | ||
cb: cb, | ||
opts: opts | ||
}; | ||
Cache.prototype.end = function end() { | ||
if (this.backend && this.backend.end) { | ||
return this.backend.end(); | ||
} | ||
}; | ||
Cache = (function() { | ||
function Cache(arg) { | ||
var backend, defaults, name; | ||
backend = arg.backend, defaults = arg.defaults, name = arg.name; | ||
this.defaults = { | ||
freshFor: 0, | ||
expire: 0 | ||
}; | ||
this.name = name || 'default'; | ||
this.prefix = this.name + ":"; | ||
this.staleOrPending = {}; | ||
this.setDefaults(defaults); | ||
this.setBackend(backend); | ||
Cache.prototype.prepareOptions = function prepareOptions(options) { | ||
return _.extend({}, this.defaults, options); | ||
}; | ||
Cache.prototype._set = function _set(key, val, options) { | ||
var self = this; | ||
function writeToBackend(resolvedValue) { | ||
return self.backend.set(key, { | ||
b: util.expiresAt(options.freshFor), | ||
d: resolvedValue, | ||
}, options); | ||
} | ||
Cache.prototype.applyPrefix = function(key) { | ||
return [this.prefix, key].join(''); | ||
}; | ||
return this._applyTimeout(util.toPromise(val).then(writeToBackend)); | ||
}; | ||
Cache.prototype.setDefaults = function(defaults) { | ||
return this.defaults = this.prepareOptions(defaults); | ||
}; | ||
Cache.prototype.set = function set(rawKey, val, _opts, _cb) { | ||
var args = util.optionalOpts(_opts, _cb); | ||
var key = this.applyPrefix(rawKey); | ||
var optsWithDefaults = this.prepareOptions(args.opts); | ||
Cache.prototype.setBackend = function(backendOptions) { | ||
backendOptions = 'string' === typeof backendOptions ? { | ||
type: backendOptions | ||
} : backendOptions != null ? backendOptions : {}; | ||
this.end(); | ||
return this.backend = Backend.create(backendOptions); | ||
}; | ||
return this._set(key, val, optsWithDefaults).nodeify(args.cb); | ||
}; | ||
Cache.prototype.end = function() { | ||
var ref; | ||
if (((ref = this.backend) != null ? ref.end : void 0) != null) { | ||
return this.backend.end(); | ||
} | ||
}; | ||
Cache.prototype._applyTimeout = function _applyTimeout(value) { | ||
var timeoutMs = this.defaults.timeout; | ||
if (timeoutMs > 0) { | ||
return value.timeout(timeoutMs); | ||
} | ||
return value; | ||
}; | ||
Cache.prototype.prepareOptions = function(options) { | ||
return extend({}, this.defaults, options); | ||
}; | ||
Cache.prototype._getWrapped = function _getWrapped(key) { | ||
return this._applyTimeout(this.backend.get(key)); | ||
}; | ||
// For backwards compatibility, eventually we should deprecate this. | ||
// It *should* be a private API. | ||
Cache.prototype.getWrapped = Cache.prototype._getWrapped; | ||
Cache.prototype.set = function(key, val, opts, cb) { | ||
var ref; | ||
ref = optionalOpts(opts, cb), cb = ref.cb, opts = ref.opts; | ||
key = this.applyPrefix(key); | ||
opts = this.prepareOptions(opts); | ||
return toPromise(val).then((function(_this) { | ||
return function(resolvedValue) { | ||
return _this.backend.set(key, { | ||
b: expiresAt(opts.freshFor), | ||
d: resolvedValue | ||
}, opts); | ||
}; | ||
})(this)).nodeify(cb); | ||
}; | ||
Cache.prototype.get = function get(rawKey, cb) { | ||
var key = this.applyPrefix(rawKey); | ||
Cache.prototype.getWrapped = function(key) { | ||
return this.backend.get(key); | ||
}; | ||
return this._getWrapped(key).then(util.extractValue).nodeify(cb); | ||
}; | ||
Cache.prototype.get = function(rawKey, cb) { | ||
var key; | ||
key = this.applyPrefix(rawKey); | ||
return this.getWrapped(key).then(function(wrappedValue) { | ||
var ref; | ||
return (ref = wrappedValue != null ? wrappedValue.d : void 0) != null ? ref : null; | ||
}).nodeify(cb); | ||
}; | ||
Cache.prototype.getOrElse = function _getOrElse(rawKey, val, _opts, _cb) { | ||
var key = this.applyPrefix(rawKey); | ||
var args = util.optionalOpts(_opts, _cb); | ||
var optsWithDefaults = this.prepareOptions(args.opts); | ||
Cache.prototype.getOrElse = function(rawKey, val, opts, cb) { | ||
var handleError, key, ref, refreshValue, resetStaleOrPending, verifyFreshness, writeValue; | ||
key = this.applyPrefix(rawKey); | ||
ref = optionalOpts(opts, cb), cb = ref.cb, opts = ref.opts; | ||
opts = this.prepareOptions(opts); | ||
resetStaleOrPending = (function(_this) { | ||
return function(passThroughData) { | ||
delete _this.staleOrPending[key]; | ||
return passThroughData; | ||
}; | ||
})(this); | ||
writeValue = (function(_this) { | ||
return function(generatedValue) { | ||
return _this.set(rawKey, generatedValue, opts).then(function(rawValue) { | ||
var ref1; | ||
return (ref1 = rawValue != null ? rawValue.d : void 0) != null ? ref1 : null; | ||
}, function() { | ||
return generatedValue != null ? generatedValue : null; | ||
}); | ||
}; | ||
})(this); | ||
refreshValue = function() { | ||
var refreshed; | ||
return refreshed = toPromise(val).then(writeValue).then(resetStaleOrPending, function(err) { | ||
resetStaleOrPending(); | ||
if (refreshed.wasEverReturned) { | ||
return Promise.reject(err); | ||
} else { | ||
return null; | ||
} | ||
}); | ||
}; | ||
verifyFreshness = (function(_this) { | ||
return function(wrappedValue) { | ||
var dataFromCache, expired, hit, loadingNewValue; | ||
hit = wrappedValue != null; | ||
expired = isExpired(wrappedValue != null ? wrappedValue.b : void 0); | ||
loadingNewValue = _this.staleOrPending[key] != null; | ||
dataFromCache = wrappedValue != null ? wrappedValue.d : void 0; | ||
if ((!hit || expired) && !loadingNewValue) { | ||
_this.staleOrPending[key] = refreshValue(); | ||
loadingNewValue = true; | ||
} | ||
if ((dataFromCache == null) && loadingNewValue) { | ||
_this.staleOrPending[key].wasEverReturned = true; | ||
return _this.staleOrPending[key]; | ||
} else { | ||
return dataFromCache; | ||
} | ||
}; | ||
})(this); | ||
handleError = function(error) { | ||
return null; | ||
}; | ||
return this.getWrapped(key)["catch"](handleError).then(verifyFreshness).nodeify(cb); | ||
}; | ||
return getOrElse(this, key, val, optsWithDefaults).nodeify(args.cb); | ||
}; | ||
return Cache; | ||
})(); | ||
module.exports = Cache; |
@@ -1,66 +0,58 @@ | ||
// Generated by CoffeeScript 1.9.1 | ||
/* | ||
Copyright (c) 2014, Groupon, Inc. | ||
All rights reserved. | ||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions | ||
are met: | ||
Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
Neither the name of GROUPON nor the names of its contributors may be | ||
used to endorse or promote products derived from this software without | ||
specific prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
* Copyright (c) 2014, Groupon, Inc. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* | ||
* Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in the | ||
* documentation and/or other materials provided with the distribution. | ||
* | ||
* Neither the name of GROUPON nor the names of its contributors may be | ||
* used to endorse or promote products derived from this software without | ||
* specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
'use strict'; | ||
var Cache, Promise, cached, extend, namedCaches; | ||
Promise = require('bluebird'); | ||
var Bluebird = require('bluebird'); | ||
var _ = require('lodash'); | ||
extend = require('lodash').extend; | ||
var Cache = require('./cache'); | ||
Cache = require('./cache'); | ||
var namedCaches = Object.create(null); | ||
namedCaches = Object.create(null); | ||
function cached(name, options) { | ||
name = name || 'default'; | ||
cached = function(name, options) { | ||
if (name == null) { | ||
name = "default"; | ||
if (!(name in namedCaches)) { | ||
namedCaches[name] = cached.createCache(_.extend({ | ||
name: name, | ||
}, options || {})); | ||
} | ||
if (options == null) { | ||
options = {}; | ||
} | ||
options = extend({ | ||
name: name | ||
}, options); | ||
return namedCaches[name] != null ? namedCaches[name] : namedCaches[name] = cached.createCache(options); | ||
}; | ||
return namedCaches[name]; | ||
} | ||
module.exports = cached; | ||
cached.createCache = function(options) { | ||
if (options == null) { | ||
options = {}; | ||
} | ||
return new Cache(options); | ||
cached.createCache = function createCache(options) { | ||
return new Cache(options || {}); | ||
}; | ||
cached.dropNamedCaches = function() { | ||
cached.dropNamedCaches = function dropNamedCaches() { | ||
namedCaches = Object.create(null); | ||
@@ -70,3 +62,3 @@ return cached; | ||
cached.dropNamedCache = function(name) { | ||
cached.dropNamedCache = function dropNamedCache(name) { | ||
delete namedCaches[name]; | ||
@@ -76,10 +68,8 @@ return cached; | ||
cached.knownCaches = function() { | ||
cached.knownCaches = function knownCaches() { | ||
return Object.keys(namedCaches); | ||
}; | ||
cached.deferred = function(fn) { | ||
return Promise.promisify(fn); | ||
cached.deferred = function deferred(fn) { | ||
return Bluebird.promisify(fn); | ||
}; | ||
module.exports = cached; |
{ | ||
"name": "cached", | ||
"version": "4.0.2", | ||
"version": "4.2.0", | ||
"description": "Simple access to a cache", | ||
"license": "BSD-3-Clause", | ||
"main": "lib/cached.js", | ||
"keywords": [ | ||
"memcached", | ||
"stampede", | ||
"cache" | ||
], | ||
"scripts": { | ||
"build": "coffee -cbo lib src", | ||
"watch": "coffee -wcbo lib src", | ||
"prepublish": "rm -rf lib && npm run build", | ||
"pretest": "npm run build", | ||
"test": "mocha", | ||
"posttest": "npub verify" | ||
}, | ||
"homepage": "https://github.com/groupon/node-cached", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/groupon/node-cached.git" | ||
"url": "git+ssh://git@github.com/groupon/node-cached" | ||
}, | ||
"author": { | ||
"name": "Jan Krems", | ||
"email": "jan.krems@groupon.com>" | ||
"bugs": { | ||
"url": "https://github.com/groupon/node-cached/issues" | ||
}, | ||
"publishConfig": { | ||
"registry": "https://registry.npmjs.org", | ||
"scripts": { | ||
"pretest": "eslint lib test", | ||
"test": "mocha", | ||
"posttest": "nlm verify", | ||
"watch": "mocha --watch" | ||
}, | ||
"nlm": { | ||
"license": { | ||
"exclude": [ | ||
"lib", | ||
"test" | ||
"files": [ | ||
"lib" | ||
] | ||
@@ -37,3 +29,3 @@ } | ||
"dependencies": { | ||
"bluebird": "^2.9.7", | ||
"bluebird": "^3.0.5", | ||
"lodash": "^3.1.0", | ||
@@ -43,7 +35,24 @@ "memcached": "^2.1.0" | ||
"devDependencies": { | ||
"assertive": "^1.4.1", | ||
"coffee-script": "^1.9.0", | ||
"mocha": "^2.0.1", | ||
"npub": "~0.5.1" | ||
"assertive": "^2.0.0", | ||
"babel-core": "^5.8.33", | ||
"eslint": "^1.0.0", | ||
"eslint-config-groupon": "^2.0.0", | ||
"mocha": "^2.0.0", | ||
"nlm": "^2.0.0" | ||
}, | ||
"author": { | ||
"name": "Groupon", | ||
"email": "opensource@groupon.com" | ||
}, | ||
"keywords": [ | ||
"memcached", | ||
"stampede", | ||
"cache" | ||
], | ||
"files": [ | ||
"lib" | ||
], | ||
"publishConfig": { | ||
"registry": "https://registry.npmjs.org" | ||
} | ||
} |
@@ -141,2 +141,7 @@ # cached | ||
* `freshFor` is the time in seconds after which a value should be replaced. Replacing the value is done in the background and while the new value is generated (e.g. data is fetched from some service) the stale value is returned. Think of `freshFor` as a smarter `expire`. | ||
* `timeout` is the maximum time in milliseconds to wait for cache operations to complete. | ||
Configuring a timeout ensures that all `get` and `set` operations fail fast. | ||
Otherwise there will be situations where one of the cache hosts goes down and reads hang for minutes while the memcached client retries to establish a connection. | ||
It's **highly** recommended to set a timeout. | ||
If `timeout` is left `undefined`, no timeout will be set and the operations will only fail once the underlying client, e.g. [`memcached`](https://github.com/3rd-Eden/memcached), gave up. | ||
@@ -143,0 +148,0 @@ ### Cache.set(key, value, opts, cb) -> Promise[Value] |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
32478
546
0
0
175
6
12
2
+ Addedbluebird@3.7.2(transitive)
- Removedbluebird@2.11.0(transitive)
Updatedbluebird@^3.0.5