@sailshq/connect-redis
Advanced tools
Comparing version 3.2.1 to 6.1.3
@@ -1,1 +0,1 @@ | ||
module.exports = require('./lib/connect-redis'); | ||
module.exports = require("./lib/connect-redis") |
/*! | ||
* Connect - Redis | ||
* Copyright(c) 2012 TJ Holowaychuk <tj@vision-media.ca> | ||
* Copyright(c) 2010-2020 TJ Holowaychuk <tj@vision-media.ca> | ||
* MIT Licensed | ||
*/ | ||
var debug = require('debug')('connect:redis'); | ||
var redis = require('redis'); | ||
var util = require('util'); | ||
var noop = function(){}; | ||
/** | ||
* One day in seconds. | ||
*/ | ||
var oneDay = 86400; | ||
function getTTL(store, sess) { | ||
var maxAge = sess.cookie.maxAge; | ||
return store.ttl || (typeof maxAge === 'number' | ||
? Math.floor(maxAge / 1000) | ||
: oneDay); | ||
} | ||
/** | ||
* Return the `RedisStore` extending `express`'s session Store. | ||
* | ||
* @param {object} express session | ||
* @return {Function} | ||
* @api public | ||
*/ | ||
module.exports = function (session) { | ||
const Store = session.Store | ||
/** | ||
* Express's session Store. | ||
*/ | ||
// All callbacks should have a noop if none provided for compatibility | ||
// with the most Redis clients. | ||
const noop = () => {} | ||
var Store = session.Store; | ||
class RedisStore extends Store { | ||
constructor(options = {}) { | ||
super(options) | ||
if (!options.client) { | ||
throw new Error("A client must be directly provided to the RedisStore") | ||
} | ||
/** | ||
* Initialize RedisStore with the given `options`. | ||
* | ||
* @param {Object} options | ||
* @api public | ||
*/ | ||
function RedisStore (options) { | ||
if (!(this instanceof RedisStore)) { | ||
throw new TypeError('Cannot call RedisStore constructor as a function'); | ||
this.prefix = options.prefix == null ? "sess:" : options.prefix | ||
this.scanCount = Number(options.scanCount) || 100 | ||
this.serializer = options.serializer || JSON | ||
this.client = options.client | ||
this.ttl = options.ttl || 86400 // One day in seconds. | ||
this.disableTTL = options.disableTTL || false | ||
this.disableTouch = options.disableTouch || false | ||
} | ||
var self = this; | ||
get(sid, cb = noop) { | ||
let key = this.prefix + sid | ||
options = options || {}; | ||
Store.call(this, options); | ||
this.prefix = options.prefix == null | ||
? 'sess:' | ||
: options.prefix; | ||
this.client.get(key, (err, data) => { | ||
if (err) return cb(err) | ||
if (!data) return cb() | ||
delete options.prefix; | ||
this.serializer = options.serializer || JSON; | ||
if (options.url) { | ||
options.socket = options.url; | ||
let result | ||
try { | ||
result = this.serializer.parse(data) | ||
} catch (err) { | ||
return cb(err) | ||
} | ||
return cb(null, result) | ||
}) | ||
} | ||
// convert to redis connect params | ||
if (options.client) { | ||
this.client = options.client; | ||
} | ||
else if (options.socket) { | ||
this.client = redis.createClient(options.socket, options); | ||
} | ||
else { | ||
this.client = redis.createClient(options); | ||
} | ||
set(sid, sess, cb = noop) { | ||
let args = [this.prefix + sid] | ||
// logErrors | ||
if(options.logErrors){ | ||
// if options.logErrors is function, allow it to override. else provide default logger. useful for large scale deployment | ||
// which may need to write to a distributed log | ||
if(typeof options.logErrors != 'function'){ | ||
options.logErrors = function (err) { | ||
console.error('Warning: connect-redis reported a client error: ' + err); | ||
}; | ||
let value | ||
try { | ||
value = this.serializer.stringify(sess) | ||
} catch (er) { | ||
return cb(er) | ||
} | ||
this.client.on('error', options.logErrors); | ||
} | ||
args.push(value) | ||
if (options.pass) { | ||
this.client.auth(options.pass, function (err) { | ||
if (err) { | ||
throw err; | ||
} | ||
}); | ||
} | ||
let ttl = 1 | ||
if (!this.disableTTL) { | ||
ttl = this._getTTL(sess) | ||
args.push("EX", ttl) | ||
} | ||
this.ttl = options.ttl; | ||
this.disableTTL = options.disableTTL; | ||
if (options.unref) this.client.unref(); | ||
if ('db' in options) { | ||
if (typeof options.db !== 'number') { | ||
console.error('Warning: connect-redis expects a number for the "db" option'); | ||
if (ttl > 0) { | ||
this.client.set(args, cb) | ||
} else { | ||
// If the resulting TTL is negative we can delete / destroy the key | ||
this.destroy(sid, cb) | ||
} | ||
} | ||
self.client.select(options.db); | ||
self.client.on('connect', function () { | ||
self.client.select(options.db); | ||
}); | ||
touch(sid, sess, cb = noop) { | ||
if (this.disableTouch || this.disableTTL) return cb() | ||
let key = this.prefix + sid | ||
this.client.expire(key, this._getTTL(sess), (err, ret) => { | ||
if (err) return cb(err) | ||
if (ret !== 1) return cb(null, "EXPIRED") | ||
cb(null, "OK") | ||
}) | ||
} | ||
self.client.on('error', function (er) { | ||
debug('Redis returned err', er); | ||
self.emit('disconnect', er); | ||
}); | ||
destroy(sid, cb = noop) { | ||
let key = this.prefix + sid | ||
this.client.del(key, cb) | ||
} | ||
self.client.on('connect', function () { | ||
self.emit('connect'); | ||
}); | ||
} | ||
clear(cb = noop) { | ||
this._getAllKeys((err, keys) => { | ||
if (err) return cb(err) | ||
this.client.del(keys, cb) | ||
}) | ||
} | ||
/** | ||
* Inherit from `Store`. | ||
*/ | ||
length(cb = noop) { | ||
this._getAllKeys((err, keys) => { | ||
if (err) return cb(err) | ||
return cb(null, keys.length) | ||
}) | ||
} | ||
util.inherits(RedisStore, Store); | ||
ids(cb = noop) { | ||
let prefixLen = this.prefix.length | ||
/** | ||
* Attempt to fetch session by the given `sid`. | ||
* | ||
* @param {String} sid | ||
* @param {Function} fn | ||
* @api public | ||
*/ | ||
this._getAllKeys((err, keys) => { | ||
if (err) return cb(err) | ||
keys = keys.map((key) => key.substr(prefixLen)) | ||
return cb(null, keys) | ||
}) | ||
} | ||
RedisStore.prototype.get = function (sid, fn) { | ||
var store = this; | ||
var psid = store.prefix + sid; | ||
if (!fn) fn = noop; | ||
debug('GET "%s"', sid); | ||
all(cb = noop) { | ||
let prefixLen = this.prefix.length | ||
store.client.get(psid, function (er, data) { | ||
if (er) return fn(er); | ||
if (!data) return fn(); | ||
this._getAllKeys((err, keys) => { | ||
if (err) return cb(err) | ||
if (keys.length === 0) return cb(null, []) | ||
var result; | ||
data = data.toString(); | ||
debug('GOT %s', data); | ||
this.client.mget(keys, (err, sessions) => { | ||
if (err) return cb(err) | ||
try { | ||
result = store.serializer.parse(data); | ||
} | ||
catch (er) { | ||
return fn(er); | ||
} | ||
return fn(null, result); | ||
}); | ||
}; | ||
/** | ||
* Commit the given `sess` object associated with the given `sid`. | ||
* | ||
* @param {String} sid | ||
* @param {Session} sess | ||
* @param {Function} fn | ||
* @api public | ||
*/ | ||
RedisStore.prototype.set = function (sid, sess, fn) { | ||
var store = this; | ||
var args = [store.prefix + sid]; | ||
if (!fn) fn = noop; | ||
try { | ||
var jsess = store.serializer.stringify(sess); | ||
let result | ||
try { | ||
result = sessions.reduce((accum, data, index) => { | ||
if (!data) return accum | ||
data = this.serializer.parse(data) | ||
data.id = keys[index].substr(prefixLen) | ||
accum.push(data) | ||
return accum | ||
}, []) | ||
} catch (e) { | ||
err = e | ||
} | ||
return cb(err, result) | ||
}) | ||
}) | ||
} | ||
catch (er) { | ||
return fn(er); | ||
} | ||
args.push(jsess); | ||
if (!store.disableTTL) { | ||
var ttl = getTTL(store, sess); | ||
args.push('EX', ttl); | ||
debug('SET "%s" %s ttl:%s', sid, jsess, ttl); | ||
} else { | ||
debug('SET "%s" %s', sid, jsess); | ||
_getTTL(sess) { | ||
let ttl | ||
if (sess && sess.cookie && sess.cookie.expires) { | ||
let ms = Number(new Date(sess.cookie.expires)) - Date.now() | ||
ttl = Math.ceil(ms / 1000) | ||
} else { | ||
ttl = this.ttl | ||
} | ||
return ttl | ||
} | ||
store.client.set(args, function (er) { | ||
if (er) return fn(er); | ||
debug('SET complete'); | ||
fn.apply(null, arguments); | ||
}); | ||
}; | ||
/** | ||
* Destroy the session associated with the given `sid`. | ||
* | ||
* @param {String} sid | ||
* @api public | ||
*/ | ||
RedisStore.prototype.destroy = function (sid, fn) { | ||
debug('DEL "%s"', sid); | ||
if (Array.isArray(sid)) { | ||
var multi = this.client.multi(); | ||
var prefix = this.prefix; | ||
sid.forEach(function (s) { | ||
multi.del(prefix + s); | ||
}); | ||
multi.exec(fn); | ||
} else { | ||
sid = this.prefix + sid; | ||
this.client.del(sid, fn); | ||
_getAllKeys(cb = noop) { | ||
let pattern = this.prefix + "*" | ||
this._scanKeys({}, 0, pattern, this.scanCount, cb) | ||
} | ||
}; | ||
/** | ||
* Refresh the time-to-live for the session with the given `sid`. | ||
* | ||
* @param {String} sid | ||
* @param {Session} sess | ||
* @param {Function} fn | ||
* @api public | ||
*/ | ||
_scanKeys(keys = {}, cursor, pattern, count, cb = noop) { | ||
let args = [cursor, "match", pattern, "count", count] | ||
this.client.scan(args, (err, data) => { | ||
if (err) return cb(err) | ||
RedisStore.prototype.touch = function (sid, sess, fn) { | ||
var store = this; | ||
var psid = store.prefix + sid; | ||
if (!fn) fn = noop; | ||
if (store.disableTTL) return fn(); | ||
let [nextCursorId, scanKeys] = data | ||
for (let key of scanKeys) { | ||
keys[key] = true | ||
} | ||
var ttl = getTTL(store, sess); | ||
// This can be a string or a number. We check both. | ||
if (Number(nextCursorId) !== 0) { | ||
return this._scanKeys(keys, nextCursorId, pattern, count, cb) | ||
} | ||
debug('EXPIRE "%s" ttl:%s', sid, ttl); | ||
store.client.expire(psid, ttl, function (er) { | ||
if (er) return fn(er); | ||
debug('EXPIRE complete'); | ||
fn.apply(this, arguments); | ||
}); | ||
}; | ||
cb(null, Object.keys(keys)) | ||
}) | ||
} | ||
} | ||
/** | ||
* Fetch all sessions' ids | ||
* | ||
* @param {Function} fn | ||
* @api public | ||
*/ | ||
RedisStore.prototype.ids = function (fn) { | ||
var store = this; | ||
var pattern = store.prefix + '*'; | ||
var prefixLength = store.prefix.length; | ||
if (!fn) fn = noop; | ||
debug('KEYS "%s"', pattern); | ||
store.client.keys(pattern, function (er, keys) { | ||
if (er) return fn(er); | ||
debug('KEYS complete'); | ||
keys = keys.map(function (key) { | ||
return key.substr(prefixLength); | ||
}); | ||
return fn(null, keys); | ||
}); | ||
}; | ||
/** | ||
* Fetch all sessions | ||
* | ||
* @param {Function} fn | ||
* @api public | ||
*/ | ||
RedisStore.prototype.all = function (fn) { | ||
var store = this; | ||
var pattern = store.prefix + '*'; | ||
var prefixLength = store.prefix.length; | ||
if (!fn) fn = noop; | ||
debug('KEYS "%s"', pattern); | ||
store.client.keys(pattern, function (er, keys) { | ||
if (er) return fn(er); | ||
debug('KEYS complete'); | ||
var multi = store.client.multi(); | ||
keys.forEach(function (key) { | ||
multi.get(key); | ||
}); | ||
multi.exec(function (er, sessions) { | ||
if (er) return fn(er); | ||
var result; | ||
try { | ||
result = sessions.map(function (data, index) { | ||
data = data.toString(); | ||
data = store.serializer.parse(data); | ||
data.id = keys[index].substr(prefixLength); | ||
return data; | ||
}); | ||
} catch (er) { | ||
return fn(er); | ||
} | ||
return fn(null, result); | ||
}); | ||
}); | ||
}; | ||
return RedisStore; | ||
}; | ||
return RedisStore | ||
} |
{ | ||
"name": "@sailshq/connect-redis", | ||
"description": "Redis session store for your Sails app.", | ||
"version": "3.2.1", | ||
"version": "6.1.3", | ||
"author": "TJ Holowaychuk <tj@vision-media.ca>", | ||
@@ -13,28 +13,34 @@ "contributors": [ | ||
"type": "git", | ||
"url": "git@github.com:visionmedia/connect-redis.git" | ||
"url": "git@github.com:mikermcneil/connect-redis.git" | ||
}, | ||
"dependencies": { | ||
"debug": "^2.2.0", | ||
"redis": "^2.1.0" | ||
}, | ||
"devDependencies": { | ||
"blue-tape": "^0.1.8", | ||
"bluebird": "^2.3.2", | ||
"eslint": "^1.6.0", | ||
"express-session": "^1.9.1", | ||
"ioredis": "^1.7.5", | ||
"istanbul": "^0.3.2", | ||
"tape": "^4.2.1" | ||
"blue-tape": "^1.0.0", | ||
"eslint": "^7.4.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"express-session": "^1.17.0", | ||
"ioredis": "^4.17.1", | ||
"nyc": "^15.0.1", | ||
"prettier": "^2.0.5", | ||
"redis-mock": "^0.56.3", | ||
"redis-v3": "npm:redis@3", | ||
"redis-v4": "npm:redis@4" | ||
}, | ||
"engines": { | ||
"node": "*" | ||
"node": ">=12" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/visionmedia/connect-redis/issues" | ||
"url": "https://github.com/balderdashy/sails/issues" | ||
}, | ||
"scripts": { | ||
"test": "DEBUG=* istanbul cover tape \"test/*-test.js\"", | ||
"bench": "node bench/redisbench.js", | ||
"lint": "eslint index.js test lib bench" | ||
} | ||
"test": "nyc tape \"test/*-test.js\"", | ||
"lint": "eslint index.js test lib", | ||
"fmt": "prettier --write .", | ||
"fmt-check": "prettier --check ." | ||
}, | ||
"keywords": [ | ||
"connect", | ||
"redis", | ||
"session", | ||
"express" | ||
] | ||
} |
@@ -1,122 +0,177 @@ | ||
var P = require('bluebird'); | ||
var test = require('blue-tape'); | ||
var redisSrv = require('./redis-server'); | ||
var session = require('express-session'); | ||
var RedisStore = require('../')(session); | ||
var redis = require('redis'); | ||
var ioRedis = require('ioredis'); | ||
const test = require("blue-tape") | ||
const redisSrv = require("../test/redis-server") | ||
const session = require("express-session") | ||
const redisV3 = require("redis-v3") | ||
const redisV4 = require("redis-v4") | ||
const ioRedis = require("ioredis") | ||
const redisMock = require("redis-mock") | ||
// Takes a store through all the operations | ||
function lifecycleTest (store, t) { | ||
P.promisifyAll(store); | ||
let RedisStore = require("../")(session) | ||
return redisSrv.connect() | ||
.then(function () { | ||
return store.setAsync('123', { cookie: { maxAge: 2000 }, name: 'tj' }); | ||
let p = | ||
(ctx, method) => | ||
(...args) => | ||
new Promise((resolve, reject) => { | ||
ctx[method](...args, (err, d) => { | ||
if (err) reject(err) | ||
resolve(d) | ||
}) | ||
}) | ||
.then(function (ok) { | ||
t.equal(ok, 'OK', '#set() ok'); | ||
return store.getAsync('123'); | ||
}) | ||
.then(function (data) { | ||
t.deepEqual({ cookie: { maxAge: 2000 }, name: 'tj' }, data, '#get() ok'); | ||
}) | ||
.then(function () { | ||
return store.setAsync('123', { cookie: { maxAge: undefined }, name: 'tj' }); | ||
}) | ||
.then(function (ok) { | ||
t.equal(ok, 'OK', '#set() no maxAge ok'); | ||
return store.destroyAsync('123'); | ||
}) | ||
.then(function (ok) { | ||
t.equal(ok, 1, '#destroy() ok'); | ||
store.client.end(); | ||
return redisSrv.disconnect(); | ||
}); | ||
} | ||
test('defaults', function (t) { | ||
var store = new RedisStore(); | ||
t.equal(store.prefix, 'sess:', 'defaults to sess:'); | ||
t.notOk(store.ttl, 'ttl not set'); | ||
t.notOk(store.disableTTL, 'disableTTL not set'); | ||
t.ok(store.client, 'creates client'); | ||
test("setup", redisSrv.connect) | ||
store.client.end(); | ||
t.end(); | ||
}); | ||
test("defaults", async (t) => { | ||
t.throws(() => new RedisStore(), "client is required") | ||
test('basic', function (t) { | ||
t.throws(RedisStore, TypeError, 'constructor not callable as function'); | ||
var store = new RedisStore({ port: 8543 }); | ||
return lifecycleTest(store, t); | ||
}); | ||
var client = redisV3.createClient(redisSrv.port, "localhost") | ||
var store = new RedisStore({ client }) | ||
test('existing client', function (t) { | ||
var client = redis.createClient(8543, 'localhost'); | ||
var store = new RedisStore({ client: client }); | ||
return lifecycleTest(store, t); | ||
}); | ||
t.equal(store.client, client, "stores client") | ||
t.equal(store.prefix, "sess:", "defaults to sess:") | ||
t.equal(store.ttl, 86400, "defaults to one day") | ||
t.equal(store.scanCount, 100, "defaults SCAN count to 100") | ||
t.equal(store.serializer, JSON, "defaults to JSON serialization") | ||
t.equal(store.disableTouch, false, "defaults to having `touch` enabled") | ||
t.equal(store.disableTTL, false, "defaults to having `ttl` enabled") | ||
client.end(false) | ||
}) | ||
test('io redis client', function (t) { | ||
var client = ioRedis.createClient(8543, 'localhost'); | ||
var store = new RedisStore({ client: client }); | ||
return lifecycleTest(store, t); | ||
}); | ||
test("node_redis v3", async (t) => { | ||
var client = redisV3.createClient(redisSrv.port, "localhost") | ||
var store = new RedisStore({ client }) | ||
await lifecycleTest(store, t) | ||
client.end(false) | ||
}) | ||
test('options', function (t) { | ||
var store = new RedisStore({ | ||
host: 'localhost', | ||
port: 8543, | ||
prefix: 'tobi', | ||
ttl: 1000, | ||
disableTTL: true, | ||
db: 1, | ||
unref: true, | ||
pass: 'secret' | ||
}); | ||
test("node_redis v4", async (t) => { | ||
var client = redisV4.createClient({ | ||
url: `redis://localhost:${redisSrv.port}`, | ||
legacyMode: true, | ||
}) | ||
await client.connect() | ||
var store = new RedisStore({ client }) | ||
await lifecycleTest(store, t) | ||
await client.disconnect() | ||
}) | ||
t.equal(store.prefix, 'tobi', 'uses provided prefix'); | ||
t.equal(store.ttl, 1000, 'ttl set'); | ||
t.ok(store.disableTTL, 'disableTTL set'); | ||
t.ok(store.client, 'creates client'); | ||
t.equal(store.client.address, 'localhost:8543', 'sets host and port'); | ||
test("ioredis", async (t) => { | ||
var client = ioRedis.createClient(redisSrv.port, "localhost") | ||
var store = new RedisStore({ client }) | ||
await lifecycleTest(store, t) | ||
client.disconnect() | ||
}) | ||
var socketStore = new RedisStore({ socket: 'word' }); | ||
t.equal(socketStore.client.address, 'word', 'sets socket address'); | ||
socketStore.client.end(); | ||
test("redis-mock client", async (t) => { | ||
var client = redisMock.createClient() | ||
var store = new RedisStore({ client }) | ||
await lifecycleTest(store, t) | ||
}) | ||
var urlStore = new RedisStore({ url: 'redis://127.0.0.1:8888' }); | ||
t.equal(urlStore.client.address, '127.0.0.1:8888', 'sets url address'); | ||
urlStore.client.end(); | ||
test("teardown", redisSrv.disconnect) | ||
var hostNoPort = new RedisStore({ host: 'host' }); | ||
t.equal(hostNoPort.client.address, 'host:6379', 'sets default port'); | ||
hostNoPort.client.end(); | ||
async function lifecycleTest(store, t) { | ||
let res = await p(store, "set")("123", { foo: "bar" }) | ||
t.equal(res, "OK", "set value") | ||
return lifecycleTest(store, t); | ||
}); | ||
res = await p(store, "get")("123") | ||
t.same(res, { foo: "bar" }, "get value") | ||
test('interups', function (t) { | ||
var store = P.promisifyAll(new RedisStore({ port: 8543, connect_timeout: 500 })); | ||
return store.setAsync('123', { cookie: { maxAge: 2000 }, name: 'tj' }) | ||
.catch(function (er) { | ||
t.ok(/broken/.test(er.message), 'failed connection'); | ||
store.client.end(); | ||
}); | ||
}); | ||
res = await p(store.client, "ttl")("sess:123") | ||
t.ok(res >= 86399, "check one day ttl") | ||
test('serializer', function (t) { | ||
var serializer = { | ||
stringify: function() { return 'XXX'+JSON.stringify.apply(JSON, arguments); }, | ||
parse: function(x) { | ||
t.ok(x.match(/^XXX/)); | ||
return JSON.parse(x.substring(3)); | ||
let ttl = 60 | ||
let expires = new Date(Date.now() + ttl * 1000).toISOString() | ||
res = await p(store, "set")("456", { cookie: { expires } }) | ||
t.equal(res, "OK", "set cookie expires") | ||
res = await p(store.client, "ttl")("sess:456") | ||
t.ok(res <= 60, "check expires ttl") | ||
ttl = 90 | ||
let newExpires = new Date(Date.now() + ttl * 1000).toISOString() | ||
// note: cookie.expires will not be updated on redis (see https://github.com/tj/connect-redis/pull/285) | ||
res = await p(store, "touch")("456", { cookie: { expires: newExpires } }) | ||
t.equal(res, "OK", "set cookie expires touch") | ||
res = await p(store.client, "ttl")("sess:456") | ||
t.ok(res > 60, "check expires ttl touch") | ||
res = await p(store, "length")() | ||
t.equal(res, 2, "stored two keys length") | ||
res = await p(store, "ids")() | ||
res.sort() | ||
t.same(res, ["123", "456"], "stored two keys ids") | ||
res = await p(store, "all")() | ||
res.sort((a, b) => (a.id > b.id ? 1 : -1)) | ||
t.same( | ||
res, | ||
[ | ||
{ id: "123", foo: "bar" }, | ||
{ id: "456", cookie: { expires } }, | ||
], | ||
"stored two keys data" | ||
) | ||
res = await p(store, "destroy")("456") | ||
t.equal(res, 1, "destroyed one") | ||
res = await p(store, "length")() | ||
t.equal(res, 1, "one key remains") | ||
res = await p(store, "clear")() | ||
t.equal(res, 1, "cleared remaining key") | ||
res = await p(store, "length")() | ||
t.equal(res, 0, "no key remains") | ||
let count = 1000 | ||
await load(store, count) | ||
res = await p(store, "length")() | ||
t.equal(res, count, "bulk count") | ||
res = await p(store, "clear")() | ||
t.equal(res, count, "bulk clear") | ||
expires = new Date(Date.now() + ttl * 1000).toISOString() // expires in the future | ||
res = await p(store, "set")("789", { cookie: { expires } }) | ||
t.equal(res, "OK", "set value") | ||
res = await p(store, "length")() | ||
t.equal(res, 1, "one key exists (session 789)") | ||
expires = new Date(Date.now() - ttl * 1000).toISOString() // expires in the past | ||
res = await p(store, "set")("789", { cookie: { expires } }) | ||
t.equal(res, 1, "returns 1 because destroy was invoked") | ||
res = await p(store, "length")() | ||
t.equal(res, 0, "no key remains and that includes session 789") | ||
} | ||
function load(store, count) { | ||
return new Promise((resolve, reject) => { | ||
let set = (sid) => { | ||
store.set( | ||
"s" + sid, | ||
{ | ||
cookie: { expires: new Date(Date.now() + 1000) }, | ||
data: "some data", | ||
}, | ||
(err) => { | ||
if (err) { | ||
return reject(err) | ||
} | ||
if (sid === count) { | ||
return resolve() | ||
} | ||
set(sid + 1) | ||
} | ||
) | ||
} | ||
}; | ||
t.equal(serializer.stringify('UnitTest'), 'XXX"UnitTest"'); | ||
t.equal(serializer.parse(serializer.stringify('UnitTest')), 'UnitTest'); | ||
var store = new RedisStore({ port: 8543, serializer: serializer }); | ||
return lifecycleTest(store, t); | ||
}); | ||
set(1) | ||
}) | ||
} |
@@ -1,21 +0,21 @@ | ||
var P = require('bluebird'); | ||
var spawn = require('child_process').spawn; | ||
var redisSrv; | ||
var port = exports.port = 8543; | ||
const spawn = require("child_process").spawn | ||
const port = (exports.port = 18543) | ||
let redisSrv | ||
exports.connect = function () { | ||
if (redisSrv) return P.resolve(); | ||
exports.connect = () => | ||
new Promise((resolve, reject) => { | ||
redisSrv = spawn("redis-server", ["--port", port, "--loglevel", "notice"], { | ||
stdio: "inherit", | ||
}) | ||
redisSrv = spawn('redis-server', ['--port', port, '--loglevel', 'verbose'], { stdio: 'ignore' }); | ||
return P.delay(1000); | ||
}; | ||
redisSrv.on("error", function (err) { | ||
reject(new Error("Error caught spawning the server:" + err.message)) | ||
}) | ||
setTimeout(resolve, 1500) | ||
}) | ||
exports.disconnect = function () { | ||
if (!redisSrv) return P.resolve(); | ||
return new P(function (res) { | ||
redisSrv.kill(); | ||
redisSrv.once('close', res); | ||
redisSrv = null; | ||
}); | ||
}; | ||
redisSrv.kill("SIGKILL") | ||
return Promise.resolve() | ||
} |
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
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
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
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
0
17798
10
307
3
- Removeddebug@^2.2.0
- Removedredis@^2.1.0
- Removeddebug@2.6.9(transitive)
- Removeddouble-ended-queue@2.1.0-0(transitive)
- Removedms@2.0.0(transitive)
- Removedredis@2.8.0(transitive)
- Removedredis-commands@1.7.0(transitive)
- Removedredis-parser@2.6.0(transitive)