Socket
Socket
Sign inDemoInstall

connect-redis

Package Overview
Dependencies
0
Maintainers
3
Versions
69
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 6.0.0 to 6.1.0

2

index.js

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

module.exports = require('./lib/connect-redis')
module.exports = require("./lib/connect-redis")

@@ -13,2 +13,3 @@ /*!

const noop = () => {}
const TOMBSTONE = "TOMBSTONE"

@@ -19,6 +20,6 @@ class RedisStore extends Store {

if (!options.client) {
throw new Error('A client must be directly provided to the RedisStore')
throw new Error("A client must be directly provided to the RedisStore")
}
this.prefix = options.prefix == null ? 'sess:' : options.prefix
this.prefix = options.prefix == null ? "sess:" : options.prefix
this.scanCount = Number(options.scanCount) || 100

@@ -32,3 +33,3 @@ this.serializer = options.serializer || JSON

get(sid, cb = noop) {
get(sid, cb = noop, showTombs = false) {
let key = this.prefix + sid

@@ -39,2 +40,3 @@

if (!data) return cb()
if (data === TOMBSTONE) return cb(null, showTombs ? data : undefined)

@@ -52,24 +54,36 @@ let result

set(sid, sess, cb = noop) {
let args = [this.prefix + sid]
this.get(
sid,
(err, oldSess) => {
if (oldSess === TOMBSTONE) {
return cb()
} else if (oldSess && oldSess.lastModified !== sess.lastModified) {
sess = mergeDeep(oldSess, sess)
}
let args = [this.prefix + sid]
let value
sess.lastModified = Date.now()
try {
value = this.serializer.stringify(sess)
} catch (er) {
return cb(er)
}
args.push(value)
args.push("EX", this._getTTL(sess))
let value
try {
value = this.serializer.stringify(sess)
} catch (er) {
return cb(er)
}
args.push(value)
let ttl = 1
if (!this.disableTTL) {
ttl = this._getTTL(sess)
args.push("EX", ttl)
}
let ttl = 1
if (!this.disableTTL) {
ttl = this._getTTL(sess)
args.push('EX', ttl)
}
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)
}
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)
}
},
true
)
}

@@ -82,4 +96,4 @@

if (err) return cb(err)
if (ret !== 1) return cb(null, 'EXPIRED')
cb(null, 'OK')
if (ret !== 1) return cb(null, "EXPIRED")
cb(null, "OK")
})

@@ -90,3 +104,5 @@ }

let key = this.prefix + sid
this.client.del(key, cb)
this.client.set([key, TOMBSTONE, "EX", 300], (err) => {
cb(err, 1)
})
}

@@ -102,5 +118,5 @@

length(cb = noop) {
this._getAllKeys((err, keys) => {
this.all((err, result) => {
if (err) return cb(err)
return cb(null, keys.length)
return cb(null, result.length)
})

@@ -132,3 +148,3 @@ }

result = sessions.reduce((accum, data, index) => {
if (!data) return accum
if (!data || data === TOMBSTONE) return accum
data = this.serializer.parse(data)

@@ -159,3 +175,3 @@ data.id = keys[index].substr(prefixLen)

_getAllKeys(cb = noop) {
let pattern = this.prefix + '*'
let pattern = this.prefix + "*"
this._scanKeys({}, 0, pattern, this.scanCount, cb)

@@ -165,3 +181,3 @@ }

_scanKeys(keys = {}, cursor, pattern, count, cb = noop) {
let args = [cursor, 'match', pattern, 'count', count]
let args = [cursor, "match", pattern, "count", count]
this.client.scan(args, (err, data) => {

@@ -187,1 +203,33 @@ if (err) return cb(err)

}
/**
* Simple object check.
* @param item
* @returns {boolean}
*/
function isObject(item) {
return item && typeof item === "object" && !Array.isArray(item)
}
/**
* Deep merge two objects.
* @param target
* @param ...sources
*/
function mergeDeep(target, ...sources) {
if (!sources.length) return target
const source = sources.shift()
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} })
mergeDeep(target[key], source[key])
} else {
Object.assign(target, { [key]: source[key] })
}
}
}
return mergeDeep(target, ...sources)
}
{
"name": "connect-redis",
"description": "Redis session store for Connect",
"version": "6.0.0",
"version": "6.1.0",
"author": "TJ Holowaychuk <tj@vision-media.ca>",

@@ -21,6 +21,8 @@ "contributors": [

"ioredis": "^4.17.1",
"mockdate": "^2.0.5",
"nyc": "^15.0.1",
"prettier": "^2.0.5",
"redis": "^3.1.2",
"redis-mock": "^0.56.3"
"redis-mock": "^0.56.3",
"redis-v3": "npm:redis@3",
"redis-v4": "npm:redis@4"
},

@@ -36,5 +38,5 @@ "engines": {

"lint": "eslint index.js test lib",
"fmt": "prettier --write \"**/*.{js,md,json,*rc}\"",
"fmt-check": "prettier --check \"**/*.{js,md,json,*rc}\""
"fmt": "prettier --write .",
"fmt-check": "prettier --check ."
}
}

