level-session
Advanced tools
Comparing version 0.1.1 to 0.2.0
const genericSession = require('generic-session') | ||
, levelup = require('levelup') | ||
, ttl = require('level-ttl') | ||
, sublevel = require('level-sublevel') | ||
, xtend = require('xtend') | ||
@@ -9,120 +9,131 @@ | ||
, dbkey = function (id, key) { | ||
return id + SEP_CHAR + key | ||
function loadLevel() { | ||
try { | ||
return require('level') | ||
} catch (e) { | ||
try { | ||
return require('levelup') | ||
} catch (e) { | ||
throw new Error('You must install either `level` or `levelup`') | ||
} | ||
} | ||
} | ||
var LevelStore = { | ||
get: function (id, key, expire, callback) { | ||
// brutish but it updates ttl on all entries | ||
this.getAll(id, expire, function (err, data) { | ||
if (err) return callback(err) | ||
callback(null, data[key]) | ||
}) | ||
} | ||
function dbkey (id, key) { | ||
return id + SEP_CHAR + key | ||
} | ||
, getAll: function (id, expire, callback) { | ||
var ret = {} | ||
, batch = [] | ||
function LevelStore (options) { | ||
if (!(this instanceof LevelStore)) | ||
return new LevelStore(options) | ||
this._forEach( | ||
id | ||
, function (key, value) { | ||
ret[key] = JSON.parse(value) | ||
batch.push({ type: 'put', key: dbkey(id, key), value: value }) | ||
} | ||
, function () { | ||
// put them back for the ttl update | ||
this._db.batch( | ||
batch | ||
, xtend(LUP_OPTIONS, { ttl: expire }) | ||
, function (err) { | ||
if (err) return callback(err) | ||
callback(null, ret) | ||
} | ||
) | ||
}.bind(this) | ||
) | ||
} | ||
if (typeof options == 'string') | ||
options = { location: options } | ||
, set: function (id, key, value, expire, callback) { | ||
this.extend(id, expire) | ||
this._db.put( | ||
dbkey(id, key) | ||
, JSON.stringify(value) | ||
, xtend(LUP_OPTIONS, { ttl: expire }) | ||
, callback | ||
) | ||
} | ||
if (!options || (typeof options.location != 'string' && typeof options.db != 'object')) | ||
throw new Error('You must provide a `location` option for your LevelDB store or a LevelUP `db` instance') | ||
, extend: function (id, expire) { | ||
this.getAll(id, expire, function () {}) | ||
} | ||
this._db = options.db || loadLevel()(options.location, { | ||
errorIfExists : false | ||
, createIfMissing : true | ||
, keyEncoding : 'utf8' | ||
, valueEncoding : 'utf8' | ||
}) | ||
, del: function (id, key, expire, callback) { | ||
this.extend(id, expire) | ||
this._db.del( | ||
dbkey(id, key) | ||
, LUP_OPTIONS | ||
, function (err) { | ||
if (err) return callback(err) | ||
this.extend(id, expire) | ||
callback() | ||
}.bind(this) | ||
) | ||
} | ||
this._db = sublevel(this._db) | ||
this._db = ttl(this._db) | ||
this._sessionDb = this._db.sublevel('session') | ||
} | ||
, delAll: function (id, callback) { | ||
var batch = [] | ||
this._forEach( | ||
id | ||
, function (key) { | ||
batch.push({ type: 'del', key: dbkey(id, key) }) | ||
} | ||
, function () { | ||
this._db.batch(batch, LUP_OPTIONS, callback) | ||
}.bind(this) | ||
) | ||
} | ||
LevelStore.prototype.get = function (id, key, expire, callback) { | ||
// brutish but it updates ttl on all entries | ||
this.getAll(id, expire, function (err, data) { | ||
if (err) return callback(err) | ||
callback(null, data[key]) | ||
}) | ||
} | ||
, close: function (callback) { | ||
this._db.close(callback) | ||
} | ||
LevelStore.prototype.getAll = function (id, expire, callback) { | ||
var ret = {} | ||
, keys = [] | ||
, _forEach: function (id, fn, callback) { | ||
var rs = this._db.readStream(xtend(LUP_OPTIONS, { start: id })) | ||
this._forEach( | ||
id | ||
, function (key, value) { | ||
ret[key] = JSON.parse(value) | ||
keys.push(dbkey(id, key)) | ||
} | ||
, function () { | ||
// update the ttl value for each key | ||
this._db.ttl( | ||
keys | ||
, expire | ||
, function (err) { | ||
if (err) return callback(err) | ||
callback(null, ret) | ||
} | ||
) | ||
}.bind(this) | ||
) | ||
} | ||
rs.on('data', function (data) { | ||
var lkey = data.key.split(SEP_CHAR) | ||
if (lkey[0] == id) | ||
fn(lkey[1], data.value) | ||
else if (lkey.length != 2 || lkey[0] > id) | ||
rs.destroy() | ||
}) | ||
.on('end', callback) | ||
} | ||
} | ||
LevelStore.prototype.set = function (id, key, value, expire, callback) { | ||
this.extend(id, expire, function () { | ||
this._sessionDb.put( | ||
dbkey(id, key) | ||
, JSON.stringify(value) | ||
, xtend(LUP_OPTIONS, { ttl: expire }) | ||
, callback | ||
) | ||
}.bind(this)) | ||
} | ||
, create = function (options) { | ||
if (typeof options == 'string') | ||
options = { location: options } | ||
LevelStore.prototype.extend = function (id, expire, callback) { | ||
this.getAll(id, expire, function (err) { callback && callback(err) }) | ||
} | ||
if (!options || (typeof options.location != 'string' && typeof options.db != 'object')) | ||
throw new Error('You must provide a `location` option for your LevelDB store or a LevelUP `db` instance') | ||
LevelStore.prototype.del = function (id, key, expire, callback) { | ||
this.extend(id, expire, function () { | ||
this._sessionDb.del( | ||
dbkey(id, key) | ||
, LUP_OPTIONS | ||
, function (err) { | ||
if (err) return callback(err) | ||
this.extend(id, expire, callback) | ||
}.bind(this) | ||
) | ||
}.bind(this)) | ||
} | ||
var db = options.db || levelup(options.location, { | ||
errorIfExists : false | ||
, createIfMissing : true | ||
, keyEncoding : 'utf8' | ||
, valueEncoding : 'utf8' | ||
}) | ||
, close | ||
LevelStore.prototype.delAll = function (id, callback) { | ||
var batch = [] | ||
this._forEach( | ||
id | ||
, function (key) { | ||
batch.push({ type: 'del', key: dbkey(id, key) }) | ||
} | ||
, function () { | ||
this._sessionDb.batch(batch, LUP_OPTIONS, callback) | ||
}.bind(this) | ||
) | ||
} | ||
db = ttl(db) | ||
close = db.close.bind(db) | ||
db = db.sublevel('session') | ||
db.close = close // close() unimplemented in level-sublevel | ||
LevelStore.prototype.close = function (callback) { | ||
this._db.close(callback) | ||
} | ||
return Object.create(LevelStore, { _db: { value: db } }) | ||
} | ||
LevelStore.prototype._forEach = function (id, fn, callback) { | ||
var rs = this._sessionDb.readStream(xtend(LUP_OPTIONS, { start: id })) | ||
module.exports = create | ||
rs.on('data', function (data) { | ||
var lkey = data.key.split(SEP_CHAR) | ||
if (lkey[0] == id) | ||
fn(lkey[1], data.value) | ||
else if (lkey.length != 2 || lkey[0] > id) | ||
rs.destroy() | ||
}) | ||
.on('end', callback) | ||
} | ||
module.exports = LevelStore |
{ | ||
"name" : "level-session" | ||
, "description" : "A very fast and persistent web server session manager backed by LevelDB" | ||
, "version" : "0.1.1" | ||
, "version" : "0.2.0" | ||
, "homepage" : "https://github.com/rvagg/node-level-session" | ||
@@ -17,15 +17,13 @@ , "authors" : [ | ||
"generic-session" : "~0.0.2" | ||
, "level-ttl" : "~0.0.0" | ||
, "xtend" : "~2.0.3" | ||
, "level-ttl" : "~0.3.0" | ||
, "xtend" : "~2.0.6" | ||
, "level-sublevel" : "~4.7.1" | ||
} | ||
, "peerDependencies": { | ||
"levelup" : "~0.8.0" | ||
} | ||
, "devDependencies" : { | ||
"tap" : "*" | ||
, "levelup" : "~0.8.0" | ||
, "request" : "~2.12.0" | ||
, "cookies" : "~0.3.6" | ||
, "rimraf" : "~2.1.1" | ||
, "async" : "~0.1.22" | ||
, "level" : "*" | ||
, "request" : "*" | ||
, "cookies" : "*" | ||
, "rimraf" : "*" | ||
, "async" : "*" | ||
} | ||
@@ -32,0 +30,0 @@ , "scripts": { |
@@ -11,5 +11,5 @@ # Level Session [![Build Status](https://secure.travis-ci.org/rvagg/node-level-session.png)](http://travis-ci.org/rvagg/node-level-session) | ||
A LevelDB store can only be accessed by one process at a time so Level Session is not ideal for multi-process deployments. | ||
A LevelDB store can only be accessed by one process at a time so Level Session is not ideal for multi-process deployments unless you're passing in a [multilevel](https://github.com/juliangruber/multilevel) instance as your `'db'`. | ||
Level Session uses [LevelUP](https://github.com/rvagg/node-levelup) for LevelDB access in Node.js. | ||
Level Session uses [LevelUP](https://github.com/rvagg/node-levelup) for LevelDB access in Node.js, you must either install **levelup** or **level** from npm for Level Session to work; it is not loaded as a dependency. | ||
@@ -16,0 +16,0 @@ ## Example |
@@ -1,2 +0,2 @@ | ||
const tap = require('tap') | ||
const test = require('tap').test | ||
, rimraf = require('rimraf') | ||
@@ -11,3 +11,3 @@ , async = require('async') | ||
tap.test('basic operations', function (t) { | ||
test('basic operations', function (t) { | ||
var store = levelSession.LevelStore('/tmp/level_store_test.db') | ||
@@ -35,5 +35,3 @@ , session = genericSession(req, res, store) | ||
store.close(function () { | ||
rimraf('/tmp/level_store_test.db', function () { | ||
t.end() | ||
}) | ||
rimraf('/tmp/level_store_test.db', t.end.bind(t)) | ||
}) | ||
@@ -47,3 +45,3 @@ }) | ||
tap.test('set many, getAll(), delAll()', function (t) { | ||
test('set many, getAll(), delAll()', function (t) { | ||
var store = levelSession.LevelStore('/tmp/level_store_test.db') | ||
@@ -100,5 +98,3 @@ , session = genericSession(req, res, store) | ||
store.close(function () { | ||
rimraf('/tmp/level_store_test.db', function () { | ||
t.end() | ||
}) | ||
rimraf('/tmp/level_store_test.db', t.end.bind(t)) | ||
}) | ||
@@ -105,0 +101,0 @@ } |
Sorry, the diff of this file is not supported yet
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
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
518
26638
+ Addedlevel-sublevel@~4.7.1
+ Addedafter@0.8.2(transitive)
+ Addedlevel-sublevel@4.7.1(transitive)
+ Addedlevel-ttl@0.3.0(transitive)
- Removedafter@0.7.0(transitive)
- Removedbindings@1.1.1(transitive)
- Removedconcat-stream@0.1.1(transitive)
- Removederrno@0.0.5(transitive)
- Removedlevel-sublevel@4.6.13(transitive)
- Removedlevel-ttl@0.0.1(transitive)
- Removedleveldown@0.2.4(transitive)
- Removedlevelup@0.8.0(transitive)
- Removedprr@0.0.0(transitive)
- Removedsimple-bufferstream@0.0.4(transitive)
Updatedlevel-ttl@~0.3.0
Updatedxtend@~2.0.6