@@ -5,4 +5,2 @@ ![Build Status](https://github.com/tj/connect-redis/workflows/build/badge.svg?branch=master) [![npm](https://img.shields.io/npm/v/connect-redis.svg)](https://npmjs.com/package/connect-redis) [![code-style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://gitter.im/jlongster/prettier) ![Downloads](https://img.shields.io/npm/dm/connect-redis.svg)

**Migrating to V4?** See [this guide](migration-to-v4.md) on what's changed.
## Installation

@@ -25,8 +23,18 @@

```js
const redis = require('redis')
const session = require('express-session')
const session = require("express-session")
let RedisStore = require("connect-redis")(session)
let RedisStore = require('connect-redis')(session)
let redisClient = redis.createClient()
// redis@v4
const { createClient } = require("redis")
let redisClient = createClient({ legacyMode: true })
redisClient.connect().catch(console.error)
// redis@v3
const { createClient } = require("redis")
let redisClient = createClient()
// ioredis
const Redis = require("ioredis")
let redisClient = new Redis()
app.use(

@@ -36,3 +44,3 @@ session({

saveUninitialized: false,
secret: 'keyboard cat',
secret: "keyboard cat",
resave: false,

@@ -55,3 +63,3 @@ })

- [redis][1]
- [redis][1] (v3, v4 with `legacyMode: true`)
- [ioredis](https://github.com/luin/ioredis)

@@ -112,3 +120,3 @@ - [redis-mock](https://github.com/yeahoffline/redis-mock) for testing.

```js
client.on('error', console.error)
client.on("error", console.error)
```

@@ -124,3 +132,3 @@

if (!req.session) {
return next(new Error('oh no')) // handle error
return next(new Error("oh no")) // handle error
}

@@ -127,0 +135,0 @@ next() // otherwise continue

@@ -1,9 +0,12 @@

const test = require('blue-tape')
const redisSrv = require('../test/redis-server')
const session = require('express-session')
const redis = require('redis')
const ioRedis = require('ioredis')
const redisMock = require('redis-mock')
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")
const MockDate = require("mockdate")
let RedisStore = require('../')(session)
let RedisStore = require("../")(session)
MockDate.set("2000-11-22")

@@ -20,22 +23,22 @@ let p =

test('setup', redisSrv.connect)
test("setup", redisSrv.connect)
test('defaults', async (t) => {
t.throws(() => new RedisStore(), 'client is required')
test("defaults", async (t) => {
t.throws(() => new RedisStore(), "client is required")
var client = redis.createClient(redisSrv.port, 'localhost')
var client = redisV3.createClient(redisSrv.port, "localhost")
var store = new RedisStore({ client })
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')
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('node_redis', async (t) => {
var client = redis.createClient(redisSrv.port, 'localhost')
test("node_redis v3", async (t) => {
var client = redisV3.createClient(redisSrv.port, "localhost")
var store = new RedisStore({ client })

@@ -46,10 +49,21 @@ await lifecycleTest(store, t)

test('ioredis', async (t) => {
var client = ioRedis.createClient(redisSrv.port, 'localhost')
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()
})
test("ioredis", async (t) => {
var client = ioRedis.createClient(redisSrv.port, "localhost")
var store = new RedisStore({ client })
await lifecycleTest(store, t)
client.disconnect()
})
test('redis-mock client', async (t) => {
test("redis-mock client", async (t) => {
var client = redisMock.createClient()

@@ -60,21 +74,44 @@ var store = new RedisStore({ client })

test('teardown', redisSrv.disconnect)
test("teardown", redisSrv.disconnect)
async function lifecycleTest(store, t) {
let res = await p(store, 'set')('123', { foo: 'bar' })
t.equal(res, 'OK', 'set value')
await p(store, "set")("123", { foo: "bar3" })
let res = await p(store, "get")("123")
t.same(res, { foo: "bar3", lastModified: 974851200000 }, "get value 1")
await p(store, "set")("123", {
foo: "bar3",
luke: "skywalker",
obi: "wan",
lastModified: 974851000000,
})
await p(store, "set")("123", {
luke: "skywalker",
lastModified: 974851000000,
})
res = await p(store, "get")("123")
t.same(
res,
{ foo: "bar3", luke: "skywalker", obi: "wan", lastModified: 974851200000 },
"get merged value"
)
res = await p(store, 'get')('123')
t.same(res, { foo: 'bar' }, 'get value')
res = await p(store, "clear")()
t.ok(res >= 1, "cleared key")
res = await p(store.client, 'ttl')('sess:123')
t.ok(res >= 86399, 'check one day ttl')
res = await p(store, "set")("123", { foo: "bar" })
t.equal(res, "OK", "set value")
res = await p(store, "get")("123")
t.same(res, { foo: "bar", lastModified: 974851200000 }, "get value")
res = await p(store.client, "ttl")("sess:123")
t.ok(res >= 86399, "check one day ttl")
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, "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')
res = await p(store.client, "ttl")("sess:456")
t.ok(res <= 60, "check expires ttl")

@@ -84,16 +121,16 @@ ttl = 90

// 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, "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.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, "length")()
t.equal(res, 2, "stored two keys length")
res = await p(store, 'ids')()
res = await p(store, "ids")()
res.sort()
t.same(res, ['123', '456'], 'stored two keys ids')
t.same(res, ["123", "456"], "stored two keys ids")
res = await p(store, 'all')()
res = await p(store, "all")()
res.sort((a, b) => (a.id > b.id ? 1 : -1))

@@ -103,42 +140,51 @@ t.same(

[
{ id: '123', foo: 'bar' },
{ id: '456', cookie: { expires } },
{ id: "123", foo: "bar", lastModified: 974851200000 },
{ id: "456", cookie: { expires }, lastModified: 974851200000 },
],
'stored two keys data'
"stored two keys data"
)
res = await p(store, 'destroy')('456')
t.equal(res, 1, 'destroyed one')
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, "get")("456")
t.equal(res, undefined, "tombstoned one")
res = await p(store, 'clear')()
t.equal(res, 1, 'cleared remaining key')
res = await p(store, "set")("456", { a: "new hope" })
t.equal(res, undefined, "tombstoned set")
res = await p(store, 'length')()
t.equal(res, 0, 'no key remains')
res = await p(store, "get")("456")
t.equal(res, undefined, "tombstoned two")
res = await p(store, "length")()
t.equal(res, 1, "one key remains")
res = await p(store, "clear")()
t.equal(res, 2, "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, "length")()
t.equal(res, count, "bulk count")
res = await p(store, 'clear')()
t.equal(res, count, 'bulk clear')
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, "set")("789", { cookie: { expires } })
t.equal(res, "OK", "set value")
res = await p(store, 'length')()
t.equal(res, 1, 'one key exists (session 789)')
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, "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')
res = await p(store, "length")()
t.equal(res, 0, "no key remains and that includes session 789")
}

@@ -150,6 +196,6 @@

store.set(
's' + sid,
"s" + sid,
{
cookie: { expires: new Date(Date.now() + 1000) },
data: 'some data',
data: "some data",
},

@@ -156,0 +202,0 @@ (err) => {

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

const spawn = require('child_process').spawn
const spawn = require("child_process").spawn
const port = (exports.port = 18543)

@@ -7,8 +7,8 @@ let redisSrv

new Promise((resolve, reject) => {
redisSrv = spawn('redis-server', ['--port', port, '--loglevel', 'notice'], {
stdio: 'inherit',
redisSrv = spawn("redis-server", ["--port", port, "--loglevel", "notice"], {
stdio: "inherit",
})
redisSrv.on('error', function (err) {
reject(new Error('Error caught spawning the server:' + err.message))
redisSrv.on("error", function (err) {
reject(new Error("Error caught spawning the server:" + err.message))
})

@@ -20,4 +20,4 @@

exports.disconnect = function () {
redisSrv.kill('SIGKILL')
redisSrv.kill("SIGKILL")
return Promise.resolve()
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc